├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── purgecss.config.js ├── src ├── another-page.html ├── index.html ├── js │ └── index.js ├── public │ ├── icon.ico │ └── images │ │ ├── image_1.jpg │ │ ├── image_2.jpg │ │ └── image_3.jpg └── scss │ ├── carousel.css │ ├── custom.scss │ └── index.scss ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "browsers": ["last 2 versions", "safari >= 7"] 8 | } 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | indent_size = 2 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["eslint:recommended", "prettier", "plugin:no-jquery/deprecated-3.5"], 4 | "globals": { 5 | "chrome": true 6 | }, 7 | "env": { 8 | "browser": true, 9 | "node": true, 10 | "jquery": true 11 | }, 12 | "rules": { 13 | "prettier/prettier": [ 14 | "error", 15 | { 16 | "trailingComma": "es5", 17 | "singleQuote": true 18 | } 19 | ], 20 | "no-console": "off" 21 | }, 22 | "plugins": ["no-jquery", "babel", "prettier"] 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js related files 2 | node_modules/ 3 | dist/ 4 | package-lock.json 5 | 6 | # OS generated files 7 | .DS_Store 8 | .Trashes 9 | Thumbs.db -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 - present Homer Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boostrap + Webpack + JQuery Boilerplate 2 | 3 | > Build landing page with **Boostrap** and **jQuery** is so easy. 4 | 5 | 6 | 7 | 8 | 9 | code style: prettier 10 | 11 | 12 | 13 | ## Why ? 14 | 15 | React is awesome, and I use it everyday. 16 | 17 | However, not each project needs such a complicated library. jQuery and bootstrap are good enough. 18 | 19 | Hence, this repo is suitable for simple projects. 20 | 21 | ## About DOM manipulation, all you need is... 22 | 23 | #### 🤩 jQuery 24 | 25 | #### ❌ No React 26 | 27 | #### ❌ No Vue 28 | 29 | #### ❌ No Angular 30 | 31 | ## About CSS, all you need is... 32 | 33 | #### 🤩 Bootstrap + CSS 34 | 35 | #### ❌ No CSS Modules 36 | 37 | #### ❌ No styled-components 38 | 39 | ## Features 40 | 41 | - **Bootstrap** and **jQuery** installed 42 | - Hot Module Replacement (**HMR**) 43 | - Support **ES6** Syntax (**Babel 7**) 44 | - **ESLint** + **Prettier** = **Neat Coding Style** 45 | - Webpack production building (**code splitting**, **cache**, **lazy-loading** and [**Terser**](https://github.com/terser-js/terser)) 46 | 47 | ## Download and Install 48 | 49 | Let's go! 50 | 51 | ``` 52 | $ git clone https://github.com/xxhomey19/bootstrap-webpack-jquery-boilerplate.git 53 | $ cd bootstrap-webpack-jquery-boilerplate 54 | $ yarn // or npm install 55 | ``` 56 | 57 | ## Development 58 | 59 | Run development page on **localhost:8080** 60 | 61 | ``` 62 | $ npm run dev 63 | ``` 64 | 65 | ## Build 66 | 67 | Build for production. 68 | 69 | ``` 70 | $ npm run build 71 | ``` 72 | 73 | ## Deploy 74 | 75 | Deploy to `gh-pages` branch on GitHub. 76 | 77 | **[DEMO](https://xxhomey19.github.io/bootstrap-webpack-jquery-boilerplate/)** 78 | 79 | ``` 80 | $ npm run deploy 81 | ``` 82 | 83 | ## License 84 | 85 | MIT © [xxhomey19](https://github.com/xxhomey19) 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-webpack-jquery-boilerplate", 3 | "license": "MIT", 4 | "author": "xxhomey19", 5 | "homepage": "https://xxhomey19.github.io/bootstrap-webpack-jquery-boilerplate/", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/xxhomey19/bootstrap-webpack-jquery-boilerplate/tree/master" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/xxhomey19/bootstrap-webpack-jquery-boilerplate/issues" 12 | }, 13 | "version": "1.6.4", 14 | "scripts": { 15 | "build": "webpack -p --progress --mode production --config webpack.config.js", 16 | "predeploy": "npm run build && npm run purge", 17 | "deploy": "gh-pages -d dist", 18 | "dev": "cross-env NODE_ENV=dev webpack-dev-server --open --config webpack.config.js", 19 | "lint": "eslint src/js", 20 | "lint:fix": "npm run lint -- --fix", 21 | "purge": "purgecss --config purgecss.config.js --output dist/css", 22 | "start": "npm run dev" 23 | }, 24 | "dependencies": { 25 | "bootstrap": "^4.3.1", 26 | "jquery": "^3.5.1", 27 | "popper.js": "^1.15.0" 28 | }, 29 | "devDependencies": { 30 | "@babel/core": "^7.4.5", 31 | "@babel/preset-env": "^7.4.5", 32 | "babel-eslint": "^10.0.2", 33 | "babel-loader": "^8.0.6", 34 | "clean-webpack-plugin": "^3.0.0", 35 | "copy-webpack-plugin": "^5.0.3", 36 | "cross-env": "^5.2.0", 37 | "css-loader": "^3.0.0", 38 | "css-url-relative-plugin": "^1.0.0", 39 | "eslint": "^6.0.1", 40 | "eslint-config-prettier": "^6.0.0", 41 | "eslint-plugin-babel": "^5.3.0", 42 | "eslint-plugin-import": "^2.18.0", 43 | "eslint-plugin-jsx-a11y": "^6.2.1", 44 | "eslint-plugin-no-jquery": "^2.4.1", 45 | "eslint-plugin-prettier": "^3.1.0", 46 | "eslint-plugin-react": "^7.14.2", 47 | "file-loader": "^4.0.0", 48 | "gh-pages": "^2.0.1", 49 | "glob": "^7.1.4", 50 | "html-webpack-plugin": "^4.0.0-beta.5", 51 | "husky": "^2.7.0", 52 | "image-webpack-loader": "^5.0.0", 53 | "lint-staged": "^8.2.1", 54 | "mini-css-extract-plugin": "^0.7.0", 55 | "node-sass": "^4.12.0", 56 | "optimize-css-assets-webpack-plugin": "^5.0.3", 57 | "preload-webpack-plugin": "^3.0.0-beta.3", 58 | "prettier": "^1.18.2", 59 | "prettier-package-json": "^2.1.0", 60 | "purgecss": "^3.0.0", 61 | "sass-loader": "^7.1.0", 62 | "terser-webpack-plugin": "^1.3.0", 63 | "url-loader": "^2.0.1", 64 | "webpack": "^4.35.0", 65 | "webpack-cli": "^3.3.5", 66 | "webpack-dev-server": "^3.7.2" 67 | }, 68 | "husky": { 69 | "hooks": { 70 | "pre-commit": "lint-staged" 71 | } 72 | }, 73 | "lint-staged": { 74 | "package.json": [ 75 | "prettier-package-json --write", 76 | "git add" 77 | ], 78 | "*.js": [ 79 | "eslint --fix", 80 | "git add" 81 | ] 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /purgecss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ['dist/**/*.html', 'dist/js/**/*.js'], 3 | css: ['dist/css/**/*.css'], 4 | }; 5 | -------------------------------------------------------------------------------- /src/another-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | Another page 13 | 14 | 15 | 16 |
17 | 58 |
59 | 60 |
61 |
62 |

