vite简介
Vite是由Vue.js作者尤雨溪开发的,是一个快速、轻量级的现代Web开发构建工具,它利用现代浏览器的原生ES模块加载功能,实现了开发环境中的快速冷重载和构建速度。Vite的开发体验非常好,因为它能够在开发时实时更新页面,而不需要对整个项目进行重新构建。相比于Webpack的构建过程,Vite的开发速度更快,也更适合小型、简单的项目。但是,Vite目前还不支持像Webpack那样的插件生态系统,因此其可扩展性还有待提高。
vite最大的优势就是利用esm进行代码运行的,为什么需要打包,因为浏览器不认识import,但是在一些比较新的浏览器里面是可以通过给script标签加上type="module"让script标签可以运行import的。让代码不像传统的构建工具一样去分析引入,打包构建,而是直接保持模块化,省去了大量编译时间。
vite原理
利用现代浏览器支持的原生ES模块导入(ESM)功能来提供快速的开发服务器和热模块替换(HMR)。Vite的打包原理可以概括为以下几个步骤:
- 预构建(Pre-bundling):Vite使用esbuild进行预构建,将依赖项(如第三方库)预先转换为ES模块格式,并缓存起来。这一步是为了减少开发过程中的编译时间。
- 按需编译(On-demand Compilation):Vite启动一个本地开发服务器,当浏览器请求某个模块时,Vite会拦截这些请求,并根据需要即时编译对应的模块(使用ESBuild作为内部的编译工具,能够快速地将模块转换为浏览器可理解地格式)。这种按需编译的方式大大提高了开发环境的响应速度。
- HMR(热模块替换):Vite支持热模块替换,即在开发过程中实时更新页面而无需刷新。当某个模块发生更改时,Vite会将更新的模块推送给浏览器,并使用HMR技术进行模块的局部更新,提供了更快的开发体验。
- 生产环境打包:在生产环境下,Vite使用Rollup作为构建工具,因为Rollup擅长于生成更小的bundle,并且支持tree-shaking等优化技术。
rollup打包特点:
- 不会生成过多的运行代码(webpack会);
- 可以多模块化规范(commonJs、ESM、umd等)打包。
- 主要配置项:input、output、external(列出不需要打包进bundle中的模块)、plugins(插件)。
vite配置
- 一个开发服务器,它基于 原生 ES 模块 提供了丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。
- 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
注:vite需要node版本18+,20+,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
安装vite:npm i -g vite;
使用vite创建项目:npm create vite@latest;
初始化项目文件目录:
vite天生支持css以及预处理语言不需要额外的loader;支持typescript;(jsx是需要配置的, 特殊文件需要插件支持,例如 .vue文件)。如果需要详细调控vite打包可以在vite.config.js 的配置文件中进行配置,以命令行方式运行 vite 时,Vite 会自动解析 项目根目录下名为 vite.config.js 的配置文件(也支持其他 JS 和 TS 扩展名)。也可以通过--config命令指定一个配置文件(相当于cwd(当前工作目录)路径解析):vite --config my-config.js
vite识别 .vue文件需要安装插件@vitejs/plugin-vue
代码分割:Vite会自动分割异步引入的代码,第三方库vendor或者特殊的拆分需要借助rollup的manualChunks
// vite.config.js
// Vite 也直接支持 TS 配置文件。你可以在 vite.config.ts 中使用 defineConfig 工具函数。
import { defineConfig } from 'vite'; // defineConfig工具函数可ui获取类型提示
import vue from "@vitejs/plugin-vue"; // 导入插件
export default defineConfig({
root:"/", // 配置根目录 及index.html所在的文件夹,如果把index.html放在src下,root就要改成"/src"
publicDir:"./static", // 指定资源目录
base:"/www.xxx.com", // 前缀,所有路径都会加上base
// 如果项目需要使用jsx语法,需要配置esbuild参数识别
esbuild:{
jsxFactory:"h",
jsxFragment: "Fragment",
jsxInject: "import { h } from 'vue'"
},
resolve:{
extensions:[".js", ".ts", ".css"],
alias: {
"@":__dirname + "/src"
}
},
// 打包配置 只对打包有用,对开发模式没用
build:{
// 实际是配置的rollup,
rollupOptions:{
// 入口配置 默认是index.html,也可以指定其他入口,或者多入口
input:"./index.html",
// 出口配置
optput:{
entryFileNames:"bundle.js" // 可以指定打包出口命名规则
chunkFileNames:"[name].chunk.js" // 指定其他模块打包文件命名方式
},
// 代码分割
manualChunks:{
vendor: ['vue'] // 指定vue打包成vendor,独立出来
},
// manualChunks也可以是一个函数,处理多个库
/*
manualChunks:(id)=>{
// id是每一个模块的名字+路径 :vue-》node_modules/vue
if(id.includes('node_modules')){
return "ventor"
}
},
*/
},
assetsInlineLimit:20000 // 小于20kb的都转为base64 打进js文件中,js文件会变大
},
// 开发模式配置 只对开发模式有用,对打包没用
server:{
port:2000
proxy:{
"/api":{
target: "www.xxx.com",
rewrite: (path)=>{
return path.replace(/^/api/,"xxx")
}
}
},
headers: {}
},
plugins:[ // 配置插件,识别.vue文件
vue()
]
})
vite本身可以当作一个脚手架,自带模板仓库,会下载Vue3最新模板
npm create vite@latest my-vue-app -- --template vue
热更新
HMR (hot module replacement) 热模块替换。热更新功能能够在修改代码后,指在应用程序运行过程中,替换、添加、删除模块,而无需重新刷新整个应用。自动将更新的模块代码注入到运行中的应用程序,以便立即看到修改后的效果,而无需手动刷新页面。
热更新地实现原理
vite server监听到文件变化,通过websocket向vite client发送通知,client根据通知内容解析,发起http请求获取更新后的文件,然后进行局部更新页面。vite源码目录src下有client与node文件夹:
node:开发时vite dev启动项目,其中也就是启动了一个node服务,当中有两个功能与hmr相关:
- 监听项目文件变化
- 启动websocket服务,向客户端主动推送消息
client:项目中有入口index.html文件,在实际请求时返回的html内容和实际在项目中写的内容并不相同:
<script type="module" src="/@vite/client"></script>vite通过这种方式向我们的代码中注入vite client,当中有两个功能与hmr相关:
- 监听websocket消息,解析后发起文件请求
- 执行import.meta.hot中定义的钩子函数
npm create vue@latest 和 npm init @vitejs/app创建的项目是自动处理的,无需编写额外的代码来启用hmr功能(自带开箱即用的模块热更新hmr支持)。vite构建的项目中,默认情况下是启用了热模块更新。如果需要修改hmr相关配置,可以在vite的配置文件中(vite.config.js)中,对server.hmr进行配置。 如果需要禁用hmr:server: { hmr: false} 如果修改连接超时:server: { hmr: { timeout: 30000, overlay: false } }
vite打包优化策略:
由于vite打包是让浏览器一个个模块去加载的,因此,就很容易存在http请求的瀑布流问题(浏览器并发一次最多6个请求)。此次,vite内部为了解决这个问题,主要采取了3个方案:
- 预打包:确保每个依赖只对应一个请求/文件,比如lodash;
- 代码分割:可以借助rollup内置的manualChunks来实现
- Etag304状态码:让浏览器在重复加载的时候直接使用浏览器缓存。
Vite 插件库推荐
- @vitejs/plugin-vue :官方提供的 Vue 插件,用于在 Vite 中编译 Vue 单文件组件。
- vitejs-plugin-legacy:用于兼容老的浏览器不支持type=”module“的版本。
- unplugin-vue-components :一个可插拔的 Vue 组件库,支持按需加载、自动导入组件等。
- unplugin-auto-import:自动引入,例如使用ref的时候不需要引入,插件会自动帮你import。
- vite-plugin-compression:提供Gzip压缩,让打包内容更小。
- vite-plugin-imagemin:压缩图片资源。
- vite-plugin-postcss :一个 PostCSS 插件,可以在 Vite 中使用 PostCSS 进行 CSS 预处理。
- vite-plugin-style-import :一个样式导入插件,支持在 Vue、React 等框架中按需加载样式文件。
- vite-plugin-typescript :官方提供的 TypeScript 插件,用于在 Vite 中编译 TypeScript 文件。
- vite-tsconfig-paths :一个 TypeScript 路径别名插件,可以在 Vite 中使用路径别名。
- vite-plugin-eslint :一个 ESLint 插件,可以在 Vite 中使用 ESLint 进行代码检查