在开发前端应用的时候,我们需要不停的在刷新浏览器来查看最新的编译效果。本篇介绍在 Webpack 中如何实现自动刷新。

Webpack 的 watch 模式

watch 模式下,每当项目中的文件发生变化,Webpack 都会重新编译输出新的内容。我们可以在配置文件中设置 watch 的值为 true 或者在命令行工具中指定 --watch 参数来开启 watch 模式。

开启 watch 模式可以解决文件发生变化之后 Webpack 自动编译的问题,但是如果做到自动刷新浏览器呢?

Webpack-dev-server

Webpack-dev-serveropen in new window 是官方维护的开发服务器,它的输出结果保存在内存中,也就是说构建出来的 bundle 不会输出到文件中。在使用 Webpack-dev-server 的时候,如下选项需要额外关注:

  1. devServer.historyApiFallbackopen in new window 如果应用中使用了基于 HTML5 History API 的路由,那么需要设置 devServer.historyApiFallback
  2. devServer.contentBaseopen in new window 可以通过 devServer.contentBase 来指定 index.html 的位置,如果最终使用的应用的 index.html 不是 webpack 自动生成的,那么需要通过 contentBase 来指定 index.html 的位置。contentBase 的值可以为一个路径,也可以为一个路径的数组,默认值是项目根路径。
  3. devServer.proxyopen in new window 有时候我们需要直接在页面上访问其他服务的接口,这时就需要设置代理。代理默认是不启用的。
  4. devServer.headersopen in new window 给页面的请求添加一些自定义响应头

Webpack-plugin-serve

Webpack-plugin-serveopen in new window 是一个第三方插件,将更新浏览器的逻辑封装在了 webpack 插件里。WPS 底层基于 webpack 的 watch 模式,并基于此实现了 HMR 等特性。

WPS 同时支持 webpack 的多编译器模式,只需要指定一组配置即可。

默认情况下,WPS 的编译结果输出到文件系统中。通过 webpack-plugin-ramdiskopen in new window, 还可以将编译输出到 RAM 中,相较于输出到文件系统来说性能更好。

安装 webpack-plugin-serve

npm add webpack-plugin-serve --develop
1

我们需要配置一下 WPS 来让 webpack 使用。配置如下:

const { mode } = require('webpack-nano/argv');
const { MiniHtmlWebpackPlugin } = require('mini-html-webpack-plugin');
const { WebpackPluginServe } = require('webpack-plugin-serve');

module.exports = {
  watch: mode === 'development',
  entry: ['./src', 'webpack-plugin-serve/client'],
  mode,
  plugins: [
    new MiniHtmlWebpackPlugin({ context: { title: 'Demo' } }),
    new WebpackPluginServe({
      port: process.env.PORT || 8080,
      static: './dist',
      liveReload: true,
      waitForBuild: true,
    }),
  ],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

添加 npm scripts:

{
  "scripts": {
    "start": "wp --mode development"
  }
}
1
2
3
4
5

此时执行构建命令,npm run start 可以看到命令行输出如下:

⬡ webpack: Watching Files
⬡ wps: Server Listening on: http://[::]:8080


⬡ webpack: asset main.js 86.8 KiB [emitted] (name: main)
  asset index.html 190 bytes [compared for emit]
  runtime modules 25.5 KiB 12 modules
  cacheable modules 35.3 KiB
    modules by path ./node_modules/ 33.4 KiB
      modules by path ./node_modules/webpack-plugin-serve/lib/client/ 24.1 KiB 8 modules
      ./node_modules/webpack-plugin-serve/client.js 1.05 KiB [built] [code generated]
      ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 6.67 KiB [built] [code generated]
      ./node_modules/css-loader/dist/runtime/api.js 1.57 KiB [built] [code generated]
    modules by path ./src/ 1.88 KiB
      modules by path ./src/*.js 248 bytes
        ./src/index.js 99 bytes [built] [code generated]
        ./src/component.js 149 bytes [built] [code generated]
      modules by path ./src/*.css 1.64 KiB
        ./src/main.css 1.32 KiB [built] [code generated]
        ./node_modules/css-loader/dist/cjs.js!./src/main.css 332 bytes [built] [code generated]
  0 (webpack 5.11.1) compiled successfully in 508 ms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

浏览器输出结果为:

HelloWorld

这时候,如果修改了源代码,我们可以看到命令行输出会有变化,同时浏览器也会自动更新。

通过网络访问开发服务器

有时候我们需要别的机器也可以访问我们本地的开发服务器,这时候,我们需要告诉开发服务器本机的 IP。在类 Unix 机器上可以通过 ifconfig | grep inet 方式获取,在 windows 机器上,可以通过 ipconfig 获取。之后通过 HOST=<ip 地址> ./node_modules/.bin/wp 的方式启动开发服务器。

轮询文件

Webpack 的文件 watch 模式在一些系统上不能不生效,比如老旧的 windows 或 Ubuntu。此时需要开启文件轮询功能,webpack.config.js 配置如下:

module.exports = {
  watchOptions: {
    aggregateTimeout: 300, // 延迟第一次 rebuild 300 毫秒
    poll: 1000, // 轮询间隔,单位毫秒
    ignored: /node_modules/, // 忽略目录,减少 CPU 消耗
  },
};
1
2
3
4
5
6
7

自动重启开发服务器

在项目初期,需要经常修改 webpack.config.js,就需要不断的重启开发服务器。我们可以通过 nodemonopen in new window 来实现 webpack 配置变更重启开发服务器的能力。

安装 nodemon:

npm add nodemon --develop
1

添加 npm scripts:

{
  "scripts": {
    "watch": "nodemon --watch webpack.*.js --exec \"npm start\"",
    "start": "wp --mode development"
  }
}
1
2
3
4
5
6

监控 Webpack 模块依赖图以外的文件

默认情况下,Webpack 只会监控项目直接依赖的模块文件。如果我们需要监控一些其他的文件,比如在使用 mini-html-webapck-pulgin 的时候,我们需要指定模板文件,来实现模板变更页面刷新的目的,这时,可以通过 webpack-add-dependency-pluginopen in new window 来解决问题。

总结

WDS 和 WPS 让 webpack 对开发过程更友好。

  1. Webpack 的 watch 模式可以实现代码变更实时输出编译结果。
  2. WPS 和 WDS 实现了代码变更刷新浏览器的功能,同时都支持 HMR。
  3. 在某些系统上,webpack 的 watch 模式可能无法起作用,需要启用轮询模式。
  4. WDS 可以通过中间件的形式与已有 node 服务集成。
  5. WPS 和 WDS 除了自动刷新浏览器和 HMR 以外,还有很多其他功能,比如代理。

关注微信公众号,获取最新推送~

加微信,深入交流~