Home > Enterprise >  Hot reloading not working on React project with Webpack 5
Hot reloading not working on React project with Webpack 5

Time:11-18

When I save my changes, the whole app is re-rendered and not only the changes that I have made.

I have tried adding target: "web" to my devServer and also tried the following guides:

Unfortunately, none seems to be working.

Here is the webpack.config.js file:

require('dotenv').config({ path: './.env' });
const path = require('path');
const DotenvWebpack = require('dotenv-webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = (env, options) => {
    const isDevMode = options.mode === 'development';
    const title = process.env.APP_TITLE_OVERRIDE || 'My Cute App';

    return {
        devtool: isDevMode ? 'source-map' : false,
        resolve: {
            extensions: ['.ts', '.tsx', '.js'],
            plugins: [
                new TsconfigPathsPlugin({
                    /* options: see below */
                })
            ],
            fallback: {
                path: require.resolve('path-browserify')
            }
        },
        entry: ['./src'],
        output: {
            path: path.resolve(__dirname, 'dist'),
            publicPath: '/',
            filename: isDevMode ? 'bundle.js' : '[name].[chunkhash:10].js',
            chunkFilename: isDevMode ? '[name].bundle.js' : '[name].[chunkhash:10].js'
        },
        optimization: {
            usedExports: true,
            innerGraph: true,
            sideEffects: true
        },
        module: {
            rules: [
                {
                    test: /\.(ts|js)x?$/,
                    exclude: /node_modules/,
                    use: [
                        {
                            loader: 'babel-loader'
                        }
                    ]
                },
                {
                    test: /\.(sa|sc|c)ss$/,
                    use: [
                        'style-loader',
                        {
                            loader: 'css-loader',
                            options: {
                                sourceMap: isDevMode
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: isDevMode
                            }
                        }
                    ]
                },
                {
                    test: /\.(ttf|eot|woff|woff2)$/,
                    use: {
                        loader: 'file-loader',
                        options: {
                            name: 'fonts/[name].[ext]'
                        }
                    }
                },
                {
                    test: /\.(jpe?g|png|gif|svg|ico)$/i,
                    loader: 'file-loader'
                }
            ]
        },
        devServer: {
            historyApiFallback: true
        },
        plugins: [
            new CleanWebpackPlugin(),
            new HtmlWebpackPlugin({
                title,
                meta: {
                    viewport:
                        'width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1'
                }
            }),
            new DotenvWebpack({
                path: './.env',
                systemvars: !isDevMode
            })
        ]
    };
};

Here is the package.json file :

{
    "name": "my-cute-app",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "engines": {
        "node": "16.18.0"
    },
    "scripts": {
        "build": "cross-env NODE_ENV=production webpack --mode production",
        "start": "concurrently \"nodemon ./server/index.tsx\" \"webpack serve --mode production\"",
        "client": "webpack serve --mode development --open",
        "server": "nodemon ./server",
        "dev": "concurrently \"npm run server\" \"npm run client\"",
        "cy-test": "npx cypress open"
    },
    "author": "Moty",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.19.6",
        "@babel/preset-env": "^7.19.4",
        "@babel/preset-react": "^7.18.6",
        "@babel/preset-typescript": "^7.18.6",
        "babel-loader": "^8.2.5",
        "babel-plugin-styled-components": "^2.0.7",
        "@types/jest": "^29.2.0",
        "@types/node": "^18.11.5",
        "@types/react": "^18.0.22",
        "@types/react-dom": "^18.0.7",
        "clean-webpack-plugin": "^4.0.0",
        "cypress": "^10.11.0",
        "dotenv-webpack": "^8.0.1",
        "eslint": "^8.26.0",
        "jest": "^29.2.1",
        "favicons": "^7.0.2",
        "favicons-webpack-plugin": "^6.0.0-alpha.1",
        "file-loader": "^6.2.0",
        "html-webpack-plugin": "^5.5.0",
        "nodemon": "^2.0.20",
        "ts-node": "^10.9.1",
        "webpack": "^5.74.0",
        "webpack-cli": "^4.10.0",
        "webpack-dev-server": "^4.11.1"
    },
    "dependencies": {
        "@sentry/node": "^7.16.0",
        "@sentry/react": "^7.16.0",
        "@sentry/tracing": "^7.16.0",
        "axios": "^0.21.4",
        "cloudinary-core": "^2.13.0",
        "concurrently": "^7.5.0",
        "cross-env": "^7.0.3",
        "dotenv": "^16.0.3",
        "ejs": "^3.1.8",
        "express": "^4.18.2",
        "history": "^5.3.0",
        "lodash": "^4.17.21",
        "lodash-es": "^4.17.21",
        "mobx": "^6.6.2",
        "mobx-react-lite": "^3.4.0",
        "path-browserify": "^1.0.1",
        "pg": "^8.8.0",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "react-router-dom": "^6.4.2",
        "sanitize-html": "^2.7.3",
        "styled-components": "^5.3.6",
        "tsconfig-paths": "^4.1.0",
        "tsconfig-paths-webpack-plugin": "^3.5.2",
        "typescript": "^4.8.4",
        "uuid": "^9.0.0"
    }
}

