问题:
升级 Webpack1 到 Webpack2 之后, 开发模式下实时重载(Live Reloading)不起作用。控制台一直显示“App hot update...”。页面不自动刷新,没有变化。
解决办法:
去掉。WebpackDevServer配置中的hot:true
new WebpackDevServer(webpack(config), {
......
// hot: true, //去掉
inline: true,
......
})
不过不知道为什么得去掉...
以下内容更新于2018/05/15
以上的方法其实没有解决根本问题。当时只知道去掉
hot:true配置后,修改文件时页面能够自动刷新了,但不知道为什么这么做,问题到底在哪里。近期看到留言才重新研究了这个问题。花费了好几个小时踩坑,算是对这个问题有了新的认识。
项目结构是,django + react + webpack。 版本:
react:0.14.7webpack:2.7.0react-hot-loader:1.3.0webpack-dev-server:1.14.1django-webpack-loader:0.5.0
值得参考的样板项目:
- django-webpack-loader example(
webpack v1+webpack-dev-server v1+react-hot-loader v1) 升级webpack 之前,我项目的配置跟这个例子差不多。 - react-hot-loader-minimal-boilerplate (
webpack v2+webpack-dev-server v2+react-hot-loader v3)
问题
升级 webpack v1到v2之后,模块热替换(Hot Module Replacement,HMR)失效了,而 webpack 配置的entry中'webpack/hot/only-dev-server'指明了HMR失效时,页面也不会重新加载(参考What's the difference between 'webpack/hot/dev-server' and 'webpack/hot/only-dev-server'?),所以开发模式下修改文件,页面不会自动刷新。
模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:
- 保留在完全重新加载页面时丢失的应用程序状态。
- 只更新变更内容,以节省宝贵的开发时间。
- 调整样式更加快速 - 几乎相当于在浏览器调试器中更改样式。
解决办法
如果不需要HMR,只需要页面可以自动刷新,那可以去掉WebpackDevServer配置中的hot:true或者把 webpack 配置的entry中'webpack/hot/only-dev-server'改成'webpack/hot/dev-server'。这样就算HMR 不生效,也不影响开发过程中实时看到页面的变化。
但升级webpack v1到v2之后,还是想使用HMR呢?
Webpack升级到2.7.0之后,react-hot-loader还是v1,根据 react-hot-loader v1.3.0 stopped working after upgrade to webpack 2.2.1 #474 中的讨论,说明需要升级react-hot-loader,v1应该是不适用 webpack v2。
webpack时也要升级webpack-dev-server。
Make sure your webpack-dev-server AND webpack are both updated. at time of writing this is what i've got
"react-hot-loader": "^3.0.0-beta.6", "webpack-dev-server": "^2.3.0", "webpack": "^2.2.1",
以上说明,重点是要升级react-hot-loader和webpack-dev-server。
注意,这个项目升级前HMR是启用的,配置参考django-webpack-loader example,升级过程中没有改动 webpack 的配置,只是根据 v2 的新特性做了相应的用法上的改变(详情参考迁移到新版本)。因此下面的内容不是从0到1地配置 HMR,而是一个升级(主要
react-hot-loader)的过程。
npm升级react-hot-loader到v3或v4,升级webpack-dev-server到v2。"react-hot-loader": "^4.0.0", "webpack-dev-server": "^2.3.0"- 在.babelrc 文件的
plugins中添加一项:"react-hot-loader/babel"。 - 修改 webpack 配置。
//webpack.config.local.js //1.修改入口 var config = require('./webpack.base.config.js'); config.entry.app = [ 'webpack-dev-server/client?http://' + ip + ':3000', 'webpack/hot/only-dev-server', //dev-server reloads when applying HMR fails, only-dev-server doesn't. 'react-hot-loader/patch', //添加这一项 './html/app', ] //2.去掉react-hot-loader config.module.rules.push( { test: /\.jsx?$/, exclude: /node_modules/, use: ['babel-loader'] //before: ['react-hot-loader','babel-loader'] } ); - 修改
WebpackDevServer的配置。添加headers。详情参考React Hot Loader Troubleshooting 。//server.js new WebpackDevServer(webpack(config), { publicPath: config.output.publicPath, hot: true, //enable HMR on the server headers:{'Access-Control-Allow-Origin':'*'}, //添加这一项 inline: true, historyApiFallback: true }).listen(3000, 'localhost', function (err, result) { if (err) { console.log(err); } console.log('Listening at localhost:3000'); }); - 使用
react-hot-loader的AppContainer封装应用的顶底组件。可参考react-hot-loader-minimal-boilerplate。import React from 'react' import ReactDOM from 'react-dom' import { AppContainer } from 'react-hot-loader' import Root from './containers/Root' const render = Component => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('root') ) } render(Root) if (module.hot) { module.hot.accept('./containers/Root', () => { render(Root)}) }
按道理,到这为止react-hot-loader的升级就完成了。HMR应该就生效了。但是我又遇到一个坑,浏览器控制台的输出信息都正常,新的打包文件的网络请求也正常,但是页面上却依然没变化。又是坑啊!最后在Hot updates not applied #581里面找到相同情况的解决方法。
效果图:
结语
这个问题的解决过程中踩了不少坑,webpack官方文档只提供了v4版本的,很多人也都在吐槽看不到历史版本的文档。这个对开发者来说确实很不方便。非官方的文档有很多,但却加大了排错过程花费的精力,降低了效率。
毕竟升级webpack还是挺麻烦的,v1到v2还好,变化不多,升级到v3配置就改变很多了。并且一些相关插件也得升级,比如这次没有升级react-hot-loader就出问题了。至于那些插件该一起升级也没个官方说法,只能出问题了再疯狂地Google。
吐槽归吐槽,坑再多,还是得踩啊~~~
延伸阅读:
- 这篇关于Webpack热加载的文章讲的很清晰透彻!虽然示例用的是Webpack1 Webpack’s HMR & React-Hot-Loader — The Missing Manual: medium.com/@rajaraodv/…
- Difference between
new webpack.HotModuleReplacementPlugin()and--hot?: github.com/webpack/web… - Webpack 2 配置 React 热加载,React Hot Loading with Webpack 2: engineering.monsanto.com/2017/08/15/…
- “module not found : Error: Cannot resolve module 'react/lib/ReactMount' ”: stackoverflow.com/questions/4…
- 升级React Hot Loader,可参考 Update TodoMVC example to React Hot Loader 3: github.com/reduxjs/red…
- 使用React Hot Loader 的问题及解决方法 : github.com/gaearon/rea…