react项目用babel-loader 或 ts-loader后 实现HMR(热替换)

668 阅读1分钟

前言:

项目中如果使用了ts和ts-loader,那么这个loader会影响webpack的HMR功能,导致代码改动后浏览器每次都刷新,给日常的react项目开发工作带来不少麻烦!下面是解决方案

准备工作:

  1. 最低支持 react 16.9 版本
  2. npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh
  3. 如果要支持ts 需要安装 npm install -D type-fest

用babel-loader编译ts 实现HMR

babel 需要安装 @babel/preset-typescript 来支持ts
webpack的相关配置如下:

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

const isDevelopment = process.env.NODE_ENV !== 'production';

module.exports = {
  mode: isDevelopment ? 'development' : 'production',
  module: {
    rules: [
      {
        test: /\.[jt]sx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: require.resolve('babel-loader'),
            options: {
              plugins: [isDevelopment && require.resolve('react-refresh/babel')].filter(Boolean),
            },
          },
        ],
      },
    ],
  },
  plugins: [isDevelopment && new ReactRefreshWebpackPlugin()].filter(Boolean),
};

babel配置文件参考

module.exports = (api) => {
  // This caches the Babel config
  api.cache.using(() => process.env.NODE_ENV);
  return {
    presets: [
      '@babel/preset-env',
      '@babel/preset-typescript',
      // Enable development transform of React with new automatic runtime
      ['@babel/preset-react', { development: !api.env('production'), runtime: 'automatic' }],
    ],
    // Applies the react-refresh Babel plugin on non-production modes only
    ...(!api.env('production') && { plugins: ['react-refresh/babel'] }),
  };
};

用ts-loader编译ts 实现 HMR

需要安装包 npm install -D react-refresh-typescript

const ReactRefreshTypeScript = require('react-refresh-typescript');

const isDevelopment = process.env.NODE_ENV !== 'production';

module.exports = {
  module: {
    rules: [
      {
        test: /\.[jt]sx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: require.resolve('ts-loader'),
            options: {
              getCustomTransformers: () => ({
                before: [isDevelopment && ReactRefreshTypeScript()].filter(Boolean),
              }),
              transpileOnly: isDevelopment,
            },
          },
        ],
      },
    ],
  },
};

ts-loader不能和HMR一起工作,除非transpileOnly设置为true。如果你需要在开发过程中进行类型检查,你应该使用ForkTsCheckerWebpackPlugin。

以上就分别实现了react项目中编译ts 和HMR 热替换 之间的冲突问题!