前端构建工具Vite
前言
若文章有误,欢迎读者留言反馈兼容性注意:Vite需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
认识Vite
Webpack是目前整个前端使用最多的构建工具,但是除了webpack之后也有其他的一些构建工具:
- 比如
rollup、parcel、gulp、vite等等 rollup一般用来打包一些框架,更为常见;parcel号称零配置的打包工具,但是本身比较大,用的会比较少一点;gulp用来做自动化比较多一点;
什么是vite呢?官方的定位∶下一代前端开发与构建工具;
如何定义下一代开发和构建工具呢?
- 我们知道在实际开发中,我们编写的代码往往是不能被浏览器直接识别的,比如
ES6、TypeScript、Vue文件等等; - 所以我们必须通过构建工具来对代码进行转换、编译,类似的工具有
webpack、rollup、parcel; - 但是随着项目越来越大,需要处理的
JavaScript呈指数级增长,模块越来越多; - 构建工具需要很长的时间才能开启服务器,
HMR也需要几秒钟才能在浏览器反应出来;
Vite(法语意为”快速的”,发音/it/)是一种新型前端构建工具,能够显著提升前端开发体验。
Vite的构造
它主要由两部分组成:
- 一个开发服务器,它基于原生
ES模块提供了丰富的内建功能,HMR的速度非常快速; - 一套构建指令,它使用
rollup打开我们的代码【内置rollup】,并且它是预配置的,可以输出生成环境的优化过的静态资源;
浏览器原生支持模块化
创建一个目录作为项目根目录,在里面创建一个src文件夹和一个main.js文件,在其中随便写点代码:1
console.log("Hello World")
再到src文件夹下创建一个js文件夹,再创建一个math.js文件,书写一点js代码1
2
3export function sum(num1, num2) {
return num1 + num2
}
然后导入到main.js文件中1
2
3
4import { sum } from "./js/math"
console.log("Hello World")
console.log(sum(1, 2))
接着再到项目根目录下创建一个index.html文件,再把main.js引入1
2
3
4
5
6
7
8
9
10
11
12
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./src/main.js" type="module"></script>
</body>
</html>
我们来运行这个html文件,由于没有构建工具,那么它是否能打印出结果呢?
先说结论吧,对于版本比较高的浏览器已经支持ES Module,刚刚写的import其实已经支持了,但是现在浏览器控制台运行是报错的,如果想要让浏览器认识main.js模块,必须给script添加一个属性type="module"
添加这个属性,就相当于浏览器解析时允许代码使用ES Module
接着再次运行,但是浏览器控制台依然是报错的,它说这个math找不到,注意这时我们再回头看一下刚刚导入math是似乎没加后缀名,那么这里就得注意了,原生的ES Module后缀名都是不能掉的,之前在webpack中js文件能省去,那是因为webpack有自己的查找规则,它会一个一个后缀名进行添加查找,所以这里的后缀名得加上1
2
3
4
5-import { sum } from "./js/math"
+import { sum } from "./js/math.js"
console.log("Hello World")
console.log(sum(1, 2))
然后浏览器就能正常显示了
既然浏览器能直接识别我这里的代码,如果开发里我还写了request.js文件代码里面也是ES6代码,这些代码加在一起都是模块化的,而浏览器也是支持模块化的,是不是完全意味着开发阶段不需要用构建工具,那就省去了构建这个过程,直接运行就行了;等到真正打包上线的时候,因为我们要适配更多的用户的浏览器,某些用户使用浏览器可能就不支持ES6了,我们等到打包的时候再做构建转成ES5的代码
其实这也就是Vite的基本思想
目前只是写的ES6代码,万一还有ts文件和vue文件,这肯定是没办法直接跑到浏览器上的,就算是现在最新的浏览器它也不支持
那不支持,该怎么办呢?Vite它将这些不识别的代码做了一个转化,转换为浏览器能识别的ES Module代码
虽然我们目前这些代码能跑,可是一旦有了ts代码,就不能跑了,所以还是需要构建工具
先在项目根目录下初始化一个package.json文件1
2
3
4# 创建package.json
npm init
# 快速创建package.json
npm init -y
再安装一个lodash-es包1
npm install lodash-es -S
在main.js导入使用1
2
3
4
5
6
7
8
9
10
11import _ from 'lodash-es'
// import { sum } from "./js/math"
// 原生后缀名不能掉
import { sum } from "./js/math.js"
console.log("Hello World")
console.log(sum(1, 2))
// 使用lodash
console.log(_.join(['abc', 'def'], '-'))
但是这样浏览器运行是无法加载lodash的,在webpack中是有专门的包对这种路径做解析的,浏览器它是无法加载的,不认识,应该换为下面这种写法:1
2
3
4
5
6
7
8
9
10
11
12
13// import _ from 'lodash-es'
// 浏览器无法加载上面这个包,找不到这个包所在位置
+import _ from '../node_modules/lodash-es/lodash.default.js'
// import { sum } from "./js/math"
// 原生后缀名不能掉
import { sum } from "./js/math.js"
console.log("Hello World")
console.log(sum(1, 2))
// 使用lodash
console.log(_.join(['abc', 'def'], '-'))
但是这种方式是有弊端的,在浏览器控制台network中,我们刷新一下,是可以看到浏览器有很多请求的,lodash依赖了很多其它文件,浏览器就会认为也要加载,就会把这些文件全部都加载出来,每个js文件都要发一次请求,浏览器再解析这么多文件是非常消耗性能的,虽然没有使用构建工具,源代码也能跑起来,但是会有两个弊端:
- 某些文件是不识别的【
ts文件、vue文件】 - 如果包之间的依赖太多,那么会发送过多的网络请求
vite它会帮我们解决。
Vite的安装和使用
注意: Vite本身也是依赖Node的,所以也需要安装好Node环境
首先,我们安装一下vite工具︰1
2
3
4# 全局安装
npm install vite -g
# 局部安装
npm install vite -D
这里我们只需要对于我们的这个项目进行打包,所以这里我们就用局部安装
使用一下vite1
npx vite
执行完它就会我们搭建好本地服务,浏览器上运行显示正常,这个vite它对我们的源代码做了一个构建,然后搭建了一个本地服务,浏览器访问时,访问的是vite搭建的这个本地服务,然后vite这个服务就会给我们提供这里的源代码
但是这样似乎和原来没有什么区别,这里来看第一个区别:
- 导入文件时不需要加后缀名,
vite它会帮自动我们加上后缀名的; - 想从
node_modules导入某个包,直接写上包名即可,不需要原来那样路径写很长; - 在
network中查看请求,它只有常见的几个请求了,因为它帮我们做了个打包,lodash虽然比较大,但是没有之前那么多http请求
Vite对于css、less的支持
在src文件夹中创建个css文件夹,再在其中创建个style.css文件1
2
3body {
background-color: skyblue;
}
加入依赖图,它才会进行构建、打包
回到main.js文件中1
2// 导入样式
import "./css/style.css"
回到浏览器样式生效了,这也说明了vite默认就对css做了处理,不需要像webpack那样再做什么css-loader、style-loader处理
接着我们再到main.js文件中创建个空标签1
2
3
4const titleEl = document.createElement('div')
titleEl.className = "title"
titleEl.innerHTML = "Hello vite"
document.body.appendChild(titleEl)
再到css文件夹下创建一个title.less文件1
2
3
4
5
6
7@fontSize: 50px;
@fontColor: pink;
.title {
font-size: @fontSize;
color: @fontColor;
}
加入依赖图中,回到main.js文件中1
import "./css/title.less"
这时下方也很快的出现了报错[vite] Internal server error: Preprocessor dependency "less" not found. Did you install it?
大概意思是:我们当前预处理器它需要依赖我们less工具,但这个less工具没有找到,你安装了less工具吗
之前webpack也是需要依赖less工具[lessc],只不过在vite中,不需要less-loader,但是less工具依然还是要安装
局部安装less工具【注意停掉服务】:1
npm install less -D
重新跑下服务,less文件就生效了
我们再来验证一下postcss,比如浏览器加上前缀,回到title.less文件中1
2
3
4
5
6
7
8
9@fontSize: 50px;
@fontColor: pink;
.title {
font-size: @fontSize;
color: @fontColor;
// 验证浏览器前缀
user-select: none;
}
浏览器上查看它是并没有帮我们加上浏览器前缀的,这时我们需要加上,一般会这样做:
- 我们还是需要postcss这个工具,用它来做转化
1
npm install postcss -D
注意postcss已经集合为一个小的生态,它还是需要相应的插件去实现功能,添加前缀我们可以使用之前autoprefixer插件,但是我们使用postcss-preset-env更多,它已经内置了autoprefixer插件
安装postcss-preset-env1
npm install postcss-preset-env -D
注意不是安装完就结束了,我们还需要配置,再到项目根目录下创建一个postcss.config.js文件,添加如下代码:1
2
3
4
5module.exports = {
plugins: [
require('postcss-preset-env')
]
}
这时再重新跑下服务,前缀就成功加上了,我们也能发现vite它都不需要我们做任何配置,执行效率也比webpack高很多
Vite对TypeScript的支持
在src文件夹下创建一个ts文件夹,再到其中创建一个mul.ts文件1
2
3export default function(num1: number, num2: number): number {
return num1 * num2
}
回到main.js文件中,导入使用1
2
3import mul from './ts/mul'
console.log(mul(10, 10))
重新跑一下,成功打印出结果,说明vite不需要我们做关于ts配置,直接写ts它就可以对于ts来做一些转化
Vite的原理
接上面,我们再到浏览器控制台的network中刷新一下来看一下这个请求的资源,如下图
我们可以看到它请求的文件扩展名就是less和ts
前面也提到过vite它会在本地建一个服务器,在webpack中使用的是express,而在vite1里面用的服务器是koa,但是从vite2开始便不再用koa了,用的是connect,本地服务器并不是直接把.less文件和.ts文件直接给浏览器,浏览器无法解析这两个文件的,vite的一些工具把我们编写的这两个.less文件和.ts文件做了个转化生成新的文件同时也还叫这个名字,并且这两个文件里面的代码变成了es6的js代码【我们可以在浏览器控制台的response中查看】,注意css也是变成了js代码,待会它会通过style标签注入到页面里面去的
当我们浏览器去请求这两个文件时,vite的本地服务它对于请求做了个拦截和转发,这也是它为什么要使用connect的原因,connect非常方便做这个转发,这个转发其实请求的是新生成的ES6的js`代码文件,然后返回给浏览器,浏览器就会解析,显示
如果有兴趣可以到node_modules下去找一下vite其中的package.json文件中它是有这个connect的包版本号的
Vite对vue的支持
我们在src下创建一个vue的文件夹再创建个App.vue文件,并书写一点代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<template>
<div>
<h2>{{ message }}</h2>
</div>
</template>
<script type="text/javascript">
export default {
data() {
return {
message: "Hello vue"
}
}
}
</script>
<style lang="less" scoped>
h2 {
color: #fff;
}
</style>
当然既然要使用vue,首先肯定得安装一下vue,我们这里安装vue3就行了1
npm install vue -D
然后再到main.js文件中导入createApp和根组件来使用1
2
3
4
5
6import { createApp } from "vue"
// 导入根组件
import App from "./vue/App.vue"
// vue
createApp(App).mount("#app")
由于需要挂载容器,我们去index.html模板中添加一下1
<div id="app"></div>
然后使用npx vite命令来跑一下,发现其实是会报错的,需要安装一个插件[vite] Internal server error: Failed to parse source for import analysis because the content contains invalid JS syntax. Install @vitejs/plugin-vue to handle .vue files.
vite对vue提供第一优先级支持:
Vue3单文件组件支持:@vitejs/plugin-vueVue3 JSX支持:@vitejs/plugin-vue-jsxVue2支持:underfin/vite-plugin-vue2
对于vue3安装一下插件1
npm install @vitejs/plugin-vue -D
安装完这个插件之后我们还需要做配置,在项目根目录下创建个vite.config.js文件1
2
3
4
5import vue from '@vitejs/plugin-vue'
export default {
plugins: [vue()]
}
注意node版本,文章开头说过,然后重新npx vite浏览器就能成功显示了
然后我们再到node_modules下,它有个.vite文件,它是我们第一次执行npx vite的时候做的一个预打包【主要是对依赖的库如vue、lodash】,它有个好处就是我们把这一次运行停掉,再次npx vite时,这两个就不需要再做预打包了,并且在终端看一下这个时间,很明显的快了一些,当然它内部也是做了判断的,并不会出现修改了还用之前的
Vite打包项目及预览
vite它里面提供了一个build,直接去执行里面这个build就行了1
npx vite build
打包成功后,它会在项目根目录下生成一个dist文件夹
一般打包后,我们也会对其在浏览器上测试一下,直接运行打包文件夹里的index.html文件也可以吗,但是vite它提供了另外一个工具preview,即预览,让它去执行里面的preview就可以了1
npx vite preview
然后我们就可以预览进行测试了
但是在真实开发里面,我们一般不会一直去写npx命令,我们会在package.json文件的scripts脚本中编写【scripts里面有个默认的test,把它删掉】1
2
3
4
5
6
7
8
9{
...
"scripts": {
"serve": "vite",
"build": "vite build",
"preview": "vite preview"
},
...
}
之后我们通过npm run xxx的方式去执行就可以了
ESBuild解析
vite打包非常快,还有个原因就是ESBuildESBuild的特点:
- 超快的构建速度,并且不需要缓存【
babel去转换还需要利用缓存,但是ESBuild速度很快,不需要做缓存】; - 支持
ES6和CommonJS的模块化 ; - 支持
ES6的Tree Shaking【比如某个函数从未使用过那么就可以通过Tree Shaking删除掉】 ; - 支持
Go、JavaScript的API; - 支持
TypeScript、JSX等语法编译 ; - 支持
SourceMap; - 支持代码压缩 ;
- 支持扩展其他插件 ;
我们可以发现ESBuild与babel很像,但是功能更加强一点,ESBuild还可以做代码压缩,babel一般不做这个,而Tree Shaking要到webpack中做,相当于兼顾了一些webpack的功能
ESBuild为什么这么快呢?
- 使用
Go语言编写的,可以直接转换成机器代码,而无需经过字节码; ESBuild可以充分利用CPU的多内核,尽可能让它们饱和运行;ESBuild的所有内容都是从零开始编写的,而不是使用第三方,所以从一开始就可以考虑各种性能问题;
Vite的项目创建方式
以上项目搭建从零开始的,但是真实开发里面不可能从零搭建一个项目,这里我们任意创建个文件夹来存放vite项目,利用vscode的终端输入如下命令1
npm init vite
它会让我们填项目名称,这里不需要删除,直接输入项目名称即可,然后是选择框架、ts
创建完之后安装一下依赖,然后根据它的脚本就可以本地运行、预览和打包



