02Geek HTML5 and JavaScript, TypeScript, React, Flash, ActionScript online School
Previous VideoNext Video

Getting Webpack Middlewares to Run with Our Real Server

Setting Up Webpack Hot Refresh Middleware in React

In this tutorial, we’ll walk through how to configure Webpack's hot refresh middleware in a React application using Express as our server. This setup ensures a faster and more efficient development environment, allowing real-time updates without refreshing the browser manually. Let’s dive in!

Step 1: Install Required Packages

First, install the necessary Webpack middleware packages for hot module replacement. These packages are needed only in the development environment.

npm install webpack-dev-middleware webpack-hot-middleware --save-dev

Make sure to use --save-dev because these dependencies are not required for production.

Step 2: Load Webpack and Configuration

In your development server setup, load Webpack and your Webpack configuration. This allows Webpack to manage the development bundling and serve files through middleware.

const webpack = require('webpack');
const config = require('./webpack.config');
const compiler = webpack(config);

Step 3: Add Middleware for Hot Reload

Now, integrate Webpack's dev middleware and hot middleware into your Express server. This will enable automatic page refreshes when code changes.

const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');

app.use(webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath
}));

app.use(webpackHotMiddleware(compiler));

Step 4: Configure Webpack Hot Module Replacement (HMR)

To enable HMR, add the HotModuleReplacementPlugin in your Webpack configuration file under plugins:

plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin() // Prevents errors from breaking the build
]

You also need to ensure that the client is aware of HMR. Add the following line in your main JavaScript file:

if (module.hot) {
    module.hot.accept();
}

Step 5: Test and Run

Start your server and test the setup. Whenever you make changes to your React code, the page will update without a manual refresh.

npm run dev

Summary

By setting up Webpack hot refresh middleware, your React development environment becomes far more efficient. This setup saves time and accelerates your feedback loop, allowing you to focus more on coding and less on manually refreshing the browser.

In the next steps, we will further optimize Webpack for production, ensuring your final build is highly performant.

Preferred Approach to Achieve Hot Module Replacement (HMR) in 2024

As of 2024, the preferred approach for implementing Hot Module Replacement (HMR) in a React application has evolved to leverage modern tooling and practices that simplify the process while improving performance and maintainability. Here's an updated guide:


1. Leverage Vite or Next.js Instead of Webpack

Modern tools like Vite and Next.js have built-in support for HMR, streamlining development workflows. They eliminate much of the manual configuration required in Webpack and offer faster builds and hot reload speeds due to their architecture.

  • Why Vite?

    • Vite uses native ES Modules for development, making it incredibly fast.
    • Built-in support for HMR with minimal setup.
    • Works seamlessly with React, Vue, and other frameworks.
  • Why Next.js?

    • Built-in HMR support with React Fast Refresh.
    • No need for separate middleware configurations.
    • Ideal for applications requiring server-side rendering (SSR) and static site generation (SSG).

Example: Setting up HMR in Vite Install Vite and create a new React project:

npm create vite@latest my-react-app --template react
cd my-react-app
npm install
npm run dev

Vite handles HMR out of the box.


2. Use Webpack 5 with Built-In HMR Support (If Webpack Is Necessary)

If you’re still using Webpack, it now has built-in HMR support without requiring webpack-hot-middleware or webpack-dev-middleware. Here's how to achieve HMR using Webpack 5:

a. Install Dependencies

Ensure you have Webpack 5 installed:

npm install webpack webpack-cli webpack-dev-server react-refresh @pmmmwh/react-refresh-webpack-plugin --save-dev

b. Update Webpack Configuration

Enable HMR and integrate React Refresh for seamless updates to React components.

const path = require('path');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
    },
    devServer: {
        static: './dist',
        hot: true, // Enable HMR
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        plugins: ['react-refresh/babel'], // Add React Refresh plugin
                    },
                },
            },
        ],
    },
    plugins: [
        new ReactRefreshWebpackPlugin(), // Enable React Refresh
    ],
};

c. Start the Development Server

Use webpack-dev-server to enable HMR:

npx webpack serve --mode development

3. Adopt React Fast Refresh

React Fast Refresh is the official replacement for React Hot Loader and is supported natively in Vite, Next.js, and Webpack (via the @pmmmwh/react-refresh-webpack-plugin).

  • Automatically updates React components during development without losing their state.
  • Simplifies debugging by maintaining error overlays.

4. Containerized Development Environments

For modern teams using Docker, tools like Tilt or Docker Compose support HMR setups with minimal overhead, ensuring developers working on different environments (local or cloud) benefit from consistent workflows.