This is another page

63 |
64 | 65 | 72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | Carousel Template for Bootstrap 13 | 14 | 15 | 16 |
17 | 58 |
59 | 60 |
61 | 154 | 155 | 159 | 162 | 163 |
164 | 165 |
166 |
167 | Generic placeholder image 174 |

Heading

175 |

176 | Donec sed odio dui. Etiam porta sem malesuada magna mollis 177 | euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. 178 | Morbi leo risus, porta ac consectetur ac, vestibulum at eros. 179 | Praesent commodo cursus magna. 180 |

181 |

182 | View details » 185 |

186 |
187 | 188 |
189 | Generic placeholder image 196 |

Heading

197 |

198 | Duis mollis, est non commodo luctus, nisi erat porttitor ligula, 199 | eget lacinia odio sem nec elit. Cras mattis consectetur purus sit 200 | amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor 201 | mauris condimentum nibh. 202 |

203 |

204 | View details » 207 |

208 |
209 | 210 |
211 | Generic placeholder image 218 |

Heading

219 |

220 | Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, 221 | egestas eget quam. Vestibulum id ligula porta felis euismod 222 | semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris 223 | condimentum nibh, ut fermentum massa justo sit amet risus. 224 |

225 |

226 | View details » 229 |

230 |
231 | 232 |
233 | 234 | 235 | 236 | 237 |
238 | 239 |
240 |
241 |

242 | First featurette heading. 243 | It'll blow your mind. 244 |

245 |

246 | Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id 247 | ligula porta felis euismod semper. Praesent commodo cursus magna, 248 | vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus 249 | commodo. 250 |

