Vite知识体系 | 青训营笔记

94 阅读4分钟

这是我参与「第四届青训营」笔记创作活动的第12天

01 浅谈构建工具

  • 前端工程的痛点
    • 模块化
    • 资源编译
      • 浏览器的标准赶不上前端开发者的速度
    • 产物质量
      • 实际开发中需要代码压缩
      • 需要兼容到Android 4.4,兼容低端浏览器
    • 开发效率
  • 前端构建工具的意义
    • 模块化方案
      • 提供模块加载方案
      • 兼容不同模块规范
    • 语法转译
      • 高级语法转译,如Sass、TypeScript
      • 资源转译,如图片、字体、worker
    • 产物质量
      • 产物压缩
      • 删除无用代码
      • 语法降级
    • 开发效率
      • 实现热更新
  • 传统构建工具
    • 存在的问题
      • 启动缓慢,项目编译等待成本高
      • 热更新缓慢,修改代码后不能实时更新
    • 瓶颈
      • 打包带来的性能开销
      • JavaScript 语言的性能瓶颈
  • 两大行业趋势
    • 浏览器普遍支持原生ESM
      • script标签增加type="module"属性
      • 使用ESM模块导入导出语法
    • 基于原生语言(Go Rust等)编写的前端编译工具链兴起
      • Go语言编写的Esbuild,性能极高,在Vite中频繁使用
        • 打包器Bundler
        • 编译器Transformer
        • 压缩器Minifier
      • Rust编写的SWC,对标babel,速度可以快几十倍

02 Vite 概要介绍

  • 新一代前端构建工具
  • 组成部分
    • No-bundle 开发服务,源文件无需打包
    • 生产环境基于Rollup的Bundler
  • 核心特征
    • 高性能,dev启动速度和热更新速度快
    • 简单易用,开发者体验好
  • 基于原生ESM的开发服务优势
    • 无需打包项目源代码
    • 天然按需加载
    • 可以利用文件级的浏览器缓存
  • 内置的Web构建能力
    • webpack webpack-dev-server
    • webpack的各种loader
    • webpack的各种plugin

03 Vite 上手实战

  • 项目初始化
    • 安装pnpm npm i -g pnpm
    • 初始化命令 pnpm create vite
    • 安装依赖 pnpm install
    • 启动项目 npm run dev
    • 输入初始化参数:项目名称、框架等
// package.json
{
	"scripts": {
		// 开发环境下运行的命令
		"dev": "vite",
		// 生产环境下运行的命令
		// vite使用的esbuild默认不支持TypeScript的类型,需要调用tsc进行类型检查
		"build": "tsc && vite build",
		// 预览生产环境产物内容
		"preview": "vite preview"
	}
}
  • 使用Sass/Scss & CSS Modules示例
    • 安装Sass pnpm i sass -D
    • 编写index.tsx
    • 编写index.module.scss
// index.tsx
import styles from './index.module.scss'
// 使用CSS Modules模块化方案{styles.header} 防止类名冲突和样式污染
export function Header() {
		return <p className={styles.header}>I'm not header </p>
}
// index.module.scss
// 与css只能平铺相比,scss 可以嵌套编写子元素样式
.header {
	color: blue;
}
  • 使用静态资源
import reactLogo from './assets/react.svg'
function App(){
	//...
	return {
		<img src={reactLogo}/>
	}
}
  • 使用HMR
    • 模块热替换
    • vite默认自动配置
    • HMR可以保存组件的局部状态
  • 使用生产环境Tree-shaking
    • 在构建阶段删除无用代码
    • vite默认自动配置
    • 依赖rollup实现
    • 基于ESM的import/export语句依赖关系,与运行时状态无关
    • CommonJS格式不能做到Tree-shaking,只能用于ESM
    • 如果require的部分依赖运行时计算的结果,使用Tree-shaking会有一定风险

04 Vite 整体架构

  • 依赖预打包
    • 为什么要进行依赖预打包?
      • 避免node_modules过多的文件请求
      • 将CommonJS格式转换为ESM格式
    • 实现原理
      • 服务启动前扫描代码中用到的依赖
      • 用esbuild对依赖代码进行预打包
      • 改写import语句,指定依赖为预构建产物路径
  • 单文件编译
    • 用esbuild编译ts/jsx
    • 优势
    • 局限性
      • 不支持类型检查
      • 不支持语法降级到ES5
  • 代码压缩
    • 默认压缩工具是esbuild,替换传统的terser uglify.js
  • 插件机制

05 Vite 进阶路线

  • 深入vite依赖的两个引擎
    • esbuild
    • rollup.js
    • 推荐学习顺序
      • 了解基本使用
      • 动手尝试各项常用配置
      • 学习插件开发
  • Vite插件开发
    • Why plugin?
      • 抽离核心逻辑
      • 易于拓展
    • Vite各阶段钩子
      • 服务启动阶段
      • 请求响应阶段
      • 热更新阶段
      • 服务关闭阶段
    • 常见钩子
      • config
      • resolveId
      • load
      • transform
  • 代码分割(拆包)
    • 拆包前
      • 只有一个bundle文件
      • 无法进行并发请求
      • 缓存复用率低
    • vite的拆包依赖rollup的打包功能
  • 语法安全降级
    • 如IE11不支持Promise语法
    • 上层解决方案: @vitejs/plugin-legacy
    • 底层原理
      • 借助Babel进行语法自动降级
        • JavaScript编译工具
        • 出现原因
          • JavaScript语法标准繁多,浏览器支持程度不一
          • 使用高级语法的需求
      • 提前注入polyfill实现
        • core-js regenerator-runtime
  • 服务端渲染(SSR)
    • 提升首屏性能和进行SEO优化
  • 深入了解底层标准
    • CJS规范
    • ESM规范
    • HTTP 2.0特性