JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1377
  • Score
    100M100P100Q120913F
  • License MIT

React Fast Refresh plugin and loader for webpack v5+

Package Exports

  • @webhotelier/webpack-fast-refresh
  • @webhotelier/webpack-fast-refresh/loader.js
  • @webhotelier/webpack-fast-refresh/runtime.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@webhotelier/webpack-fast-refresh) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

webpack-fast-refresh

React Fast Refresh for webpack@5+ and babel@7.9+

webpack@4 users should try https://github.com/pmmmwh/react-refresh-webpack-plugin

Usage

1. Install both react-refresh and webpack-fast-refresh

npm install -D -E @webhotelier/webpack-fast-refresh react-refresh
# or
yarn add -D -E @webhotelier/webpack-fast-refresh react-refresh

2. Configure webpack

Make the following changes to your webpack.config.js:

a) Register the plugin:

const ReactRefreshPlugin = require('@webhotelier/webpack-fast-refresh');

config.plugins.unshift(new ReactRefreshPlugin());

// or if you have an object-based config:
{
  ...otherSettings,
  plugins: [new ReactRefreshPlugin(), ...otherplugins];
}

b) Place the runtime in front of your entrypoint:

Depending on how you have configured your entry, change it similarly to the following examples:

// if it looks like this ("./index.js" is just an example, can be any file or path)
config.entry = './index.js'; // or
config.entry = ['./index.js'];
// change it to this:
config.entry = ['@webhotelier/webpack-fast-refresh/runtime.js', './index.js'];

// if it looks like this
config.entry = {
  import: './index.js',
}; // or
config.entry = {
  import: ['./index.js'],
};
// change it to this:
config.entry = {
  import: ['@webhotelier/webpack-fast-refresh/runtime.js', './index.js'],
};

// named entry points are also supported ("main" is just an example, can be any entry name)
config.main.entry = './index.js'; // or
config.main.entry = ['./index.js'];
// change to:
config.main.entry = [
  '@webhotelier/webpack-fast-refresh/runtime.js',
  './index.js',
];

// Examples of object-based config:
// change:
{
  "entry": {
    "main": "./index.js"
  }
}

// to:
{
  "entry": {
    "main": ["@webhotelier/webpack-fast-refresh/runtime.js", "./index.js"]
  }
}

c) Place the loader in your rule matching React files:

Let's say you have the following rule:

{
  "rules": [
    {
      "test": /\.jsx$/,
      "use": [
        { "loader": "babel-loader", "options": { "cacheDirectory": true } }
      ]
    }
  ]
}

Change to:

{
  "module": {
    "rules": [
      {
        "test": /\.jsx$/,
        "use": [
          { "loader": "babel-loader", "options": { "cacheDirectory": true } },
          { "loader": "@webhotelier/webpack-fast-refresh/loader.js" }
        ]
      }
    ]
  }
}

or push it with code:

// make sure to use the index of your JSX loader, 0 in this example
config.module.rules[0].use.push('@webhotelier/webpack-fast-refresh/loader.js');

3. Configure babel

Add react-refresh/babel to your babelrc:

{
  "presets": [["@babel/preset-react", { "runtime": "automatic" }]],
  "plugins": ["react-refresh/babel"]
}

4. Configure error-overlay plugin (optional)

const ErrorOverlayPlugin = require('@webhotelier/webpack-fast-refresh/error-overlay');
config.plugins.push(new ErrorOverlayPlugin());

// or if you have an object-based config:
{
  ...otherSettings,
  plugins: [new ErrorOverlayPlugin(), ...otherplugins];
}

5. Launch the server

Make sure you have HMR enabled.

Using webpack-dev-server:

webpack-dev-server --hot --mode development

Using webpack-hot-middleware:

In webpack.config.js:

config.entry.main.unshift(require.resolve('webpack-hot-middleware/client'));
config.plugins.push(new webpack.HotModuleReplacementPlugin());

In your node server:

if (app.get('env') === 'development') {
  const webpack = require('webpack');
  const webpackConfig = require('./webpack.config.json');
  const webpackCompiler = webpack(webpackConfig);

  app.use(
    require('webpack-dev-middleware')(webpackCompiler, {
      lazy: false,
      publicPath: webpackConfig.output.publicPath,
      headers: { 'Access-Control-Allow-Origin': '*' },
    })
  );

  app.use(
    require('webpack-hot-middleware')(webpackCompiler, {
      path: '/__webpack_hmr',
      heartbeat: 10 * 1000,
      noInfo: false,
      quiet: false,
    })
  );
}

Common Issues

Production problems

The above plugins/loader/etc are not checking if running in production builds.

Make sure you add the correct checks to only include them in development builds.

Still having trouble configuring everything?

Real-world example using the plugin:

https://github.com/LWJGL/lwjgl3-www/blob/master/webpack.config.cjs

References