跳到主要内容

Vite

https://www.vitejs.net/guide/why.html

对前端工程化的理解

借助一些工程化手段或工具,涵盖从项目启动到代码部署的全过程,从而提升开发效率、代码质量、可维护性,优化项目构建,使开发流程标准化、自动化

提高开发效率:通过制定统一的代码规范、使用版本控制系统、进行代码审查等方式,可以规范团队成员的开发流程,减少沟通成本,提高团队协作效率。

提升代码质量:通过使用代码规范工具代码质量检查工具、单元测试等手段,可以有效地约束代码风格,提高代码的可读性和可维护性,并减少潜在的错误。

增强可维护性:通过模块化开发、组件化开发、代码版本管理等方式,可以将代码拆分成更小、更易于管理的单元,从而降低代码的耦合度,提高代码的可维护性。

优化项目构建:通过使用模块打包工具代码压缩工具图片优化工具等,可以优化项目构建流程,减少代码体积,提高页面加载速度,提升用户体验。

开发流程自动化:通过配置 CICD 或者自动化部署脚本,实现一键部署,减轻运维压力,提升整体项目实施效率

Vite 是什么

是尤雨溪及 Vue 团队开发的一个现代化的前端构建工具

Vite 解决了什么问题

传统的基于打包器(bundle-based)的方案,无论是在首次启动还是热更新,其构建效率都会随着应用规模的增长而显著下降,影响开发效率与开发体验。

其更深层的原因还有:传统基于打包器的方案必须先 build 再启动服务器;基于 JS 开发的工具的构建效率很低。

Vite 如何解决以上问题的

  • 冷启动:

    • Vite 一开始会将应用中的模块分为「依赖」和「源码」

    • Vite 使用 ESBuild 预构建依赖以及 TS/JSX 转换,比 JS 编写的打包器要快 10 - 100 倍

    • Vite 利用浏览器对 ESM 的原生支持,只需要在浏览器请求源码时进行转换并按需提供源码即可

  • 热更新:

    • Vite 中的 HMR 也是基于原生 ESM 执行的,当一个文件更新后,Vite 只需要准确替换这个文件的链接即可,这样一来,热更新效率就不再受应用规模的影响了。

    • 同时利用 HTTP 缓存机制来加速页面重新加载:源码使用 304 协商缓存;依赖使用 Cache-Control 进行强缓存

为什么生产环境仍需打包

尽管原生 ESM 现在得到了广泛支持,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用 HTTP/2)。为了在生产环境中获得最佳的加载性能,最好还是将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存)。

为什么不用 ESBuild 打包

esbuild 快但不成熟,rollup 成熟但不快

ESBuild 虽然构建速度快,但灵活性与可扩展性以及技术生态还不及 Rollup,而且 Vite 强大的插件 API 也正是基于 Rollup 来展开的,所以两套方案并存也算是 Vite 的一个权衡之策

目前 Vite 团队正在基于 Rust 重构 Rollup,命名为 Rolldown,一旦 Rolldown 问世,Vite 就会替换 Rollup 和 ESBuld,显著提高构建性能,并消除开发和构建之间的不一致性

手动分包

vite 默认情况下都会将全部源码和全部依赖重新打包成一个 js 文件。这对于依赖库很多或者很重的项目来说,每次版本更新,客户端都需要重新下载这个 js 文件(文件指纹变了),一定程度上影响了用户体验。

解决方案就是手动分包,将依赖和源码分开打包成若干个 js 文件

vite 在打包时使用的是 rollup,支持 rollup 的 manualChunks 分包配置:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
output: {
manualChunks: {
'react': ['react'],
'react-router-dom': ['react-router-dom'],
// 也可以写成一个
'vendor': ['react', 'react-router-dom'],
}
}
}
}
})

同时 manualChunks 支持传入函数,入参为依赖的文件 id,返回值可以为字符串

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
output: {
manualChunks: (id) => {
if(id.includes('node_modules')) {
return 'vendor'
}
}
}
}
}
})