Published on

vite-1.0简单介绍

Authors
  • avatar
    Name
    祝你好运
    Twitter

vite是通过使用ES Module来实现开发环境秒开,快速HMR的。这个ES Module说白了我们前端开发者应该每天都在用,因为我们都在用import,export来导入导出模块。不过如果你还是用的CommonJS的require,那就不是ES Module。

主思路

有了上面的思路,那就简单了,我们就是要把所有的代码,搞成ES Module,然后用一个Koa搭建一个HTTP服务器,然后当浏览器访问的时候,返回相应的代码,这就是主要的思路。

HMR (Hot Module Replace)

首先说什么是HMR,我们可以举一个React的例子,我们的React组件一般会对应到DOM上,当我们修改这个组件的时候,对应的DOM就会更新。那如果我们能做到,不刷新整个页面,只刷新那块更新的DOM,效率是不是大增?这个局部刷新,就是HMR。怎么样在我们修改组件的时候通知浏览器刷新?用WebSockets,然后在首页(比如index.html)注入client的代码,服务端启动WebSockets的服务端,然后监听文件改动。当文件有改动的时候,通知客户端,客户端拿到改动信息后,局部刷新页面就好了。当然这里还有一些别的辅助工具,后面详细讲。

功能扩展

说完上面的WebSockets,那就不得不提一下vite的plugin系统,本身vite就是一个koa服务器,我们知道koa上面是可以加很多中间件,然后这些中间件就是洋葱模型中的层。vite就有各种中间件,比如处理CSS的serverPluginCss.ts,比如处理TypeScript的serverPluginEsbuild.ts。比如处理静态文件的serverPluginServeStatic.ts

开发环境秒开

这里首先要强调是开发环境,生产环境vite是依赖Rollup的。但是第一次运行项目的时候,vite是需要一个优化的,它会用[Rollup]来把node_modules下面那些CommonJS的包打成ES Module,放到node_modules/.vite_opt_cache/下面。然后后续开发的时候,就直接从缓存加载这些package。例如React就会被提前打包。

路径解析

上面提到React会被提前打包,那当我们的文件中引入React的时候,import React from 'react',具体会怎么引入文件呢?其实返回到浏览器之前,这些代码都被修改过了,这些修改大部分是在src/node/server/serverPluginModuleRewrite.ts完成的。比如前面那个对React的引入,会被修改为

import $viteCjsImport0_react from "/@modules/react.js";
const React = $viteCjsImport0_react;

那这个/@modules/react.js又是如何对应到缓存里面的node_modules/.vite_opt_cache/文件呢?这个是通过src/node/server/serverPluginModuleReresolve.ts来完成的。

代码结构介绍

当我们要分析vite的源代码的时候,我们的注意力主要集中在src上,更进一步,主要集中在src/node上。src/client里面就是HMR相关的,比如建立WebSockets相关的,还有当服务端监听到文件变更后,发给客户端,也就是浏览器,客户端相应的处理代码。在我们深入研究HMR之前,不需要看这些。

node
  - build     # 生产打包相关
  - optimizer # 预打包,把node_modules下面的一部分包打成ES Module
  - server    # 我们启动的koa服务器相关,以及那些中间件
  - cli.ts    # 我们的vite命令行脚本

上面就是我们需要重点看的代码。

总结

其实从比较高的抽象层次来看的话,其实vite也很简单,就是koa服务器来来返回ES Module,外加各种优化。明白主要架构之后,后面再展开讲就不容易迷失在细节之中。