webpack-dev-server和HMR原理

webpack-dev-server

webpack-dev-server只用于开发,不能在生产环境中使用。
webpack-dev-server其实是给你提供了一个简单的web服务器,使得打包后的文件能够在该服务器上运行,并且实现了实时更新的功能。
配置dev-server之后,我们改动css、js文件之后保存,webpack-dev-server会自动帮我们打包文件到内存,并且自动帮我们刷新页面,改变页面视图。
我们可以看到浏览器左上角的图标自动发生变化,表明页面进行了刷新。
在这里插入图片描述
当页面的内容较多时,刷新页面变得很浪费时间,或者当我们打开一个弹窗时,我们希望改变弹窗上的某一个视觉,在弹窗不关闭的情况下,能够更新页面部分视图,这就需要配置热更新(HMR)。
webpack.config.js 配置:
在这里插入图片描述
上面两项配置了热更新,重新打包,重新npm start,再改变css样式,保存,发现图标并没有转动,说明页面没有刷新,但是页面上的样式变了,这就是热更新,只替换发生变化的模块。

模块热更新的原理(HMR)

HMR帮助我们做了什么?
使用webpack-dev-server之前,当我们修改文件之后,我们需要手动重新打包,然后刷新浏览器才能看到我们改动的内容,而且还需要恢复之前页面的状态(比如重新打开弹窗)。webpack-dev-server配置了HMR之后,这些HMR都替我们做了。
接下来,我们来讨论一下HMR的工作原理:
在这里插入图片描述
上图是webpack和webpack-dev-server之间配合进行模块热更新的原理图。
上图底部红色框内是服务端,而上面的橙色框是浏览器端。
绿色的方框是 webpack 代码控制的区域。蓝色方框是 webpack-dev-server 代码控制的区域,洋红色的方框是文件系统,文件修改后的变化就发生在这,而青色的方框是应用本身。
上图表示了从代码修改到模块热更新的整个过程,图中的数字已经表示了整个过程。
第一、二步:
是weback和webpack-dev-server之间的交互,是webpack-dev-server的中间件webpack-dev-middleware通过webpack暴露的api来watch监听文件的变化,当文件发生变化时,webpack重新打包,并告知webpack将打包后的文件存放在内存中。
问题1:为什么要将打包后的文件存放在内存中,而不是文件目录下?
webpack-dev-middleware将原本webpack的outputFileSystem 替换成了MemoryFileSystem 实例,这样打包后的文件就存放在内存中了,访问内存中的文件比访问文件目录下的文件更快,而且减少了代码写入文件的开销,便于开发。
第三步:
webpack-dev-server监听文件变化时,只会监听contentBase下的js,css文件等,不会监听html等静态文件的变化,当设置devserver.watchContentBase为true时,webpack-dev-server也会监听html等静态文件的变化,当发生变化时,会通知浏览器进行
刷新
(并不是HMR)。
第四步:
是webpack-dev-server内部的webpack-dev-middleware和client之间通过sockjs在浏览器和服务器之间建立websocket链接,webpack-dev-server会监听webpack的compile的done事件,当编辑完成后,把html文件是否发生变化、最新打包的hash值传递给浏览器端,浏览器根据这些来作出相应的操作。
第五步:
client负责接收服务端发送过来的信息,包括hash值和ok消息,先将hash值存放起来,当接收到ok值之后,根据hot的配置,来决定是否进行下一步热更新。如果有hot的配置,就调用webpack/hot/emitter将最新的hash值传递给webpack,将热更新的控制权交给webpack,如果没有配置热更新,就调用location.reload方法直接刷新页面。

// webpack-dev-server/client/index.js
hash: function msgHash(hash) {
    currentHash = hash;
},
ok: function msgOk() {
    // ...
    reloadApp();
},
// ...
function reloadApp() {
  // ...
  if (hot) {
    log.info('[WDS] App hot update...');
    const hotEmitter = require('webpack/hot/emitter');
    hotEmitter.emit('webpackHotUpdate', currentHash);
    // ...
  } else {
    log.info('[WDS] App updated. Reloading...');
    self.location.reload();
  }
}

在这里插入图片描述

第六步:
HotModuleReplacement.runtime是HMR的中枢,接受到上一步传递给他的hash值,它通过JsonpMainTemplate.runtime向服务器发送ajax、jsonp请求,分别请求更新的文件列表、最新的代码模块,返回给HMR runtime,进行模块热更新。
在这里插入图片描述
上图中,蓝色部分是我改动某个js文件之后保存之后,发送到浏览器的websocket信息,client接受到ok的信息之后,根据hot设置将hash值发送到webpack。webpack的三个模块通过ajax和jsonp请求,请求了改动的文件列表和改动的模块代码(图中绿色的部分),HMR runtime,依此进行模块热更新。

