├── .gitignore
├── src
└── index.js
├── public
└── index.html
├── babel.config.js
├── package.json
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 |
4 | ReactDOM.render(
React App
, document.getElementById("root"));
5 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React App
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------