Thanks in advance :)

CodePudding user response:

Public Path

Try changing output.publicPath:'/', to output.publicPath: ASSET_PATH. As most of webpack hmr malfunctions are often due to publicPath. publicPath webpack doc

  • Just a tip. CleanWebpackPlugin isn't necessary in webpack v5, you can just use output.clean:true.

CodePudding user response:

What worked for me in the end is adding the following plug-in:'@pmmmwh/react-refresh-webpack-plugin'

Here is the webpack.config.js file after the changes:

require('dotenv').config({ path: './.env' });
const path = require('path');
const DotenvWebpack = require('dotenv-webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

module.exports = (env, options) => {
    const isDevMode = options.mode === 'development';
    const title = process.env.APP_TITLE_OVERRIDE || 'My Cute App';

    return {
        devtool: isDevMode ? 'source-map' : false,
        resolve: {
            extensions: ['.ts', '.tsx', '.js'],
            plugins: [
                new TsconfigPathsPlugin({
                    /* options: see below */
                })
            ],
            fallback: {
                path: require.resolve('path-browserify'),
                fs: false
            },
            alias: { common: path.resolve(__dirname, './common') }
        },
        entry: ['./src'],
        output: {
            path: path.resolve(__dirname, 'dist'),
            publicPath: '/',
            filename: isDevMode ? 'bundle.js' : '[name].[chunkhash:10].js',
            chunkFilename: isDevMode ? '[name].bundle.js' : '[name].[chunkhash:10].js'
        },
        optimization: {
            usedExports: true,
            innerGraph: true,
            sideEffects: true
        },
        module: {
            rules: [
                {
                    test: /\.(ts|js)x?$/,
                    exclude: /node_modules/,
                    include: [
                        path.resolve(__dirname, './src'),
                        path.resolve(__dirname, './common')
                    ],
                    use: [
                        {
                            loader: 'babel-loader'
                        }
                    ]
                },
                {
                    test: /\.(sa|sc|c)ss$/,
                    use: [
                        'style-loader',
                        {
                            loader: 'css-loader',
                            options: {
                                sourceMap: isDevMode
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: isDevMode
                            }
                        }
                    ]
                },
                {
                    test: /\.(ttf|eot|woff|woff2)$/,
                    use: {
                        loader: 'file-loader',
                        options: {
                            name: 'fonts/[name].[ext]'
                        }
                    }
                },
                {
                    test: /\.(jpe?g|png|gif|svg|ico)$/i,
                    loader: 'file-loader'
                }
            ]
        },
        devServer: {
            historyApiFallback: true,
            hot: true
        },
        plugins: [
            new CleanWebpackPlugin(),
            new ReactRefreshWebpackPlugin({
                overlay: false
            }),
            new HtmlWebpackPlugin({
                title,
                meta: {
                    viewport:
                        'width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1'
                }
            }),
            new DotenvWebpack({
                path: './.env',
                systemvars: !isDevMode
            })
        ]
    };
};

  • Related