【webpack】记录hmr失效解决方案

前言

最近遇到个问题,由于登陆系统使用单点登陆加应用使用微前端,开发时使用xswitch插件进行拦截代理,然后导致每次修改完代码需要手动刷新浏览器更新。特此寻找了解决方法。后发现每次都会刷新浏览器而不是热重载,经过探索后成功不刷新浏览器热重载。

解决方法

1、首先需要保证ws服务正常。由于未使用localhost域名导致会尝试建立访问域名的ws服务。

  • 找到node_modules下_react-dev-utils这个包
  • 其中有个文件叫webpackHotDevClient.js文件,第58行修改协议host和端口:
process.env.WDS_SOCKET_HOST = '127.0.0.1';
// Connect to WebpackDevServer via a socket.
var connection = new WebSocket(
  url.format({
    
    
    protocol:  'ws',
    hostname: process.env.WDS_SOCKET_HOST || window.location.hostname,
    port: 改成自己启动的端口,
    // Hardcoded in WebpackDevServer
    pathname: process.env.WDS_SOCKET_PATH || '/sockjs-node',
    slashes: true,
  })
);
  • 找到node_modules下的_webpack-dev-server 版本3.11.2,其中client下utils下的createSocketUrl.js文件里第77行修改配置:
return url.format({
    
    
    protocol: 'http',
    auth: auth,
    hostname: '127.0.0.1',
    port: sockPort,
    // If sockPath is provided it'll be passed in via the resourceQuery as a
    // query param so it has to be parsed out of the querystring in order for the
    // client to open the socket to the correct location.
    pathname: sockPath
  });
  • 此时ws可以连接,启动后会发现ws成功连接,但是每次修改代码后,会进行刷新浏览器。
  • 经断点研究后发现,修改代码后,会查找该代码块,但是该代码块不支持热更新,貌似是module.hot._main_是true就直接throw出unaccept,导致刷浏览器。
  • 正常来说react-dev-utils已处理了module.hot等逻辑,不需要侵入性再写逻辑,可能是由于这个模块工作不正常。但研究半天未发现有啥问题。于是使用新开服务的方式去解决这个问题。
  • 增加额外代码有2个库可以用,一个是react-refresh,一个是react-hot-loader。首先尝试使用react-refresh,因为dan说react-refresh后续会替代react-hot-loader,并且react-hot-loader不进行维护的原因就是因为出现了react-refresh。
  • 使用react-refresh时发现ws连接也没连上,同样硬编码进去修改host端口,该文件位置位于_@[email protected]下sockets/utils/getSocketUrlParts.js 109行。后续连接后发现仍然无法进行热更新,也没有报错,于是换成使用react-hot-loader。
  • 经配置后发现react-hot-loader可以进行热更新且不刷新浏览器。
  • 需要先给dev-server开启hot:
"devServer": {
    
    
    "historyApiFallback": true,
    "hot": true
  },
  • 增加入口与babel-plugin:
 config
      .toConfig()
      .entry.app.unshift(require.resolve('react-hot-loader/patch'));
    config.toConfig().module.rules.forEach((v, i) => {
    
    
      if ((v.test + '').includes('jsx')) {
    
    
        v.use.forEach((k) => {
    
    
          if (k.loader.includes('babel-loader')) {
    
    
            k.options.plugins.push(require.resolve('react-hot-loader/babel'));
          }
        });
      }
    });
  • 根组件中套入hot:
import {
    
     hot } from 'react-hot-loader/root';
class Appx extends React.PureComponent {
    
    
  ...
  render() {
    
    
    return (
      <Provider store={
    
    store}>
      	...
      </Provider>
    );
  }
}
const App = hot(Appx);
  • 即可进行热重载。

猜你喜欢

转载自blog.csdn.net/yehuozhili/article/details/121270477