13Vite知识体系 | 青训营笔记

72 阅读3分钟

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

PPT: bytedance.feishu.cn/file/boxcnR…

01 浅谈构建工具

  • 模块化

    ESM, CommonJS, UMO

  • 资源编译

    高级语法的编译

  • 产物质量

    代码体积, 代码性能

  • 开发效率

    热更新

构建工具的意义

  • 模块化方案

    提供模块加载方案, 兼容不同模块规范

  • 语法转译

    高级语法转译, 资源加载

  • 产物质量

    产物压缩, 无用代码删除, 语法降级

  • 开发效率

    热更新

02 Vite概要介绍

新一代前端构建工具

两大组成部分:

  1. No-bundle开发服务, 源文件无需打包
  2. 生产环境基于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

优化原理

  1. 基于ESM的import/export语句依赖关系, 与运行时状态无关
  2. 在构建阶段将未使用到的代码进行删除

04 Vite整体架构

关键技术: 依赖预打包

为什么要进行预打包?

  1. 避免node_modules过多的文件请求
  2. 将CommonJS格式转换为ESM格式

实现原理

  1. 服务启动前扫描代码中用到的依赖
  2. 用Esbuild对依赖代码进行预打包
  3. 改写import语句, 指定依赖为预构建产物路径

关键技术: 单文件编译

用Esbuild编译TS/JSX

优势: 编译速度提升10-100x

局限性: 不支持类型检查, 不支持语法降级到ES5 (最多降到ES6)

关键技术: 代码压缩

关键技术: 插件机制

05 Vite进阶路线

深入双引擎

esbuild 和 rollup.js

推荐学习顺序:

  • 先了解基本使用, 动手尝试各项常用配置
  • 然后学习其插件开发

为什么需要插件机制?

  • 抽离核心逻辑
  • 易于拓展

Vite插件开发

Hook

  1. 服务启动阶段

    config⭐ => configResolved => options => configureServer => buildStart

  2. 请求响应阶段

    • transformIndexHtml
    • resolveId⭐ => load⭐ => transfrom⭐
  3. 热更新阶段

    handleHotUpdate

  4. 服务关闭阶段

    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()]
 })

代码分割 (拆包)

拆包前: 无法进行并发请求, 缓存复用率低

JS编译工具 (Babel)

语法安全降级

服务端渲染(SSR)

深入了解底层标准