前言
为了提高开发效率,我们会选择一个可监听文件的修改、可重新编译、并且可以自动刷新浏览器,这样可能还不满足,我们还需要热更新(HMR),避免页面状态丢失。
正文
选择一个工具
在开发过程中,如果每次修改完代码都需要手动去编译的话,那显然效率极低。都 2020 年了,不提高效率哪有时间摸鱼划水。
webpack 提供了几种可选方式,帮助我们在修改代码后自动编译代码:
- webpack watch mode
- webpack-dev-server
- webpack-dev-middleware
webpack 可以在 watch mode
(观察模式)下使用。在这种模式下,webpack 将监视您的文件,并在更改时重新编译。
webpack-dev-server
提供了一个易于部署的开发服务器,具有快速的实时重载(live reloading)功能。
如果你已经有一个开发服务器并且需要完全的灵活性,可以使用 webpack-dev-middleware
作为中间件。
webapck-dev-server
和 webpack-dev-middleware
使用内存编译,这意味着 bundle
不会被保存在硬盘上。这使得编译十分迅速,并导致你的文件系统更少麻烦。
我的选择是
webpack-dev-server
。
使用 watch mode
*webpack-dev-server 和 webpack-dev-middleware 里 Watch 模式默认开启。
此前,我一直没有 get 到这货有什么用,没太懂。首先,开启 Watch 模式的方式有两种。
通过 CLI 参数传递:
// package.json { "scripts": { "watch": "webpack --watch" } }
或者在配置文件中添加:
// webpack.config.js module.exports = { // ... watch: true, watchOptions: { // 定制 Watch 模式选项 poll: 1000, // 检查一次变动的时间间隔(ms) aggregateTimeout: 500, // 重新构建前增加延迟,这段时间内允许其他任何更改都聚合到一次重新构建里面(ms) ignored: /node_modules/, // 这个选项可以排除一些巨大的文件夹,避免占用大量的 CPU 或者内存。多个可以是数组 } }
现在,我们运行脚本命令 yarn run watch
,然后就会看到 webpack 是如何编译代码的。同时你会发现并没有退出命令行,这是因为此 script 当前还在 watch 你文件。
我们随意更改一行代码,然后保存,接着我们应该可以在终端(Terminal)窗口可以看到 webpack 自动地重新编译修改后的模块!
它的缺点是,为了看到修改后的实际效果,我们需要刷新浏览器。明显不是我们想要的对吧。还有,它跟
webpack-dev-server
和webpack-dev-middleware
不同的是,前者每次更改都会重新打包到本地,而后者是将 bundle 文件保存在内存中,这样前者速度会慢很多。那么有没有能够自动刷新浏览器的呢?可以通过
webpack-dev-server
实现我们的需求。
使用 webpack-dev-server
它为我们提供了一个简单的 web server,并且具有 live reloading (实时重新加载)功能。
webpack-dev-server 在编译之后不会写入到任何输出文件。而是将 bundle 文件保留在内存中,然后将它们 serve 到 server 中,就好像它们是挂载在 server 根路径上的真实文件一样。如果你的页面希望在其他不同路径中找到 bundle 文件,则可以通过
devServer
配置中的publicPath
选项进行修改。
webpack-dev-server
实际上相当于启用了一个 express
的 HTTP 服务器 + 调用 webpack-dev-middleware
。它的作用主要是用来伺服资源文件。这个 HTTP 服务器和 Client 使用了 Websocket 通讯协议,原始文件作出改动后,webpack-dev-server
会用 webpack 实时的编译,再用 webpack-dev-middleware
将 webpack 编译后文件会输出到内存中。适合纯前端项目,很难编写后端服务,进行整合。
使用 webpack-dev-middleware
webpack-dev-middleware
是一个封装器(wrapper),它可以把 webpack 处理过的文件发送到一个 server。
webpack-dev-middleware
输出的文件存在于内存中。你定义了 webpack.config.js
,webpack 就能据此梳理出 entry
和 output
模块的关系脉络,而 webpack-dev-middleware
就在此基础上形成一个文件映射系统,每当应用程序请求一个文件,它匹配到了就把内存中缓存的对应结果以文件的格式返回给你,反之则进入到下一个中间件。
因为是内存型文件系统,所以重建速度非常快,很适合于开发阶段用作静态资源服务器;因为 webpack 可以把任何一种资源都当作是模块来处理,因此能向客户端反馈各种格式的资源,所以可以替代 HTTP 服务器。事实上,大多数 webpack 用户用过的 webpack-dev-server
就是一个 express
+webpack-dev-middleware
的实现。二者的区别仅在于 webpack-dev-server
是封装好的,除了 webpack.config.js
和命令行参数之外,很难去做定制型开发。而 webpack-dev-middleware
是中间件,可以编写自己的后端服务然后把它整合进来,相对而言比较灵活自由。