Key Benefits of Updated HMR Practices

  1. Faster Reload Speeds: Tools like Vite and Next.js significantly reduce the time taken for hot updates.
  2. Simplified Configuration: Modern frameworks handle the complexity, reducing the need for middleware and plugins.
  3. Improved Compatibility: React Fast Refresh and ES Module-based tooling ensure fewer issues with HMR.
  4. Better Developer Experience: Enhanced error overlays and state preservation make debugging easier.

Conclusion

While Webpack is still a powerful tool, Vite and Next.js represent the modern standard for achieving HMR in React applications. They are faster, simpler to set up, and better aligned with current development workflows. If starting a new project in 2024, consider Vite or Next.js for an optimal development experience.

Video Transcript

00:00Now that we got the basics
00:01of the hot middleware configured, it's time for us
00:04to configure the rest, rest of Webpac by setting up Webpack,
00:08using the Webpack dev middleware to enable us to have that
00:12Webpack server per se.
00:14This is, by the way, a middleware is a word that's used
00:16by express or anytime you add features to express.
00:19So we're basically adding the feature, just like
00:21with loaders and Webpack, we're adding the feature
00:24of Webpack dev as a middleware,
00:27and we're also gonna add the web pack hot middleware,
00:29which both will give us those features that we need
00:32to be able to have hot refreshes on our server.
00:34So by the end of this lecture, we'll have our
00:37Webpack dev server configured as we created it ourselves.
00:42Alright, so contrary to our last section where automatic
00:46or really the one before that,
00:48that webpac dev server ran automatically behind the hood.
00:52Now that we have to configure it ourselves, we need
00:54to also go to our configuration and,
00:57and do a few changes to it.
00:58So for one, we don't have that web server configured
01:01by default, so I'm just gonna go into
01:02that web pack config and delete that.
01:05The next one, I'm gonna go into my entry
01:07and turn it into an array.
01:08And the reason why I'm doing that is
01:09because I want to add more things into it.
01:12Uh, namely specifically I want to add the server
01:15and I want to add that hot middleware
01:17into our entry as well.
01:18So we'll be able to communicate back
01:20and forth between the client and the server.
01:23Now in our development environment,
01:25what I'm just gonna go ahead
01:26and do is I'm gonna go to my config
01:28and I'm gonna go into my entry and I'm gonna go ahead
01:32and unshift, and again, this is not a realistic scenario.
01:35This is if you really know that in advance
01:37that you're gonna have there in array, a,
01:39a better solution would have probably just two different,
01:42um, configs, one config for this, one, config for that.
01:45But I decided to just do
01:46something interesting and a little bit different.
01:48Okay? So I'm gonna go ahead for my web pack hot dev
01:53server, that's how I added in to our client.
01:56And I'm also gonna add the hot refresh capability on the
01:59client itself by adding the web pack hot
02:03middleware client.
02:05Okay? So those are the two items that we need
02:07to add into our entry of our, uh, application.
02:12Okay? So once we've added that, let's continue down the path
02:15of actually building it out.
02:17So step num, step number, whatever step we're in already,
02:22it's time for us to go into our config
02:24and compile it down into basically a,
02:27a compile it down with webpac.
02:29The way we do that is we basically create a compiler
02:33and we'll take our web pack, which we have there,
02:36and add into it that config that we've just modified.
02:39That way it will compile down our configurations.
02:43Step number two is, I'm gonna go ahead
02:44and I'm gonna literally go ahead and start up my server,
02:48but I'm gonna start my original server, the one
02:51that we've created in the last section.
02:52So I'm gonna go to source server, load it up.
02:56Now, as you recall, we have your, our build.
02:57Oh, I had that written down
02:58There, I forgot about that.
03:00And I'm just gonna basically build it out
03:01and gain access to my app.
03:03Now that I have access to my app, I'm gonna go ahead
03:06and in my app itself, I'm going to use those two,
03:09basically the two components
03:11that we loaded up in the previous lecture
03:14where we had our web pack dev middleware
03:17and we had our web pack hot middleware.
03:20Both of them are used in express.
03:23And what I'm basically gonna do is I'm ba I'm basically
03:25gonna add the web pack dev middleware.
03:28I'm going ahead and doing that,
03:30and I'm going to use that inside of our, um, environment.
03:33And I'm gonna go ahead as I'm using it.
03:36I also wanna make sure that I actually am calling it,
03:39requiring it, I'm gonna require it.
03:44And then as soon as I require it,
03:46I'm gonna basically instantiate it.
03:48And I'm gonna send into a two parameters.
03:50First parameter is gonna be our friendly compiler
03:52that we've just created, and our second parameter is gonna
03:55be a list of extra, extra, um, configurations that we want
04:00to give that are specific to the development environment.
04:03For example, we could ask it not
04:05to list out all the information
04:07when they're building it out.
04:09And just for the sake of practice,
04:10really even beyond practice.
04:13Um, right now, it wouldn't work if we would run the server
04:16because in our Webpack config we have your relative path.
04:20And in reality, when we're actually in this dev environment
04:22setting, we really need that do to disappear.
04:26So how about we just assume that the, this value is not, um,
04:31relevant and instead of that we replace it really with
04:35a virtual value.
04:36And for that virtual val value, I'm gonna go ahead
04:39for my path itself.
04:40So I'm gonna go into my output path and in my output path,
04:44and I'm just gonna go ahead and put that in my config.
04:46And again, this is just for the practice output, uh, path.
04:51And I'm just gonna set it to be just the root.
04:54So it's gonna be a real path.
04:56And lemme just go ahead here and paste that.
05:00And by the way, if you're wondering how does the images,
05:02how do, how will anything be loaded up?
05:04Well, all that is managed already inside of our server
05:06where, where we made our static application public.
05:11All this line does inside
05:13of our development environment is say where to post this.
05:16And we're basically telling it virtually posted in the path
05:19in the in, in the, in the domain path.
05:22This path in the domain.
05:23Okay, so with that said, all that's really left for me
05:27to do is I'm just gonna go ahead
05:28and save this and we don't need this.
05:29Um, comma is um, go ahead and add one last item.
05:33And that last item is gonna be to use our hot middleware.
05:38So let me just go ahead
05:39and call require that web,
05:43let's just copy it from our J
05:47web pack hot middleware, which will add
05:49that actual capability of the hot compiling
05:53and we will instantiate it as well on the spot
05:56And send into it.
05:58Its compiler or its web pack for that matter.
06:02And if I go ahead and say this,
06:03and I think I've done everything right here,
06:05but this is just an example of how you could create the,
06:08your differences of between your development and production.
06:10Well still maintaining the central file, which is the same,
06:13which is your production environment, uh,
06:16which is basically clean
06:18and then your development environment is a little bit dirty.
06:20And here you put those extra tidbits of information.
06:23So let's go ahead and test this out.
06:24Let's see if it's working. So to be able
06:26to see if it's working, I need to call the node and server
06:30and we want to try the dev environment out.
06:32Now if everything worked appropriately
06:35after the server has started up,
06:37although 3000 is incorrect,
06:38so we probably should update that.
06:40And let's go ahead and change that really,
06:41because in our server we don't have it hard coded anymore.
06:46So let's turn this into a
06:50string template of ES six.
06:53And I'm just gonna go ahead here
06:54and send inside the dollar open close bracket
06:57and put here our port number itself.
06:59So we'll get the actual right port next time we run it
07:02and we got our server, it's running.
07:04If we go ahead and test it out on
07:08port 3010, then we should be connected.
07:12Not only will we be connected if I go ahead
07:14and try to change something, for example, in my app,
07:17don't forget our app itself.
07:19Our client itself has that hot module refresh.
07:22So even if I go into my app,
07:23and let's say I change here from zero to geek to zero
07:28to 3, 0 3, 0 3 geek,
07:31wow, that is a hard thing to say.
07:33Then it will update and refresh automatically exactly the
07:37same way as it worked when we were working
07:39with it automatically.
07:40But by breaking this out, now it got access to all
07:43of our server side code.
07:44And among that, in our case, it's just that rendering.
07:47But in a real world application now, Webpac will be able
07:50to communicate or in one big application,
07:53which is incredibly powerful, which will help us
07:57improve our performance By that,
07:59that our server now is running on the server
08:01and we can actually, uh,
08:02our react is rendering on the server for the first time.
08:04And we can now also test it out in our development
08:07environment in the next lecture.
08:10Now that we've completed creating our dev middlewares
08:13and our dev production, our dev environment, really
08:15to make it possible for us to have a separation
08:18between development and production in the next lecture,
08:20we're gonna fix a problem in what we've just built
08:23because our priorities are not configured correctly,
08:26which means that it's actually not gonna work when we run
08:29it.

Ready to Level Up Your Skills?

Join thousands of learners on 02GEEK and start your journey to becoming a coding expert today!

Enroll Now for Free!