你是一个码农,拿到了一个新的项目,项目使用了 Vite 作为开发工具。拿到项目的第一件事,当然是把项目先跑起来。跑起来?
这个时候通常会先看项目的相关说明文档,如何安装依赖,如何启动项目等等。于是看完项目相关文档后,你使用了npm install安装了项目依赖,
然后使用npm run dev启动项目。项目启动后,你看到了一堆日志,然后打开了浏览器,看到了项目的首页。

这个时候你可能会想,Vite 是如何启动的呢?为什么我只需要运行npm run dev就能启动项目呢?这篇文章就来探讨一下 Vite
开发服务器的启动原理。

开发服务器

开发服务器,这就涉及到了服务器端的东西,通常我们会使用 Node.js 来搭建一个服务器。Vite 也是如此,它使用了一个 Node.js
服务器来启动项目。
但是他是如何解析项目中的.vue文件的?浏览器又不认识.vue文件没办法渲染呀。等等等等还有很多问题需要解决。
这里看一张图

这是一个示例工程,可以看到开发服务器给我们返回了一个 App.vue 文件 可以看到里面其实都是 js 的语法格式,这是因为 Vite
在启动时会将 .vue 文件解析成一个 js 文件,这样浏览器就可以识别了。
这个转换涉及到模板编译和ATS的工作,这里不做深入讨论。

模拟Vite启动过程

下面我们基于node.js来实现一个简单的开发服务器,来粗略的模拟一下Vite的启动过程。

1
2
3
4
5
6
7
8
# 新建一个工程目录
mkdir my-vite-server
# 进入工程目录
cd my-vite-server
# 初始化一个node.js工程
yarn init -y
# 安装koa
yarn add koa

新建4个文件分别是index.jsmain.jsindex.htmlApp.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 这里只是一个示例工程,实际开发不要这么写服务端代码,只是为了更好的get到vite的启动原理
const Koa = require('koa');
const fs = require('fs');
const path = require('path');


const app = new Koa();

app.use( async (ctx) => {
console.log("ctx", ctx.request, ctx.response);
if(ctx.request.url === '/'){
const indexContent = await fs.promises.readFile(path.resolve(__dirname, './index.html')) //字符串路径拼接
ctx.response.body = indexContent;
ctx.response.set(
'Content-Type',
'text/html'
)
}
// 实际不会这么写,一般都会有中间件去做路径解析
if(ctx.request.url === '/main.js'){
const mainContent = await fs.promises.readFile(path.resolve(__dirname, './main.js')) //字符串路径拼接
ctx.response.body = mainContent;
ctx.response.set(
'Content-Type',
'text/javascript'
)
}
if(ctx.request.url === '/App.vue'){
const vueContent = await fs.promises.readFile(path.resolve(__dirname, './App.vue')) //字符串路径拼接
ctx.response.body = vueContent;
ctx.response.set(
'Content-Type',
'text/javascript'
)
}
})

app.listen(5173, () => {
console.log('vite-dev-server is running at http://localhost:5173');
})
1
2
import "./App.vue"
console.log("tttets///")
1
2
3
4
5
6
7
8
9
10
11
12
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Document</title>
</head>
<body>
<h1>hello world</h1>
<script src="./main.js" type="module"></script>
</body>
</html>
1
console.log("app123vue")

这些文件都准备好了之后,可以启动这个服务器了。

1
2
# 启动服务器, nodemon是一个node.js的热更新工具,可以自动重启node应用,可以通过npm install -g nodemon安装
nodemon index.js

这个时候打开浏览器访问http://localhost:5173,可以看到页面上打印了hello world,控制台打印了app123vue , tttets///

为什么这里的vue文件不写vue的模板语法,因为还是和前文所说,涉及到vue的模板编译和ATS的工作,如果想要模拟出效果还是挺麻烦的,vite的[源码](https://github.com/vitejs/vite)。