├── .babelrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── config ├── paths.js ├── webpack.common.js ├── webpack.dev.js └── webpack.prod.js ├── package.json ├── public └── index.html ├── src ├── App.js ├── app.styles.scss ├── assets │ └── icons │ │ └── favicon.png ├── index.js └── index.scss └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ "@babel/preset-env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": [ 7 | "last 2 Chrome versions", 8 | "last 2 Firefox versions", 9 | "last 2 Safari versions", 10 | "last 2 iOS versions", 11 | "last 1 Android version", 12 | "last 1 ChromeAndroid version", 13 | "ie 11" 14 | ] 15 | } 16 | } ], 17 | "@babel/preset-react" 18 | ], 19 | "plugins": [ "@babel/plugin-proposal-class-properties" ] 20 | } -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es6: true, 5 | node: true, 6 | }, 7 | parser: "babel-eslint", 8 | extends: [ 9 | "eslint:recommended", 10 | "plugin:react/recommended", 11 | "prettier", 12 | "prettier/react", 13 | ], 14 | parserOptions: { 15 | ecmaVersion: "2017", 16 | ecmaFeatures: { 17 | experimentalObjectRestSpread: true, 18 | jsx: true, 19 | }, 20 | sourceType: "module", 21 | }, 22 | plugins: ["babel", "react", "import", "prettier"], 23 | rules: { 24 | "import/no-duplicates": "error", 25 | "import/no-unresolved": "error", 26 | "import/named": "error", 27 | "prettier/prettier": "error", 28 | "react/no-typos": "error", 29 | "react/no-unused-state": "error", 30 | "react/jsx-no-bind": "error", 31 | "array-callback-return": "error", 32 | "consistent-return": "error", 33 | "babel/no-invalid-this": "error", 34 | "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 35 | }, 36 | settings: { 37 | react: { 38 | pragma: "React", 39 | version: "15.0", 40 | flowVersion: "0.63.1", 41 | }, 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | stats.json 4 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack5-react-boilerplate 2 | 3 | Webpack 5 boilerplate for react using babel, sass, with a hot dev server and an optimized production build.Configured with eslint rules. 4 | 5 | ## Installation 6 | 7 | ``` 8 | git clone https://github.com/miami78/webpack5-react-boilerplate.git 9 | cd webpack5-react-boilerplate 10 | yarn / npm i 11 | ``` 12 | 13 | ## Usage 14 | 15 | ### Development server 16 | 17 | ```bash 18 | yarn start / npm start 19 | ``` 20 | 21 | You can view the development server at `localhost:8080`. 22 | 23 | ### Production build 24 | 25 | ```bash 26 | yarn build / npm run build 27 | ``` 28 | 29 | ## Features 30 | 31 | - [webpack](https://webpack.js.org/) 32 | - [Babel](https://babeljs.io/) 33 | - [Sass](https://sass-lang.com/) 34 | - [Eslint](https://eslint.org/) 35 | 36 | ## Dependencies 37 | 38 | ### webpack 39 | 40 | - [`webpack`](https://github.com/webpack/webpack) - Module and asset bundler. 41 | - [`webpack-cli`](https://github.com/webpack/webpack-cli) - Command line interface for webpack 42 | - [`webpack-dev-server`](https://github.com/webpack/webpack-dev-server) - Development server for webpack 43 | - [`webpack-merge`](https://github.com/survivejs/webpack-merge) - Simplify development/production configuration 44 | - [`cross-env`](https://github.com/kentcdodds/cross-env) - Cross platform configuration 45 | 46 | ### Babel 47 | 48 | - [`@babel/core`](https://www.npmjs.com/package/@babel/core) - Transpile ES6+ to backwards compatible JavaScript 49 | - [`@babel/plugin-proposal-class-properties`](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) - Use properties directly on a class (an example Babel config) 50 | - [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env) - Smart defaults for Babel 51 | 52 | ### Loaders 53 | 54 | - [`babel-loader`](https://webpack.js.org/loaders/babel-loader/) - Transpile files with Babel and webpack 55 | - [`sass-loader`](https://webpack.js.org/loaders/sass-loader/) - Load SCSS and compile to CSS 56 | - [`node-sass`](https://github.com/sass/node-sass) - Node Sass 57 | - [`css-loader`](https://webpack.js.org/loaders/css-loader/) - Resolve CSS imports 58 | - [`style-loader`](https://webpack.js.org/loaders/style-loader/) - Inject CSS into the DOM 59 | 60 | ### Eslint 61 | - [`eslint-config-prettier`](https://www.npmjs.com/package/eslint-config-prettier) - Turns off all rules that are unnecessary or might conflict with Prettier. 62 | - [`eslint-import-resolver-alias`](https://www.npmjs.com/package/eslint-import-resolver-alias) - a simple Node behavior import resolution plugin for eslint-plugin-import, supporting module alias. 63 | - [`eslint-plugin-babel`](https://www.npmjs.com/package/eslint-plugin-babel) - an eslint rule plugin companion to babel-eslint. 64 | - [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import) - This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, and prevent issues with misspelling of file paths and import names. 65 | - [`eslint-plugin-prettier`](https://www.npmjs.com/package/eslint-plugin-prettier) - Runs prettier as an eslint rule. 66 | - [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react) - React specific linting rules for ESLint. 67 | 68 | 69 | ### Plugins 70 | 71 | - [`clean-webpack-plugin`](https://github.com/johnagan/clean-webpack-plugin) - Remove/clean build folders 72 | - [`copy-webpack-plugin`](https://github.com/webpack-contrib/copy-webpack-plugin) - Copy files to build directory 73 | - [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin) - Generate HTML files from template 74 | - [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin) - Extract CSS into separate files 75 | - [`optimize-css-assets-webpack-plugin`](https://github.com/NMFR/optimize-css-assets-webpack-plugin) - Optimize and minimize CSS assets 76 | - [`terser-webpack-plugin`](https://github.com/webpack-contrib/terser-webpack-plugin) - Optimize and minimize JavaScript -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | // Source files 5 | src: path.resolve(__dirname, "../src"), 6 | 7 | // Production build files 8 | build: path.resolve(__dirname, "../dist"), 9 | 10 | // Static files that get copied to build folder 11 | public: path.resolve(__dirname, "../public"), 12 | }; 13 | -------------------------------------------------------------------------------- /config/webpack.common.js: -------------------------------------------------------------------------------- 1 | const paths = require("./paths"); 2 | 3 | const { CleanWebpackPlugin } = require("clean-webpack-plugin"); 4 | const CopyWebpackPlugin = require("copy-webpack-plugin"); 5 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 6 | 7 | module.exports = { 8 | // Where webpack looks to start building the bundle 9 | entry: [paths.src + "/index.js"], 10 | 11 | // Where webpack outputs the assets and bundles 12 | output: { 13 | path: paths.build, 14 | filename: "[name].bundle.js", 15 | publicPath: "/", 16 | }, 17 | 18 | // Customize the webpack build process 19 | plugins: [ 20 | // Removes/cleans build folders and unused assets when rebuilding 21 | new CleanWebpackPlugin(), 22 | 23 | // Copies files from target to destination folder 24 | new CopyWebpackPlugin({ 25 | patterns: [ 26 | { 27 | from: paths.src + "/assets", 28 | to: "assets", 29 | globOptions: { 30 | ignore: ["*.DS_Store"], 31 | }, 32 | }, 33 | ], 34 | }), 35 | 36 | // Generates an HTML file from a template 37 | // Generates deprecation warning: https://github.com/jantimon/html-webpack-plugin/issues/1501 38 | new HtmlWebpackPlugin({ 39 | title: "National Missing and Unidentified Persons Kenya", 40 | favicon: paths.src + "/assets/icons/favicon.png", 41 | template: paths.public + "/index.html", // template file 42 | filename: "index.html", // output file 43 | }), 44 | ], 45 | 46 | // Determine how modules within the project are treated 47 | module: { 48 | rules: [ 49 | // JavaScript: Use Babel to transpile JavaScript files 50 | { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ["babel-loader"] }, 51 | 52 | // Styles: Inject CSS into the head with source maps 53 | { 54 | test: /\.(scss|css)$/, 55 | use: [ 56 | "style-loader", 57 | { 58 | loader: "css-loader", 59 | options: { sourceMap: true, importLoaders: 1 }, 60 | }, 61 | { loader: "sass-loader", options: { sourceMap: true } }, 62 | ], 63 | }, 64 | 65 | // Images: Copy image files to build folder 66 | { test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: "asset/resource" }, 67 | 68 | // Fonts and SVGs: Inline files 69 | { test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: "asset/inline" }, 70 | ], 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /config/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const paths = require("./paths"); 2 | 3 | const webpack = require("webpack"); 4 | const { merge } = require("webpack-merge"); 5 | const common = require("./webpack.common.js"); 6 | 7 | module.exports = merge(common, { 8 | // Set the mode to development or production 9 | mode: "development", 10 | 11 | // Control how source maps are generated 12 | devtool: "inline-source-map", 13 | 14 | // Spin up a server for quick development 15 | devServer: { 16 | historyApiFallback: true, 17 | contentBase: paths.build, 18 | open: true, 19 | compress: true, 20 | hot: true, 21 | port: 8080, 22 | }, 23 | 24 | plugins: [ 25 | // Only update what has changed on hot reload 26 | new webpack.HotModuleReplacementPlugin(), 27 | ], 28 | }); 29 | -------------------------------------------------------------------------------- /config/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const paths = require("./paths"); 2 | const { merge } = require("webpack-merge"); 3 | const common = require("./webpack.common.js"); 4 | 5 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 6 | const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 7 | const TerserPlugin = require("terser-webpack-plugin"); 8 | 9 | module.exports = merge(common, { 10 | mode: "production", 11 | devtool: false, 12 | output: { 13 | path: paths.build, 14 | publicPath: "/", 15 | filename: "js/[name].[contenthash].bundle.js", 16 | }, 17 | plugins: [ 18 | // Extracts CSS into separate files 19 | // Note: style-loader is for development, MiniCssExtractPlugin is for production 20 | new MiniCssExtractPlugin({ 21 | filename: "styles/[name].[contenthash].css", 22 | chunkFilename: "[id].css", 23 | }), 24 | ], 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.(scss|css)$/, 29 | use: [ 30 | MiniCssExtractPlugin.loader, 31 | { 32 | loader: "css-loader", 33 | options: { 34 | importLoaders: 2, 35 | sourceMap: false, 36 | }, 37 | }, 38 | "sass-loader", 39 | ], 40 | }, 41 | ], 42 | }, 43 | optimization: { 44 | minimize: true, 45 | minimizer: [new OptimizeCssAssetsPlugin(), new TerserPlugin()], 46 | // Once your build outputs multiple chunks, this option will ensure they share the webpack runtime 47 | // instead of having their own. This also helps with long-term caching, since the chunks will only 48 | // change when actual code changes, not the webpack runtime. 49 | runtimeChunk: { 50 | name: "runtime", 51 | }, 52 | }, 53 | performance: { 54 | hints: false, 55 | maxEntrypointSize: 512000, 56 | maxAssetSize: 512000, 57 | }, 58 | }); 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "namup-ke", 3 | "version": "1.0.0", 4 | "description": "National Missing and Unidentified Persons Kenya", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "cross-env NODE_ENV=development webpack serve --config config/webpack.dev.js", 8 | "build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.js", 9 | "lint": "eslint src --ext .jsx --ext .js", 10 | "predeploy": "npm run build", 11 | "deploy": "gh-pages -d dist" 12 | }, 13 | "keywords": [], 14 | "author": "Larry Miami", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@babel/core": "^7.12.1", 18 | "@babel/plugin-proposal-class-properties": "^7.12.1", 19 | "@babel/preset-env": "^7.12.1", 20 | "@babel/preset-react": "^7.12.1", 21 | "babel-eslint": "^10.1.0", 22 | "babel-loader": "^8.1.0", 23 | "clean-webpack-plugin": "^3.0.0", 24 | "copy-webpack-plugin": "^6.2.1", 25 | "cross-env": "^7.0.2", 26 | "css-loader": "^5.0.0", 27 | "css-minimizer-webpack-plugin": "^1.1.5", 28 | "eslint": "^7.11.0", 29 | "eslint-config-prettier": "^6.12.0", 30 | "eslint-import-resolver-alias": "^1.1.2", 31 | "eslint-plugin-babel": "^5.3.1", 32 | "eslint-plugin-import": "^2.22.1", 33 | "eslint-plugin-prettier": "^3.1.4", 34 | "eslint-plugin-react": "^7.21.2", 35 | "html-webpack-plugin": "^4.5.0", 36 | "node-sass": "^4.14.1", 37 | "optimize-css-assets-webpack-plugin": "^5.0.4", 38 | "prettier": "^2.1.2", 39 | "sass-loader": "^10.0.3", 40 | "style-loader": "^2.0.0", 41 | "terser-webpack-plugin": "^4.2.3", 42 | "webpack": "^5.1.2", 43 | "webpack-cli": "^4.0.0", 44 | "webpack-dev-server": "^3.11.0", 45 | "webpack-merge": "^5.2.0" 46 | }, 47 | "dependencies": { 48 | "react": "^16.14.0", 49 | "react-dom": "^16.14.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |