webpack 里的刷新
webpack 里涉及了多种形式的刷新,其中包括文件监听,修改内容时,页面的整体刷新,还有修改组件时,只针对组件的局部刷新。从最基本的 webpack -w
,到 webpack-dev-server
与 html-webpack-plugin
的结合,再到 Hot Module Replacement,它们都有其对应的应用场景。
注:本文的内容是对上一篇文章【webpack】的补充与提高,所以,项目结构和文件是相同的。
webpack –watch
webpack 给我们提供了 webpack --watch
这么一个命令,它的简写是 webpack -w
。当在 cli 中输入 webpack -w
,webpack会开启监听模式,观察项目文件的变化。
这样,你在每次修改完文件后,就无需再运行 webpack -p
去重新编译文件,只需要刷新浏览器,便能看到修改的效果。
所以,这个命令的优点是修改后免编译,缺点是修改完文件后,还是得手动去刷新浏览器。
webpack-dev-server
理想情况下,我们是希望修改完文件后,浏览器会自动刷新,即插件具备livereload的功能。通过文章前面的描述,可以采用 webpack-dev-server
并且设置 inline: true
属性。
当修改 entry
里设置的 JavaScript 文件时,浏览器里的页面也跟着刷新。
但修改 html、css 文件却发现浏览器却没跟着刷新,也就是说,这个插件不会监控 html、css 文件。
所以,你还需要借助 html-webpack-plugin
插件。这样,无论是修改 html文件、js文件,还是 css文件,或其他资源,页面都能自动刷新了。
模块热替换 HMR(Hot Module Replacement)
随着web技术在移动端的发展,单页面应用变得越来越火热。这种应用一般只有一个页面,它由许多组件和模块组成,然后通过ajax结合路由方式去加载不同状态的模块。
一个复杂的单页面应用,通常包含了很多组件,而组件里面又包含很多状态。用户的操作,是从一个组件的状态,到另外一个状态,或者到下一个组件。
但这种单页面应用,在开发时也带来一些问题。
比如,一个申请贷款的项目。第一步是 “填写个人信息”,操作完后进入第二个界面 “绑定并设置银行卡”,继续操作完后进入第三个界面 “选择贷款方式”…等等后续界面的操作。当我们在修改第三个组件 “选择贷款方式” 时,页面会重新刷新,所有之前填写的信息被重置,各种状态被丢失,界面也回到第一个组件,即 “填写个人信息”。要查看修改的效果,还得完成前面界面的操作,直到第三个界面。
又比如,假如某个页面的结构是一个tab切换,里面每一个tab项都是一个组件,默认是显示第一个tab项。但我们在开发第二个tab项时,每次修改和变更,页面又重新刷新到第一个tab项,要查看修改后的效果,还得手动切换到第二个tab项。
这无疑给我们的开发调试带来了一定的阻碍。
模块热替换的概念
依照webpack官网的解释,可以理解为:
模块热替换功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载页面。这使得你可以在独立模块变更后,无需刷新整个页面,就可以更新这些模块,极大地加速了开发时间。
你可以把 HMR 看成是 LiveReload 的一种替换方式。
注意:无论是前面提到的刷新插件、还是HMR,它们都是应用在开发环境中,辅助我们更好的开发项目,与生产环境无关!
模块热替换-react
要实现 模块热替换 的功能,可以通过很多方式。由于涉及到组件化开发,目前最流行的采用 webpack + react 的开发模式,如果你采用的也是 react 开发,那么,你可以使用通过 react-hot-loader
加载器来实现 模块热替换,去刷新 react 组件。
首先安装它:
> npm install --save-dev react-hot-loader@next |
然后在 webpack.config.js
中设置:
// webpack.config.js |
上面的代码中,entry
的值为一个数组,除了原来的 path.resolve(__dirname, './src/res/js/main.js')
, 它还增加了 'react-hot-loader/patch'
、'webpack-dev-server/client?http://localhost:8080'
、以及 'webpack/hot/only-dev-server'
这三项。
另外,还在 devServer
中开启了 hot
属性,plugins
新增了关于 HMR 的设置。
最后,修改 main.js
:
// main.js |
在上述代码中,父组件包含了两个子组件 <Navbar />
和 <Heading />
(它们的代码,在此不赘述),父组件设置了一个定时器计数,并且,用户可以切点击 Navbar
和 Heading
按钮来切换这两个子组件的显示隐藏。
这样,我们无论是修改 <Navbar />
组件,还是修改 <Heading />
组件,都只更新它们对应的视图,而不会刷新整个页面,父组件里的定时计数也不会被重置。