webpack之文件监听及热更新

webpack 的文件监听

文件监听是在源码发生变化时,自动重新构建出新的输出文件。
webpack开启监听模式,有两种方式:

  • 启动 webpack 命令时,带上 --watch 参数。
    {
      "name": "project",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "webpack",
        "watch": "webpack --watch"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
    }
    
  • 在配置 webpack.config.js 中设置 watch: true
    但是,这种方式需要每次手动刷新浏览器

webpack文件监听的原理

webpack会轮询判断文件的最后编辑时间是否变化。
某个文件发生了变化,并不会立即告诉监听者,而是先缓存起来,等 aggregateTimeout

module.exports = {
    // 默认是false,即不开启
    watch: true,
    // 只有开启监听模式时,watchOptions才有意义
    watchOptions: {
        // 默认为空,不监听的文件或者文件夹,支持正则匹配
        ignored: /node_modules/,
        // 监听到变化发生后会等300ms再去执行,默认300ms
        aggregateTimeout: 300,
        // 判断文件是否发生变化是通过不停询问系统指定文件有没有变化实现的,默认每秒问1000次
        poll: 1000
    },
};

热更新

使用webpack-dev-server

安装依赖

npm i -D webpack-dev-server
  • WDS 不刷新浏览器
  • WDS 不输出文件,而是放在内存中
  • 使用 Hot ModuleReplacementPlugin插件
{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --open"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
}

因为WDS主要是在开发过程中使用,生产环境是用不到的,所以我们将mode改为development,然后再引入webpack自带的Hot ModuleReplacementPlugin插件,由于该插件是内置的,所以我们先引入webpack,再将插件加进来,最后还要配置一下devServer

const webpack = require('webpack');

module.exports = {
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        contentBase: './dist', // 服务的基础目录
        hot: true   // 开启热更新
    }
};

升级填坑

但是,当你升级webpack4 ---->webpack5时,如果你的版本是webpack-cli 4*时,就会报错

Error: Cannot find module 'webpack-cli/bin/config-yargs'

{
  "webpack": "^5.36.0",
  "webpack-cli": "^4.6.0",
  "webpack-dev-server": "^3.11.2"
}

这是,因为在webpack-cli 4*中,作者删除了config-yargs,所以会报错
这里有两种解决方案:

  • 临时解决方案:将webpack-cli版本降级到webpack-cli 3*
  • 终极解决方案:修改配置文件,使用webpack serve替代webpack-dev-server也就是将配置项的 "dev": "webpack-dev-server --open"改为"dev": "webpack serve --open"

使用webpack-dev-middleware

WDM将webpack输出的文件传输给服务器,适用于灵活的定制场景。
使用这种方式,通常需要再引入一个server,一般是express或者koa

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

app.listen(3000, function(){
  console.log('Example app listening on port 3000!\n');
})

热更新原理分析

  • Webpack Compile(webpack的编译器):将JS的源代码编译成Bundle
  • HMR Server:将热更新的文件输出给 HMR Runtime
  • Bundle server:提供文件在浏览器的访问,可以让你的文件以服务器的方式访问,比如“http://localhost:8080/search.html”
  • HMR Runtime:会被注入到浏览器端的bundle.js里面,bundle.js就可以与服务器建立一个连接,通常这个连接是一个websocket,当它收到一些数据,一些回包之后,就会自动更新文件
  • bundle.js:构建输出的文件

热更新的过程

  • 启动阶段,是在文件系统里面,文件系统的一个编译,就是将初始的代码经过Webpack Compile进行一个打包,打包好以后,将打包好的文件传输给bundle server,也就是一个服务器,bundle server就可以让这个文件以server的方式让浏览器访问到
  • 更新阶段,如果本地开发时,有文件发生了变化,这时的流程是一个文件系统的变化,然后代码还是会经过Webpack Compile进行编译,编译好以后会将代码发送给HMR ServerHMR Server就可以知道哪些模块(源代码部分的模块)发生了变化,然后HMR Server就会通知HMR runtimeHMR Server是在服务端,HMR runtime是在客户端)。通常是以json的格式进行数据传输,传递给HMR runtime之后,HMR runtime就会更新我们的代码,最后我们的代码进行了改变,并且不需要刷新浏览器。

你可能感兴趣的:(webpack之文件监听及热更新)