分享目标
vite是什么,带给我们什么好处,vite的一些基本配置
vite 是什么
vite是一个高阶的前端构建工具
vite 初衷
构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长
性能瓶颈:
- JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器
- 即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来
极大的影响开发者开发效率
目的
- 使用简单
- 快
与传统构建工具区别
-
自己没有编译构建能力 预编译采用esbuild 打包使用rollup
-
开发时基于原生ESM加载的方式(下边会有介绍)
-
vite 减少很多配置量
vite 配置 不繁琐,为前端项目而生,dev-server,css依赖,图片加载功能都是开箱即用的,不需要你去配置插件,loader,所以你的vite配置可能不超过20行代码,webpack 项目基本不太可能
-
vite 为项目而生 不是为构建而生
原生ESM
我们一直提到一个概念就是 vite以原生ES Moudle 的加载方式,那么我们详细来了解下
我们之前的js是没有模块管理能力的,所以出现了一些模块管理规范和库
我们已经知道一些前端的模块管理方案: commonJs AMD (RequireJs) UMD
而这些本质都是通过JS脚本的执行来进行管理的,不是原生的Native模块管理能力
那么 ES Moudle是随着ES6推出的正式的JavaScript模块语法
更多详情参考 ES Moudle
我本地也部署了一个示例帮大家理解(代码basic-modules)
开始创建一个vite应用
npm init vite@latest
这样你就可以快速创建一个vite项目 vite项目默认目录
├── src
│ ├── App.css
│ ├── App.jsx
│ ├── favicon.svg
│ ├── index.css
│ ├── logo.svg
│ └── main.jsx
├── index.html
├── package.json
└── vite.config.js
推荐用yarn安装依赖 github.com/evanw/esbuild/issues/462
vite-show
优势
上手简单,开发效率高
webpack 配置复杂,这点我们应该深有体会
比如数据平台的配置就很多数据平台webpack配置
而vite配置(帮我们省去了很多配置)
即使我们有方便的脚手架构建工具例如 vue-cli create-react-app
你还是要学习webpack 才能修改,就官网来说看起来就内容很多,学习成本不低
vite你不需要管那么多配置问题,只需要了解基本的配置就可以了
快
随着项目增多 ,webpack项目启动速度明显变慢,但vite不会
速度对比
- vite 编译和webpack区别
不难看出,webpack 需要把所有模块生成一个bundle ,随着项目变大,构建时间必定会显著增长
vite你可以理解为她是一个服务器,index.html是一个入口
让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
(直接浏览器加载html 通过script 加载main.js 这个js请求到达vite的server,vite再去找对应的文件,再根据用到的文件去加载)
当项目提交增大的时候,vite 编译时间不会有太大变化
另一个快原因:
vite 采用esbuild预编译
Vite 将会使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
性能对比图可以看 esbuild官网
vite配置
typescript
天然支持ts(通过esbuild 将ts文件编译成 js),但不会校验,需要自己配置
配置过程
npm install typescript
配置tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["./src"]
}
因为vite不会校验ts,所以我们可以在构建脚本中运行 tsc --noEmit,这样在构建的时候可以进行校验
"scripts": {
"dev": "tsc --noEmit && vite",
"build": "tsc --noEmit && vite build",
"preview": "vite preview"
},
只针对 单文件 有些ts功能没法实现 不支持模块间关联的类型校验 所以我们在tsconfig.json 中
静态资源处理
集成eslint
npm install eslint-config-standard eslint-plugin-import eslint-plugin-promise -D npm install eslint
自己配置eslint
module.exports = {
extends: 'standard',
}
因为vite 构建时不会自行校验,需要做如下配置
"scripts": {
"dev": "npm run lint && tsc --noEmit && vite",
"build": "npm run lint && tsc --noEmit && vite build",
"preview": "vite preview",
"lint":"eslint --ext jsx src/"
},
环境变量
通过不通的文件获取不同的环境变量
.env.production
.env.development
.env.local
变量名要加 VITE前缀
关于 import.meta 是 ECMAScript 实现的
通过 import.meta.env 获取环境变量
配置文件要重启才能生效
vite 功能
热更新
Vite 提供了一套原生 ESM 的 HMR API。
vite 命令行创建的项目,都是默认开启热更新的
接下来我们实现以下vite怎么使用热更新
npm init @vitejs/app 创建没有任何框架继承的项目
可以发现是没有支持热更新的,改变内容页面会刷新,而有热更新的项目,改变内容页面不会刷新
修改前
import './style.css'
document.querySelector('#app').innerHTML = `
<h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`
修改后
import './style.css'
export function render(){
document.querySelector('#app').innerHTML = `
<h1>Hello Vite!123</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`
}
render()
// vite build 后 import.meta.hot可能是undefined
if(import.meta.hot){
import.meta.hot.accept((newModule)=>{
newModule.render()
})
}
页面热更新实现
glob
vite提供的功能: 通过正则方式多文件引入
const globModule = import.meta.glob('./glob/*')
const globModule = import.meta.glob('./glob/*.js')
const globModule = import.meta.glob('./glob/*.json')
可以在浏览器看到编译后的代码
如果我们不希望异步引入文件,可以使用 globEager
const globModuleEager = import.meta.globEager('./glob/*')
实现库 fast-glob
预编译
vite快的一个原因是: 第一次启动时会把第三方包编译放到cache里,之后会从cache里面去取(预编译有点像webpack 的dll 打包)
cache 目录 node_modules/.vite
预编译过程中,会把非ESM文件 编译成 ESM
例如 commonJs => ESM
可以看 node_modules/react/cjs/react.development.js
react 通过commonJs管理模块,vite需要进行转换
node_modules/.vite/react.js
配置预编译 optimizeDeps
{
plugins: [react()],
optimizeDeps: { // 是否需要预编译
include: [], // 需要预编译的文件
exclude: ['react'] // 不需要预编译的文件
}
}
Vite 将有许多内部模块的 ESM 依赖关系转换为单个模块,以提高后续页面加载性能。
比如lodash-es 他包含600个内置模块 vite 会打成一个包
如果不进行编译的话,我们再浏览器可以看到600个请求,影响页面性能
不要随便把包exclud