11. devServer、HMR

88 阅读2分钟

自动编译有以下三种方式

Webpack watch

在该模式下,webpack依赖图中的所有文件,只要有一个发生了更新,那么代码将被重新编译
开启 watch,在 package.json 的 scripts 中添加一个 watch 的脚本。 image.png

webpack-dev-server

安装:npm install --save-dev webpack-dev-server webpack-dev-server 在编译之后不会写入到任何输出文件。而是将 bundle 文件保留在内存中。

  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch",
    "serve": "webpack serve"
  }

webpack-dev-middleware

webpack-dev-middleware 是一个封装器(wrapper),它可以把 webpack 处理过的文件发送到一个 server。

自己实现 devserver: QQ截图20231104163254.png

QQ截图20231104163655.png webpack(config) webpack根据配置信息开始编译 compiler 是编译后的对象

模块热替换(HMR)

模块热替换:应用程序运行过程中,替换、添加、删除模块,而无需重新刷新整个页面。
HMR通过如下几种方式,来提高开发的速度

  1. 不重新加载整个页面,这样可以保留某些应用程序的状态不丢失
  2. 只更新需要变化的内容,节省开发的时间
  3. 修改了css、js源代码,会立即在浏览器更新,相当于直接在浏览器的devtools中直接修改样式

开启HMR
默认情况下,webpack-dev-server已经支持HMR,我们只需要开启即可。 修改webpack的配置:

  devServer: {
    hot: true
  }

浏览器可以看到如下效果: image.png
此时 css 样式经过 style-loader 处理,style-loader已经具备 HMR 功能了。 但是 js 还不行,js修改了之后,还是要刷新整个页面。需要去指定哪些模块发生更新时进行HMR

if (module.hot) { // 低版本浏览器可能不支持
  module.hot.accept("./math.js", () => {
    console.log("math模块发生了更新~");
  });
}

如上述代码,每一个模块的修改如果都在打包入口文件写module.hot.accept代码,就太繁琐了,vue 或 react框架都有自己的 HMR。

框架的 HMR

1. React的HMR
在之前,React是借助于React Hot Loader来实现的HMR,目前已经改成使用react-refresh来实现了
安装:npm install -D @pmmmwh/react-refresh-webpack-plugin react-refresh
修改 webpack.config.js 和 babel.config.js 文件 image.png 2.Vue的HMR
vue-loader 加载的组件默认进行 HMR 的处理
安装:npm install vue-loader vue-template-compiler -D 配置 webpack.config.js: image.png

HMR的原理

webpack-dev-server会创建两个服务:提供静态资源的服务(express)和Socket服务(net.Socket),express server负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析),HMR Socket Server,是一个socket的长连接,当服务器监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk),通过长连接,可以直接将这两个文件主动发送给客户端(浏览器),浏览器拿到两个新的文件后,通过HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新。 image.png