├── .gitignore ├── babel.config.js ├── package.json ├── public └── index.html ├── src └── index.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | modules: false 7 | } 8 | ], 9 | "@babel/preset-react" 10 | ], 11 | plugins: [ 12 | "@babel/plugin-transform-runtime", 13 | "@babel/plugin-syntax-dynamic-import", 14 | "@babel/plugin-proposal-class-properties" 15 | ], 16 | env: { 17 | production: { 18 | only: ["src"], 19 | plugins: [ 20 | [ 21 | "transform-react-remove-prop-types", 22 | { 23 | removeImport: true 24 | } 25 | ], 26 | "@babel/plugin-transform-react-inline-elements", 27 | "@babel/plugin-transform-react-constant-elements" 28 | ] 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-react", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Michael Pontus ", 6 | "license": "MIT", 7 | "scripts": { 8 | "build": "webpack --mode production", 9 | "start": "webpack-dev-server --mode development" 10 | }, 11 | "dependencies": { 12 | "react": "^16.9.0", 13 | "react-dom": "^16.9.0" 14 | }, 15 | "devDependencies": { 16 | "@babel/core": "^7.6.0", 17 | "@babel/plugin-proposal-class-properties": "^7.5.5", 18 | "@babel/plugin-syntax-dynamic-import": "^7.2.0", 19 | "@babel/plugin-transform-react-constant-elements": "^7.6.0", 20 | "@babel/plugin-transform-react-inline-elements": "^7.2.0", 21 | "@babel/plugin-transform-runtime": "^7.6.0", 22 | "@babel/preset-env": "^7.6.0", 23 | "@babel/preset-react": "^7.0.0", 24 | "@babel/runtime": "^7.6.0", 25 | "@svgr/webpack": "^4.3.2", 26 | "babel-loader": "^8.0.6", 27 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 28 | "css-loader": "^3.2.0", 29 | "file-loader": "^4.2.0", 30 | "html-webpack-plugin": "^3.2.0", 31 | "mini-css-extract-plugin": "^0.8.0", 32 | "optimize-css-assets-webpack-plugin": "^5.0.3", 33 | "style-loader": "^1.0.0", 34 | "terser-webpack-plugin": "^2.1.0", 35 | "url-loader": "^2.1.0", 36 | "webpack": "^4.40.2", 37 | "webpack-cli": "^3.3.9", 38 | "webpack-dev-server": "^3.8.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React App 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | ReactDOM.render(

React App

, document.getElementById("root")); 5 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const webpack = require("webpack"); 5 | const TerserWebpackPlugin = require("terser-webpack-plugin"); 6 | const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 7 | 8 | module.exports = function(_env, argv) { 9 | const isProduction = argv.mode === "production"; 10 | const isDevelopment = !isProduction; 11 | 12 | return { 13 | devtool: isDevelopment && "cheap-module-source-map", 14 | entry: "./src/index.js", 15 | output: { 16 | path: path.resolve(__dirname, "dist"), 17 | filename: "assets/js/[name].[contenthash:8].js", 18 | publicPath: "/" 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.jsx?$/, 24 | exclude: /node_modules/, 25 | use: { 26 | loader: "babel-loader", 27 | options: { 28 | cacheDirectory: true, 29 | cacheCompression: false, 30 | envName: isProduction ? "production" : "development" 31 | } 32 | } 33 | }, 34 | { 35 | test: /\.css$/, 36 | use: [ 37 | isProduction ? MiniCssExtractPlugin.loader : "style-loader", 38 | "css-loader" 39 | ] 40 | }, 41 | { 42 | test: /\.(png|jpg|gif)$/i, 43 | use: { 44 | loader: "url-loader", 45 | options: { 46 | limit: 8192, 47 | name: "static/media/[name].[hash:8].[ext]" 48 | } 49 | } 50 | }, 51 | { 52 | test: /\.svg$/, 53 | use: ["@svgr/webpack"] 54 | }, 55 | { 56 | test: /\.(eot|otf|ttf|woff|woff2)$/, 57 | loader: require.resolve("file-loader"), 58 | options: { 59 | name: "static/media/[name].[hash:8].[ext]" 60 | } 61 | } 62 | ] 63 | }, 64 | resolve: { 65 | extensions: [".js", ".jsx"] 66 | }, 67 | plugins: [ 68 | isProduction && 69 | new MiniCssExtractPlugin({ 70 | filename: "assets/css/[name].[contenthash:8].css", 71 | chunkFilename: "assets/css/[name].[contenthash:8].chunk.css" 72 | }), 73 | new HtmlWebpackPlugin({ 74 | template: path.resolve(__dirname, "public/index.html"), 75 | inject: true 76 | }), 77 | new webpack.DefinePlugin({ 78 | "process.env.NODE_ENV": JSON.stringify( 79 | isProduction ? "production" : "development" 80 | ) 81 | }) 82 | ].filter(Boolean), 83 | optimization: { 84 | minimize: isProduction, 85 | minimizer: [ 86 | new TerserWebpackPlugin({ 87 | terserOptions: { 88 | compress: { 89 | comparisons: false 90 | }, 91 | mangle: { 92 | safari10: true 93 | }, 94 | output: { 95 | comments: false, 96 | ascii_only: true 97 | }, 98 | warnings: false 99 | } 100 | }), 101 | new OptimizeCssAssetsPlugin() 102 | ], 103 | splitChunks: { 104 | chunks: "all", 105 | minSize: 0, 106 | maxInitialRequests: 10, 107 | maxAsyncRequests: 10, 108 | cacheGroups: { 109 | vendors: { 110 | test: /[\\/]node_modules[\\/]/, 111 | name(module, chunks, cacheGroupKey) { 112 | const packageName = module.context.match( 113 | /[\\/]node_modules[\\/](.*?)([\\/]|$)/ 114 | )[1]; 115 | return `${cacheGroupKey}.${packageName.replace("@", "")}`; 116 | } 117 | }, 118 | common: { 119 | minChunks: 2, 120 | priority: -10 121 | } 122 | } 123 | }, 124 | runtimeChunk: "single" 125 | }, 126 | devServer: { 127 | compress: true, 128 | historyApiFallback: true, 129 | open: true, 130 | overlay: true 131 | } 132 | }; 133 | }; 134 | --------------------------------------------------------------------------------