Vite 知识体系 | 青训营笔记

132 阅读4分钟

浅谈构建工具

为什么需要构建工具?——前端工程的痛点

  1. 模块化

    ESM、CommonJS、UMD

  2. 资源编译

    高级语法的编译

  3. 产物质量

    代码体积、代码性能

  4. 开发效率

    热更新

前端构建工具的意义

  1. 模块化方案

    1. 提供模块加载方案
    2. 兼容不同模块规范
  2. 语法转译

    1. 高级语法转译,如:Sass、TypeScript
    2. 资源加载,如:图片、字体、worker
  3. 产物质量

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

  4. 开发效率

    热更新

Vite 概要介绍

Vite 是什么?

定位:新一代前端构建工具。

两大组成部分:

  1. No-bundle 开发服务,源文件无需打包
  2. 生产环境基于 Rollup 的 Bundler

核心特征:

  1. 高性能,dev 启动速度和热更新速度非常快
  2. 简单易用,开发者体验好

当下问题

  1. 缓慢的启动 -> 项目编译等待成本高
  2. 缓慢的热更新 -> 修改代码后不能实时更新

瓶颈在哪里?

  1. bundle 带来的性能开销
  2. JavaScript 语言的性能瓶颈

两大行业趋势

  1. 浏览器

    • 全球浏览器对原生 ESM 的普遍支持(目前占比 92% 以上)
  2. 工具

    • 基于原生语言(Go、Rust)编写前端编译工具链
    • 如 Go 语言编写的 Esbuild、Rust 编写的 SWC

浏览器原生 ESM 的支持

两大要素:

  1. script 标签增加 type="module" 属性
  2. 使用 ESM 模块导入导出语法

基于原生 ESM 的开发服务优势

  1. 无需打包项目源代码
  2. 天然的按需加载
  3. 可以利用文件级的浏览器缓存

基于 Esbuild 的编译性能优化

Esbuild——基于 Golang 开发的前端工具,具备如下能力:

  1. 打包器 Bundler
  2. 编译器 Transformer
  3. 压缩器 Minifier

优点:性能极高,在 Vite 中被深度使用

内置的 Web 构建能力

Vite 开箱即用的功能等价于:

  • webpack
  • webpack-dev-server
  • css-loader
  • style-loader
  • less-loader
  • sass-loader
  • postcss-loader
  • file-loader
  • MiniCssExtractPlugin
  • HTMLWebpackPlugin
  • ...

Vite 上手实战

初始化 Vite

  1. 全局安装 pnpm

     npm i -g pnpm
    
  2. 初始化命令

     pnpm create vite
    
  3. 安装依赖

     pnpm install
    
  4. 启动项目

     npm run dev
    

使用 Sass/Scss 和 CSS Modules

  1. 安装 sass 在开发环境

     pnpm i sass -D
    
  2. 创建 scss 文件

     .header {
       color: red;
     }
    
  3. 引入 scss 文件

     // 使用 CSS Modules 模块化方案,防止 className 命名冲突
     import styles from './index.module.scss';
     ​
     export function Header() {
       return <p className={styles.header}>This is Header</p>
     }
    

生产环境 Tree Shaking

优化原理:

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

Tree Shaking 在 Vite 中无序配置,默认开启!

Vite 整体架构

单文件编译

用 Esbuild 编译 TS / JSX。

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

局限性:

  1. 不支持类型检查(打包 TS 时要先 tsc 一下)
  2. 不支持语法降级到 ES5

代码压缩

Esbuild 作为默认压缩工具,替换传统的 Terser、Uglify.js 等压缩工具。

插件机制

  • 开发环境 -> 模拟 Rollup 插件机制
  • 生产环境 -> 直接使用 Rollup

插件兼容性具体可查阅:vite-rollup-plugins.patsk.dev/

Vite 进阶路线

深入双引擎

  1. esbuild
  2. rollup.js

推荐学习顺序:

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

Vite 插件开发

为什么需要插件机制?

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

image-20230814160721344

插件示例

主要是两步:

  1. 开发 Vite 插件

     const fileRegex = /.(my-file-ext)$/
     ​
     exportt default function myPlugin() {
       return {
         name: 'transform-file',
         transform(src, id) {
           if(fileRegex.test(id)) {
             return {
               code: compileFileToJS(src),
               map: null // 如果可行将提供 source map
             }
           }
         }
       }
     }
    
  2. 配置文件引入插件

     // vite.config.js
     ​
     import plugin from './myPlugin'
     ​
     export default defineConfig({
       plugins: [plugin()]
     })
    

学习插件开发

学习方式:先看文档,过一遍插件钩子的功能,然后多学习其他插件的实现,掌握套路

代码分割(拆包)

解决问题:

  1. 无法进行并发请求
  2. 缓存复用率低

image-20230814162619038

参考资料:

JS编译工具(Babel)

出现的原因:

  1. JavaScript 语法标准繁多,浏览器支持度不一
  2. 开发者需要用到高级语法

image-20230814162550612

参考资料:

语法安全降级

image-20230814162722877

如何在构建产物中避免这类问题?

  1. 上层解决方案:@vitejs/plugin-legacy

  2. 底层原理:

    1. 借助 Babel 进行语法自动降级
    2. 提前注入 Polyfill 是西安,如:core-js、regenerator-runtime

服务端渲染(SSR)

image-20230814163021706

深入了解底层标准

image-20230814163145613