Vue 项目之 Webpack 中 DevServer 的模块热替换(1)

680 阅读4分钟

「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

1. devServer 开启模块热替换

devServer 除了 contentBase 属性之外其实还有很多其它的属性,下面再讲一个 hot 属性,将其设置为 true 就能开启模块热替换功能。

1.1 认识模块热替换(HMR

  • 什么是 HMR 呢?
    • HMR 的全称是 Hot Module Replacement,翻译为模块热替换
    • 模块热替换是指在应用程序运行过程中替换、添加、删除模块,而无需重新刷新整个页面
  • HMR 通过以下几种方式,来提高开发速度:
    • 不重新加载整个页面,这样可以保留某些应用程序的状态不丢失
    • 只更新需要变化的内容(模块/文件)节省开发的时间
    • 修改了 cssjs 源代码时,会立即在浏览器更新,相当于直接在浏览器的 dev tools 中修改样式;
  • 如何使用 HMR 呢?
    • 默认情况下,webpack-dev-server 支持 HMR,我们只需要开启即可,在这个模式下,它会尝试在重新加载整个页面之前使用 HMR 进行更新
    • 在不开启 HMR 的情况下,当我们修改了源代码之后,整个页面会自动刷新,使用的是 live reloading
    • 更多信息可以查阅官方文档:webpack.js.org/concepts/ho…

在演示 HMR 的效果之前,我们先把项目跑起来(npm run serve),跑起来后,我们在 src/js/element.js 文件的最后添加一行代码:console.log('哈哈哈');,保存之后,你会发现 webpack 会对代码进行重新编译:

image-20211128130228302

编译成功之后,我们来到浏览器中看下效果:

image-20211128130433545

你会发现,控制台中成功打印出了“哈哈哈”。

如果我们再把打印的内容修改为“呵呵呵”后再进行保存,就又会对代码进行重新编译:

image-20211128131723437

并且,浏览器页面也会自动进行刷新,控制台会重新打印最新的内容:

image-20211128131938209

也就是说,现在 devServer 已经帮助我们实现了这样的功能:只要源代码发生改变了,devServer 就会让 webpack 自动帮助我们重新编译源代码,重新编译成功后,浏览器也会自动刷新。

但是,我们可以思考一下,浏览器刷新是不是一个好的现象呢?

不好,有时候我们是不希望浏览器随随便便刷新的。举个例子,假如页面上有个计数器,起初当前计数为 0,在经过一段时间的计数后,当前计数终于来到了 99。那么通常我们都是需要让这个当前计数为 99 的状态一直保持着,以便后续使用这个 99 的状态做其它的操作。也就是说,有时候我们需要保留页面中的某些状态。但是,如果这时浏览器刷新了页面,这些状态就都会丢失或者还原为了初始状态。当然,仅对于一个数字而言可能还不是很要紧,但是,我们的项目中还会有诸如登录状态、保存到 Vuex 里面的一大堆数据(状态),如果就因为(像我们前面那样)只改了一下打印的内容,就让浏览器自动刷新,导致浏览器中原来的所有状态都丢失了(因为浏览器刷新会清除当前所有的状态,你可能会说:“那我做 localStorage 缓存啊”,但那是一种缓存的做法,你不可能说我们改变了一下数字,就立马缓存一下数字,这肯定是不现实的),肯定是非常不好的。

此外,刷新浏览器的第二个问题是性能问题。因为刷新浏览器会去加载整个页面中的所有内容,即便我们仅修改了一个地方的代码,假如我们的应用程序比较大,那么肯定是非常消耗性能的。

总结一下,刷新浏览器有两个问题:

  1. 页面状态丢失问题;
  2. 性能问题;

所以我们希望浏览器能够只针对我们修改的文件(在 webpack 中把一个文件看成一个模块)来做相应的更新。那么,我们就可以开启模块热替换了。