- Published on
vite-1.0 CSS插件解读
- Authors
- Name
- 祝你好运
这个src/client/client.ts
是HMR的客户端,我们之前提到过,HMR是通过WebSockets来做的,那它肯定是需要一个客户端和一个服务端的,通常就是客户端来连接服务端,然后服务端在特定条件下发送消息,客户端接收并处理消息,我们来看下代码主结构:
主结构

处理消息
我们发现最终所有的更新都会走到61行的
handleMessage
。vue相关的我们可以不管,因为这个是只针对vue的,和vite关系不大的。还有一个就是style有update和remove,但是JS就只有update,为啥JS没有remove?我还特意去看了下chokidar的文件删除的时间,删除是unlink
,但是vite里面并没有监听unlink
,后来我想了下,其实监听unlink
没啥用,因为文件删除完,我们还是需要手动更新那些导入了这个被删除文件的文件,这样就有了update
。那为啥CSS就有remove?这个remove其实只有vue里面会调用,普通的CSS更新只会先走update,update里面会先remove,再add。 
style更新
样式更新是这样一个流程:
- 用户更新样式文件
- chokidar触发
change
(serverPluginCss
第43行) serverPluginCss
发送style-update
给WebSockets客户端- 客户端拉去最新的代码
- 服务端返回最新的CSS代码
- 如果是
<link>
就直接挂在上去了,如果import,就会走ES module的路子,类似JSONP的套路,会执行到updateStyle
,然后就更新了样式
下图就是根据是<link>
或者import
来走不同的路子

再来看下具体是如何更新的,首先175行就是通过文件名id拿到之前生成的具体元素,这个文件名id是在。具体元素有可能是HTMLStyleElement
,也就是<style>...</style>
。也有可能是CSSStyleSheet,这个可以直接用新的文件内容替换。
下面的逻辑一行行解释的话,效果也不理想,我来说一下大致思想吧。如果是纯的CSS内容,而且浏览器支持CSSStyleSheet
,就用它挂载到document.adoptedStyleSheets
上。否则就生成<style>...</style>
插入到document.head
里面。然后还需要注意这里是更新,也就是需要根据情况来移除上次的结果。

style移除
这里就两种情况,一种是移除<style>...</style>
,另一种就是过滤document.adoptedStyleSheets
,我觉得213行应该是无用代码,等分析vite 2.0代码的时候看它还在不在。

JS更新
JS的更新是用了队列的:
queueUpdate(updateModule(path, changeSrcPath, timestamp))