问题2:
为什么更新模块的代码不通过websocket直接发送到浏览器,而是要通过webpack来获取数据?
功能解耦,各司其职,client值负责消息的传递,而不负责新模块的获取,这些工作是由HMR runtime来做的,这样做的话,我们就算不用webpack-dev-server,也可以用webpack-hot-middleware和webpack配合来实现热更新。

第七步:
最后一步就是HMR runtime进行热更新。热更新主要分为三步:找到变化的模块和依赖,删除过期的模块和依赖,将新的模块添加到modules中。
问题3:
当模块的热替换过程中,如果替换模块失败,有什么回退机制吗?
当替换失败时,直接刷新页面。

第八步:
实现了热更新之后,其实我们的业务代码并不知道打包代码发生了变化,我们需要重新添加模块更新后的处理函数,将代码的变化更新到页面上。

// index.js
if(module.hot) {
    module.hot.accept('./hello.js', function() {
        div.innerHTML = hello()
    })
}

参考文章:https://zhuanlan.zhihu.com/p/30669007

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于webpack-dev-server的用法,我可以告诉你,webpack-dev-server是一个用于开发环境的快速web服务器,它可以使用内存中的文件系统来提供静态文件服务,可以支持热模块替换(HMR)。它可以通过添加--hot参数来启用热更新,可以通过添加--inline参数来启用实时重载,还可以添加--open参数来自动打开浏览器。 ### 回答2: webpack-dev-server 是一个基于 Node.js 的轻量级开发服务器,用于在开发阶段快速启动和调试 Webpack 构建的应用程序。 使用 webpack-dev-server 需要先全局安装 webpack 和 webpack-dev-server,然后在项目中安装 webpack 和 webpack-cli。 使用 webpack-dev-server 的基本用法如下: 1. 在项目的配置文件中(比如 webpack.config.js),设置 entry、output 和其他需要的配置。 2. 安装好 webpack-dev-server 后,在终端输入 `webpack-dev-server` 启动服务器。 3. 默认情况下,webpack-dev-server 会启动在 localhost:8080 上,可以在浏览器中访问该地址来查看编译后的应用。 4. webpack-dev-server 在内存中编译和打包应用程序,并通过 WebSocket 将应用程序的修改通知到浏览器,实现热模块替换(Hot Module Replacement)的功能。 5. webpack-dev-server 还提供了一些额外的配置选项,比如设置监听的端口号、是否自动打开浏览器、是否使用 HTTPS 等等。这些选项可以在启动 webpack-dev-server 时通过命令行参数或在配置文件中进行配置。 总结来说,webpack-dev-server 是一个方便的工具,能够帮助我们快速启动和调试 Webpack 构建的应用程序,在开发过程中提供热更新的功能,提高开发效率。 ### 回答3: webpack-dev-server是一个为开发环境提供的快速开发服务器。它是一个基于Node.js的工具,能够在本地运行webpack打包后的应用,以便于开发人员能够实时预览和调试应用。 使用webpack-dev-server的步骤如下: 1. 首先,在项目的根目录中安装webpack-dev-server,可以通过npm或者yarn进行安装。例如,在命令行中输入`npm install webpack-dev-server --save-dev`。 2. 在webpack配置文件中进行相应的配置。需要注意的是,配置文件中需要添加`devServer`选项,并设置一些属性,例如`contentBase`指定服务器启动的文件目录,`port`指定服务器运行的端口号等等。这些配置可以根据自身的需求进行调整。 3. 在项目中添加一个启动脚本。在项目的`package.json`文件中的`scripts`字段中添加一个脚本,例如`"start": "webpack-dev-server"`。然后,在命令行中输入`npm start`即可启动webpack-dev-server。 4. 此时,webpack-dev-server会根据配置文件中的选项,启动一个本地服务器,并监听指定的端口。在浏览器中打开`localhost:port`(port为配置文件中设置的端口号),即可在实时预览应用程序。 webpack-dev-server还提供了一些其他的功能,例如热模块替换(Hot Module Replacement),它能够在应用代码变动时,自动刷新浏览器,以保持应用状态的连续性。 总而言之,webpack-dev-server是一个非常方便的工具,能够提高开发效率,实时预览和调试应用程序。它简化了项目的配置过程,并提供了一些有用的功能,确保开发人员能够更加便捷地进行开发工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值