webpack 完全指南:文件监听和热更新
文件监听
我们每次在对项目进行修改后,都要手动跑 webpack 打包命令,是不是很烦?Webpack 就不能帮我们监听文件的变化,然后在文件发生修改时自动编译打包吗?
webpack 说:我可以啊!我可以通过轮询去检查文件的最后编辑时间是否发生变化,从而判断是否需要重新编译(文件监听的实现原理)。
webpack 中开启监听模式,有两种方式:
- 启动 webpack 命令时,带上 
--watch参数。 - 在配置 
webpack.config.js中设置watch:true。 
--watch
可以在 package.json 中配置监听命令:
{
  // ...
  "scripts": {
    "watch": "webpack --watch"
  }
}
然后跑 npm run watch,webpack 就进入了监听模式
watch: true
在 webpack.config.js 中配置监听模式:
module.exports = {
  //...
  watch: true,
};
watchOptions
通过 watchOptions 可以定制 watch 模式的选项。
watchOptions.aggregateTimeout
当第一个文件更改,会在重新构建前增加延迟。也就是说,webpack 会将这段时间内进行的任何其他更改都缓存起来,最后在一次重新构建中完成。默认为 200 毫秒。
// webpack.config.js
module.exports = {
  //...
  watchOptions: {
    aggregateTimeout: 600,
  },
};
watchOptions.ignored
忽略一些不需要监听的庞大文件,比如 node_modules,可以优化性能。
// webpack.config.js
module.exports = {
  //...
  watchOptions: {
    ignored: /node_modules/,
  },
};
watchOptions.poll
指定轮询的时间间隔。
module.exports = {
  //...
  watchOptions: {
    poll: 1000, // 每秒检查一次变动
  },
};
文件监听的缺陷
虽然,开启 webpack 的文件监听后,可以在源码发生改变时,自动的重新构建出新的输出文件;但是,还是需要 手动刷新浏览器 才能看到更新内容。
那么,这个“痛点”有没有解决方案吗?webpack 的 热更新 奉上。
热更新
热更新可以让我们在文件发生修改后,不刷新浏览器,页面就能自动更新。

在了解热更新流程之前,有必要对一些名词进行了解:
- bundle.js: 构建输出的文件。
 - Webapck Compiler: webpack 的编辑器,将 JS 源代码编译为 bundle.js。
 - HMR Server: 将热更新的文件传输给 HMT Runtime。
 - Bundle Server: 在浏览器中,可以以服务器的形式访问文件
 - HMR Runtime: 在打包阶段被注入浏览器的 bundle.js 中,使 bundle.js 和 Server 建起链接(Web Socket),在文件发生变化时,自动更新 bundle.js 中的 Code。
 
⬆️ 然后我们具体走一下流程,从上图可以看出 热更新的完整流程分为两个阶段:
- 
启动阶段:
- 1、在文件系统中进行编译
 - 2、通过 Webpack Compiler 进行打包
 - A、将打包好的文件传输给 Bundle Server
 - B、启动服务,使浏览器以 Server 的形式访问 bundle.js
 
 - 
文件更新阶段:
- 1、文件系统中的内容发生变化
 - 2、通过 Webpack Compiler 进行打包
 - 3、将打包好的文件传输给 HMR Server,分析哪些代码发生了改变
 - 4、HMR Server(服务端) 将改变通知到 HMR Runtime(客户端)
 - 5、HMR Runtime 更新 bundle.js 中的代码
 
 
webpack-dev-server
webpack-dev-server 为我们提供了一个基本的 web server,并且具有 live reloading(热更新)功能。
webpack-dev-server 并不会输出文件,也就是说不会发生磁盘的 I/O 操作,它是将 bundle 文件保留在内存中,所以相比 watch 性能更优。
首先,安装一下 webpack.config.js:
npm i webpack-dev-server -D
然后,我们修改一下 webpack.config.js:
- 只在开发环境需要用到 
webpack.config.js,所以修改mode: 'development' - 告知 dev server,将 dist 目录下的文件 serve1 到 localhost:8080 下。
 
const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "index.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "babel-loader",
      },
    ],
  },
+  mode: "development",
+  devServer: { static: "./dist" },
  performance: {
    hints: false,
    maxEntrypointSize: 512000,
    maxAssetSize: 512000,
  },
};
添加一个可以直接运行 dev server 的 script,--open 表示每次构建完成后自动打开页面:
// package.json
{
  // ...
  "script": {
    // ...
    "dev": "webpack-dev-server --open"
  }
}
现在,在命令行中运行 npm run dev,我们会看到浏览器自动加载页面(默认在 http://localhost:8080/index),试试看!
webpack 系列
Footnotes
- 
将资源作为 server 的可访问文件 ↩
 
转载自:https://juejin.cn/post/7029625287721615390