251 |
252 |
253 | Generic placeholder image 258 |
259 |
260 | 261 |
262 | 263 |
264 |
265 |

266 | Oh yeah, it's that good. 267 | See for yourself. 268 |

269 |

270 | Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id 271 | ligula porta felis euismod semper. Praesent commodo cursus magna, 272 | vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus 273 | commodo. 274 |

275 |
276 |
277 | Generic placeholder image 282 |
283 |
284 | 285 |
286 | 287 |
288 |
289 |

290 | And lastly, this one. Checkmate. 291 |

292 |

293 | Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id 294 | ligula porta felis euismod semper. Praesent commodo cursus magna, 295 | vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus 296 | commodo. 297 |

298 |
299 |
300 | Generic placeholder image 305 |
306 |
307 | 308 |
309 | 310 | 311 |
312 | 313 | 314 | 315 | 322 |
323 | 324 | 325 | -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | import 'bootstrap'; 2 | 3 | import '../scss/index.scss'; 4 | 5 | $('#alert').on('click', () => { 6 | alert('jQuery works!'); 7 | }); 8 | 9 | // Your jQuery code 10 | -------------------------------------------------------------------------------- /src/public/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/homerchen19/bootstrap-webpack-jquery-boilerplate/505796277391e863afab58b6570fe88ad04c5646/src/public/icon.ico -------------------------------------------------------------------------------- /src/public/images/image_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/homerchen19/bootstrap-webpack-jquery-boilerplate/505796277391e863afab58b6570fe88ad04c5646/src/public/images/image_1.jpg -------------------------------------------------------------------------------- /src/public/images/image_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/homerchen19/bootstrap-webpack-jquery-boilerplate/505796277391e863afab58b6570fe88ad04c5646/src/public/images/image_2.jpg -------------------------------------------------------------------------------- /src/public/images/image_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/homerchen19/bootstrap-webpack-jquery-boilerplate/505796277391e863afab58b6570fe88ad04c5646/src/public/images/image_3.jpg -------------------------------------------------------------------------------- /src/scss/carousel.css: -------------------------------------------------------------------------------- 1 | /* GLOBAL STYLES 2 | -------------------------------------------------- */ 3 | /* Padding below the footer and lighter body text */ 4 | 5 | body { 6 | padding-top: 3rem; 7 | padding-bottom: 3rem; 8 | color: #5a5a5a; 9 | } 10 | 11 | /* CUSTOMIZE THE CAROUSEL 12 | -------------------------------------------------- */ 13 | 14 | /* Carousel base class */ 15 | .carousel { 16 | margin-bottom: 4rem; 17 | } 18 | /* Since positioning the image, we need to help out the caption */ 19 | .carousel-caption { 20 | bottom: 3rem; 21 | z-index: 10; 22 | } 23 | 24 | /* Declare heights because of positioning of img element */ 25 | .carousel-item { 26 | height: 32rem; 27 | background-color: #777; 28 | } 29 | .carousel-item > img { 30 | position: absolute; 31 | top: 0; 32 | left: 0; 33 | min-width: 100%; 34 | height: 32rem; 35 | object-fit: cover; 36 | } 37 | 38 | /* MARKETING CONTENT 39 | -------------------------------------------------- */ 40 | 41 | /* Center align the text within the three columns below the carousel */ 42 | .marketing .col-lg-4 { 43 | margin-bottom: 1.5rem; 44 | text-align: center; 45 | } 46 | .marketing h2 { 47 | font-weight: 400; 48 | } 49 | .marketing .col-lg-4 p { 50 | margin-right: 0.75rem; 51 | margin-left: 0.75rem; 52 | } 53 | 54 | /* Featurettes 55 | ------------------------- */ 56 | 57 | .featurette-divider { 58 | margin: 5rem 0; /* Space out the Bootstrap
more */ 59 | } 60 | 61 | /* Thin out the marketing headings */ 62 | .featurette-heading { 63 | font-weight: 300; 64 | line-height: 1; 65 | letter-spacing: -0.05rem; 66 | } 67 | 68 | /* RESPONSIVE CSS 69 | -------------------------------------------------- */ 70 | 71 | @media (min-width: 40em) { 72 | /* Bump up size of carousel content */ 73 | .carousel-caption p { 74 | margin-bottom: 1.25rem; 75 | font-size: 1.25rem; 76 | line-height: 1.4; 77 | } 78 | 79 | .featurette-heading { 80 | font-size: 50px; 81 | } 82 | } 83 | 84 | @media (min-width: 62em) { 85 | .featurette-heading { 86 | margin-top: 7rem; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/scss/custom.scss: -------------------------------------------------------------------------------- 1 | @import './carousel.css'; 2 | 3 | // Your customize CSS 4 | -------------------------------------------------------------------------------- /src/scss/index.scss: -------------------------------------------------------------------------------- 1 | @import '../../node_modules/bootstrap/scss/bootstrap'; 2 | @import './custom.scss'; 3 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebPackPlugin = require('html-webpack-plugin'); 4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 5 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 7 | const PreloadWebpackPlugin = require('preload-webpack-plugin'); 8 | const CssUrlRelativePlugin = require('css-url-relative-plugin'); 9 | const glob = require('glob'); 10 | 11 | const IS_DEV = process.env.NODE_ENV === 'dev'; 12 | 13 | const config = { 14 | mode: IS_DEV ? 'development' : 'production', 15 | devtool: IS_DEV ? 'eval' : 'source-map', 16 | entry: './src/js/index.js', 17 | output: { 18 | filename: 'js/[name].[hash].js', 19 | path: path.resolve(__dirname, 'dist'), 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /\.js$/, 25 | exclude: /node_modules/, 26 | loader: 'babel-loader', 27 | }, 28 | { 29 | test: /\.scss$/, 30 | use: [ 31 | { 32 | loader: MiniCssExtractPlugin.loader, 33 | options: { 34 | hmr: IS_DEV, 35 | }, 36 | }, 37 | 'css-loader', 38 | 'sass-loader', 39 | ], 40 | }, 41 | { 42 | test: /\.(gif|png|jpe?g|svg)$/i, 43 | use: [ 44 | { 45 | loader: 'url-loader', 46 | options: { 47 | limit: 8192, 48 | name: '[name].[ext]', 49 | fallback: 'file-loader', 50 | outputPath: 'public/images', 51 | }, 52 | }, 53 | { 54 | loader: 'image-webpack-loader', 55 | options: { 56 | mozjpeg: { 57 | progressive: true, 58 | quality: 65, 59 | }, 60 | pngquant: { 61 | quality: '65-90', 62 | speed: 4, 63 | }, 64 | gifsicle: { 65 | interlaced: false, 66 | }, 67 | webp: { 68 | quality: 75, 69 | }, 70 | }, 71 | }, 72 | ], 73 | }, 74 | ], 75 | }, 76 | plugins: [ 77 | new CleanWebpackPlugin(), 78 | new webpack.ProvidePlugin({ 79 | $: 'jquery', 80 | jQuery: 'jquery', 81 | 'window.jQuery': 'jquery', 82 | }), 83 | new CopyWebpackPlugin([ 84 | { 85 | from: './src/public', 86 | to: 'public', 87 | }, 88 | ]), 89 | new MiniCssExtractPlugin({ 90 | filename: IS_DEV ? 'css/[name].css' : 'css/[name].[contenthash].css', 91 | chunkFilename: 'css/[id].css', 92 | }), 93 | new webpack.HashedModuleIdsPlugin(), 94 | new PreloadWebpackPlugin({ 95 | include: 'initial', 96 | }), 97 | new CssUrlRelativePlugin(), 98 | ], 99 | devServer: { 100 | contentBase: path.join(__dirname, 'src'), 101 | }, 102 | optimization: { 103 | runtimeChunk: 'single', 104 | splitChunks: { 105 | cacheGroups: { 106 | vendor: { 107 | test: /node_modules/, 108 | chunks: 'initial', 109 | name: 'vendor', 110 | priority: 10, 111 | enforce: true, 112 | }, 113 | }, 114 | }, 115 | minimizer: [], 116 | }, 117 | }; 118 | 119 | if (!IS_DEV) { 120 | const TerserPlugin = require('terser-webpack-plugin'); 121 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); 122 | 123 | config.optimization.minimizer.push( 124 | new TerserPlugin(), 125 | new OptimizeCSSAssetsPlugin({}) 126 | ); 127 | } 128 | 129 | const files = glob.sync('./src/*.html'); 130 | 131 | files.forEach(file => { 132 | config.plugins.push( 133 | new HtmlWebPackPlugin({ 134 | filename: path.basename(file), 135 | template: file, 136 | favicon: path.resolve(__dirname, './src/public/icon.ico'), 137 | minify: !IS_DEV, 138 | }) 139 | ); 140 | }); 141 | 142 | module.exports = config; 143 | --------------------------------------------------------------------------------