这是我参与「第四届青训营 」笔记创作活动的的第12天
01 浅谈构建工具
-
模块化
ESM, CommonJS, UMO
-
资源编译
高级语法的编译
-
产物质量
代码体积, 代码性能
-
开发效率
热更新
构建工具的意义
-
模块化方案
提供模块加载方案, 兼容不同模块规范
-
语法转译
高级语法转译, 资源加载
-
产物质量
产物压缩, 无用代码删除, 语法降级
-
开发效率
热更新
02 Vite概要介绍
新一代前端构建工具
两大组成部分:
- No-bundle开发服务, 源文件无需打包
- 生产环境基于Rollup的Bundler
核心特征: 1. 高性能, dev的启动速度和热更新速度非常快 2. 简单易用, 开发者体验好
基于原生ESM的开发服务优势
- 无需打包项目源代码
- 天然的按需加载
- 可以利用文件级的浏览器缓存
基于Esbuild的编译性能优化
03 Vite上手实战
项目初始化
npm i -g pnpm
pnpm create vite
// 进入项目目录后
pnpm install
npm run dev
使用Sass/Scss & CSS Module
pnpm i sass -D
// index.module.scss
.header {
color: red;
}
import React from "react";
import styles from './index.module.scss'
export function Header() {
return <div className={styles.header}>Header</div>
}
使用module起到样式隔离的效果
使用静态资源
见官方文档
使用HMR
无需配置, 自动开启
生产环境 Tree Shaking
优化原理
- 基于ESM的import/export语句依赖关系, 与运行时状态无关
- 在构建阶段将未使用到的代码进行删除
04 Vite整体架构
关键技术: 依赖预打包
为什么要进行预打包?
- 避免node_modules过多的文件请求
- 将CommonJS格式转换为ESM格式
实现原理
- 服务启动前扫描代码中用到的依赖
- 用Esbuild对依赖代码进行预打包
- 改写import语句, 指定依赖为预构建产物路径
关键技术: 单文件编译
用Esbuild编译TS/JSX
优势: 编译速度提升10-100x
局限性: 不支持类型检查, 不支持语法降级到ES5 (最多降到ES6)
关键技术: 代码压缩
关键技术: 插件机制
05 Vite进阶路线
深入双引擎
esbuild 和 rollup.js
推荐学习顺序:
- 先了解基本使用, 动手尝试各项常用配置
- 然后学习其插件开发
为什么需要插件机制?
- 抽离核心逻辑
- 易于拓展
Vite插件开发
Hook
-
服务启动阶段
config⭐ => configResolved => options => configureServer => buildStart
-
请求响应阶段
- transformIndexHtml
- resolveId⭐ => load⭐ => transfrom⭐
-
热更新阶段
handleHotUpdate
-
服务关闭阶段
buildEnd => closeBundle
复杂度较低的插件: json加载插件
复杂度中等的插件: Esbuild接入插件
复杂度较高的插件: 官方React插件
见PPT中的链接
插件示例
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
}
}
}
}
}
// 使用插件
import plugin from './myPlugin'
export default defineConfig({
plugins: [plugin()]
})
代码分割 (拆包)
拆包前: 无法进行并发请求, 缓存复用率低