- Published on
vite-1.0 CSS插件解读
- Authors

- Name
- 祝你好运
这个src/client/client.ts是HMR的客户端,我们之前提到过,HMR是通过WebSockets来做的,那它肯定是需要一个客户端和一个服务端的,通常就是客户端来连接服务端,然后服务端在特定条件下发送消息,客户端接收并处理消息,我们来看下代码主结构:
主结构
这个文件跟之前看的插件不一样,插件是作为koa的中间件来运行的,这个文件是WebSockets的客户端代码,它是以ES Module直接注入到HTML文件里面的(被import),然后当浏览器通过网络请求拿到这个文件的内容的时候,是会直接执行了,所以才有了上面红色箭头指向的关键代码。处理消息
我们发现最终所有的更新都会走到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))