从零实现 vite(先导篇)

脑洞前端

共 1256字,需浏览 3分钟

 ·

2021-07-05 03:07


mono-vite

基本知识

假设我们有如下两个 JS 文件。

即两个 esm 的模块, 并且 main.mjs 依赖 utils.mjs。

如上代码可以被支持 ESM 的浏览器所识别,但并不意味着其可以直接被运行。比如我的代码依赖了 npm 包和一些相对路径,这些浏览器是无法识别的。

而 vite 则解决了这个问题。由于 vite 本质还是依赖了浏览器的特性,因此可以直接利用浏览器的诸如缓存的特点来提高性能。

除此之外, 每次修改文件,比如修改上面的 main.mjs 或者  utils.mjs 中的任意一个文件并不会导致“打包”全部文件。这是因为 vite 根本没有打包过程, 而是直接将修改过的文件热更新到浏览器的内存中。

比如,我修改了 main.js,那么就直接发送一个 http 去请求最新的 main.mjs 文件,而 utils.mjs 则可以继续使用浏览器缓存中的内容即可。

我画了一个简单的原理图给大家参考一下。

模块之间的关系如上图所示。并且这个时序指的是「更新一个文件之后的更新流程」

我将其分成了若干模块,它们分别是:

  • 浏览器。用于处理 ESM
  • 文件系统。用于存储源代码文件。
  • vite-server。响应浏览器,并返回内容。这些内容主要是最新的文件系统中的文件,除此外还有注入到 client 中的代码等。
  • hrm-sever。用于根据模块的依赖关系确定应该更新的模块,并触发相应的回调函数。
  • watcher。监听文件系统的变更,当文件内容发生变化的时候,通知 hmr-server。之后 hmr-server 再去通过 websocket 通知浏览器获取最新的模块(按需请求)。

如何确定需要更新的模块

我们可以根据 esm 的 import 关系生成一个依赖图。并将图中的所有点都放入一个哈希表中,key 可以是文件的请求路径,value 可以是模块本身,这样就可以根据请求路径在 的时间获取到指定的节点。之后我们可以遍历依赖图,并依次发起浏览器的 http 请求获取最新内容,并触发回调函数。

如下图红色的模块被更新,我们通过 时间获取到它,然后依次遍历虚线的两个模块,发起请求获取其最新模块内容,最后触发注册到这「三个」模块上的回调函数即可。

回调函数通过  module.hot.accept 注册,具体参考 hmr 相关文档。

一个更复杂的例子:

之后我会根据这个原理图带大家一步步实现一个 mono-vite(等西法有时间的)。


爱心三连击

1.看到这里了就点个在看支持下吧,你的在看是我创作的动力。

2.关注公众号脑洞前端,获取更多前端硬核文章!加个星标,不错过每一条成长的机会。

3.如果你觉得本文的内容对你有帮助,就帮我转发一下吧。



浏览 18
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报