Vite 知识体系 | 青训营笔记
这是我参与「第五届青训营」伴学笔记创作活动的第 14 天
0x1 浅谈构建工具
- 前端工程的痛点
- 模块化
- 资源编译
- 产物质量
- 开发效率
- 前端构建工具的意义
- 模块化方案
- 提供模块加载方案
- 兼容不同模块规范
- 语法转译
- 高级语法转译
- 资源加载
- 产物质量
- 产物压缩
- 无用代码删除
- 语法降级
- 开发效率
- 热更新
- 模块化方案
0x2 Vite 概要介绍
-
Vite 概览
- 定位:新一代前端构建工具
- 组成部分
- No-bundle 开发服务,源文件无需打包
- 生产环境基于 Rollup 的 Bundle
- 核心特征
- 高性能,dev 启动速度和热更新速度非常快
- 简单易用,开发者体验好
-
当下问题
- 缓慢的启动:项目编译等待成本高
- 缓慢的热更新:修改代码后不能实时更新
-
行业趋势
-
各大浏览器对原生 ESM(ECMA Script Modules) 的普遍支持
-
浏览器原生 ESM 支持
-
script 标签增加
type="module"
属性<script type="module"> import { foo } from './foo.js' console.log(foo) </script>
-
使用 ESM 模块导入导出语法
-
-
基于原生 ESM 的开发服务优势
- 无需打包项目源代码
- 天然的按需加载
- 可以利用文件级的浏览器缓存
-
-
基于原生语言(如:Go——Esbuild,Rust——SWC)编写前端编译工具链
-
基于 Esbuild 的编译性能优化
基于 Golang 开发的前端工具 Esbuild 具备以下能力:
- 打包器:Bundler
- 编译器:Transformer
- 压缩器:Minifier
-
-
0x3 Vite 上手实战
-
项目初始化
- 安装 pnpm:
npm i -g pnpm
- 初始化命令:
pnpm create vite
- 输入初始化参数(使用 React)
- 安装依赖:
pnpm install
- 启动项目:
npm run dev
- 安装 pnpm:
-
使用 Sass/Scss & CSS Modules
-
目录结构
-
安装 Sass:
pnpm i sass -D
-
index.tsx
import styles from './index.module.scss'; export function Header() { return <p className={styles.header}>This is Header</p> };
-
index.module.scss
.header { color: red; }
-
在 App.tsx 中引入 Header 组件
import { Header } from "./components/Header" function App() { return ( <div> <Header /> </div> ) } export default App
-
-
使用静态资源
举例:在 App.tsx 中引入 logo.svg
import logoUrl from './logo.svg' function App() { return ( <div> <img src={ logoUrl } alt="" /> </div> ) } export default App
-
使用 HMR
无需额外配置,自动开启
-
生产环境 Tree-Shaking
无需额外配置,自动开启
优化原理:
- 基于 ESM 的 import/export 语句依赖关系,与运行时状态无关
- 在构建阶段将未使用到的代码进行删除
0x4 Vite 整体架构
-
单文件编译
用 Esbuild 编译 TS/JSX
- 优势:编译速度提升
- 局限性:
- 不支持类型检查
- 不支持语法降级到 ES5
-
代码压缩
Esbuild 作为默认压缩工具,替换传统的 Terser、Uglify.js 等压缩工具
-
插件机制
- 开发阶段:模拟 Rollup 插件机制
- 生产环境:直接使用 Rollup
0x5 Vite 进阶路线
-
深入双引擎
- esbuild
- rollup.js
学习顺序:
- 了解基本使用并尝试各项常用配置
- 学习其插件开发
-
Vite 插件开发
- 抽离核心逻辑
- 易于拓展
-
服务启动阶段
-
请求响应阶段
-
热更新阶段
-
服务关闭阶段
-
插件实例
-
开发插件
const fileRegex = /\.(my-file-ext)$/ export default function myPlugin() { return { name: 'transform-file', transform(src, id) { if(fileRegex.test(id)) { return { code: compileFileToJS(src), map: null } } } } }
-
配置文件引入插件
// filename: vite.config.js import plugin from './myPlugin' export default defineConfig({ plugins: [plugin()] })
-
-
代码分割(拆包)
拆包前存在的问题:
- 无法进行并发请求
- 缓存复用率低
-
JS 编译工具(Babel)
出现的原因:
- JavaScript 语法标准繁多,浏览器支持程度不一
- 对开发者使用的高级语法合理降级
-
语法安全降级
- Vite 上层解决方案:
@vitejs/plugin-legacy
- 底层原理
- 借助 Babel 进行语法自动降级
- 提前注入 Polyfill 实现,如:core-js、regenerator-runtime
- Vite 上层解决方案:
-
服务端渲染(SSR)
- 构建阶段
- 代码执行阶段
-
深入了解底层标准
重点特性:
- CJS(CommonJS) 规范
- ESM 规范
- HTTP 2.0 特性