Vite知识体系|笔记

79 阅读9分钟

Vite知识体系

浅谈构建工具

前端为什么需要构建工具

前端项目的核心要素--资源
  • JS
  • TS
  • JSX
  • CSS
  • SCSS
  • LESS
  • PNG
  • JPEG
  • WEBP
  • ...
前端功能化的问题
  • 模块化

    • 常用规范:ESM,CommonJS,UMD
  • 资源编译:高级语法的编译

  • 产物质量:代码体积,代码性能,产物的语法兼容性

  • 开发效率:热更新

前端构建工具的意义

  • 解决模块化的问题

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

    • 高级语法转译,如Sass、TypeScript
    • 资源加载,如图片、字体、worker
  • 解决产物质量的问题

    • 产物压缩、无用代码删除、语法降级
  • 解决开发效率的问题

    • 提供一个热更新的系统来支持改动代码后立即可以看到代码效果

传统构建工具存在的问题

  • 缓慢的启动

    • 项目编译等待成本高
  • 缓慢的热更新

    • 修改代码后不能实时更新
瓶颈
  • bundle带来的性能开销
  • JavaScript语言的性能瓶颈
两大行业趋势
  • 全球浏览器对原生ESM的普遍支持(92%以上)

    • 两大要素

      • script标签增加type="module"属性

      • 使用ESM模块导入导出语法

        import{ xxx } from './xx.js'
        
        export const xxx='';
        
  • 基于原生语言(Go, Rust)编写前端编译工具链

    例如,Go语言编写的Esbuild,Rust编写的SWC

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

      1. 打包器 Bundler
      2. 编译器 Transformer
      3. 压缩器 Minifier
    • 性能极高,在Vite中被深度使用

基于原生ESM的开发服务优势
  • 无需打包项目源代码
  • 天然的按需加载
  • 可以利用文件级的浏览器缓存

image-20241123201654260.png

Vite概要介绍

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

  • 两大组成部分:

    • No-bundle开发服务,源文件无需打包
    • 生产环境基于Rollup的Bundler
  • 核心特征

    1. 高性能,dev启动速度和热更新速度非常快
    2. 简单易用,开发者体验好
  • 内置的Web构建能力

    Vite 开箱即用的功能等价于

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

    image-20241123203253296.png

Vite上手实战

项目初始化

image-20241123203407536.png

  • 三个命令

    "scripts": {
      "dev": "vite",//开发阶段的启动
      "build": "tsc -b && vite build",//生产环境下进行项目的打包
      "preview": "vite preview"//生产之后显示出产物的内容
    }
    

使用Sass/Scss & CSS Modules

image-20241123210049395.png

image-20241123211452028.png

使用静态资源

除了常见的图片格式, Vite也内置了对于JSON, Worker, WASM资源的加载支持

image-20241123211635421.png

使用HMR

HMR

是 Hot Module Replacement(热模块替换)的缩写,这是一种在开发过程中无需刷新整个页面就能更新应用的技术。HMR 允许开发者在修改代码后,只重新加载那些发生变化的部分,从而极大地提高了开发效率和用户体验。

主要特点:
  1. 即时更新:开发者在保存文件后,浏览器会自动更新界面,无需手动刷新页面。
  2. 状态保持:在模块热替换过程中,应用的状态和用户输入可以保持不变。
  3. 开发效率:开发者可以立即看到代码更改的效果,加快了开发和调试的速度。
  4. 资源优化:只加载变化的部分,减少了数据传输,节省了带宽和加载时间。
HMR 在不同工具和框架中的应用:
  • Webpack:Webpack 提供了 HMR 的支持,可以在开发服务器配置中启用。Webpack 会监听文件变化,并只重新打包那些发生变化的模块。
  • React:在使用 Create React App 创建的项目中,默认支持 HMR。当你修改组件后,只有该组件会被重新加载。
  • Vue:Vue CLI 也支持 HMR,允许开发者在开发过程中享受热替换的便利。

image-20241123211930677.png

HMR可以保存组件的局部状态

生产环境Tree Shaking

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

import React from 'react';
import styles from './index.module.scss'
import { add } from '../../util';
​
export function Header(){
    return <div className={styles.header}>header{add(1, 2)}</div>
export const add = (a: number, b: number) => a + b;
​
export const sub = (a: number, b: number) => a - b;//打包时这段代码会被删除

CommonJS格式不能做到Tree Shaking:require的部分可能依赖运行时计算的结果

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

Vite整体架构

image-20241123214037080.png

依赖预打包

为什么要进行预打包?
  1. 避免 node_modules 过多的文件请求
  2. 将 CommonJS 格式转换为 ESM 格式
实现原理:
  1. 服务启动前扫描代码中用到的依赖
  2. 用 Esbuild 对依赖代码进行预打包
  3. 改写 import 语句,指定依赖为预构建产物路径
// 改写前
import React from "react";
// 改写后
import React from '/node_modules/.vite/react.js'

单文件编译

用 Esbuild 编译 TS/JSX

  • 优势:

    • 编译速度提升10-100x
  • 局限性:

    • 不支持类型检查
    • 不支持语法降级到ES5 放到低版本浏览器会报错

代码压缩

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

image-20241123215703420.png

插件机制

image-20241123220139476.png

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

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

Vite进阶路线

深入双引擎

esbuild

esbuild 是一个高性能的构建工具,用于打包 JavaScript、TypeScript 和其他语言的代码。它以其快速的构建速度和简洁的API而闻名。esbuild 自动处理许多现代前端开发中的常见任务,如代码压缩、树摇(tree-shaking)、代码分割和最小化。

特点:
  • 快速构建esbuild 的构建速度非常快,通常比传统的打包器如Webpack快得多。
  • 单一二进制文件esbuild 是一个单一的二进制文件,不需要额外的构建依赖。
  • 多种语言支持:除了JavaScript和TypeScript,esbuild 还支持多种语言,包括JSX、TSX和其他预处理器。
  • 插件系统esbuild 允许开发者通过插件扩展其功能。
  • 跨平台esbuild 支持Windows、macOS和Linux。
参考资料

esbuild - 快速入门 | esbuild中文文档 | esbuild中文网

Rollup.js

Rollup 是一个模块打包器,用于将小块代码合并成更大的代码包,特别是用于库和框架的打包。它特别适合用于打包那些需要在多个环境中运行的JavaScript库,因为Rollup可以生成各种模块格式的代码,如ES6、UMD、CommonJS等。

特点:
  • 树摇:Rollup 支持树摇,这意味着它只会包含最终打包文件中实际用到的代码,从而减少文件大小。
  • 多种模块格式:Rollup 支持多种模块格式,使得打包后的代码可以在不同的环境中运行。
  • 插件系统:Rollup 拥有一个强大的插件系统,允许开发者添加新的功能,如支持新的语法或转换代码。
  • 代码分割:Rollup 支持代码分割,可以将代码拆分成多个文件,按需加载。
  • 兼容性:Rollup 支持各种JavaScript版本,包括ES6+。
参考资料

简介 | rollup.js 中文文档 | rollup.js中文网 (rollupjs.com)

推荐学习顺序:
  • 先了解基本使用,动手尝试各项常用配置;
  • 然后学习其插件开发。

Vite插件开发

为什么需要插件机制
  • 抽离核心逻辑
  • 易于拓展

插件的钩子

"钩子"(Hook)

是一种特殊类型的函数,它允许用户或开发者介入或“钩住”某个事件、操作或程序的执行流程。钩子函数通常被用于拦截和修改系统或库的正常行为,以便在特定事件发生时执行自定义的代码。

钩子的作用
  • 扩展功能:允许插件扩展宿主应用程序的功能,而不需要修改宿主应用程序的代码。
  • 自定义行为:允许用户或开发者根据需要自定义应用程序的行为。
  • 拦截和修改:在数据被处理或保存之前,钩子可以拦截和修改这些数据。
  • 调试和日志记录:钩子可以用来插入调试代码或记录日志,帮助开发者理解应用程序的运行流程。

image-20241123221317525.png

通过上述的Hook,我们可以在不同的构建阶段插入自定义的逻辑

例子
  1. 开发Vite插件
  2. 配置文件引入插件
//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 //如果可行将提供 source map
                }
            }
        }
    }
}
//使用插件
// vite.config.js
import plugin from './myPlugin'export default defineConfig({
    plugins: [plugin()]
})
参考资料

插件 API | Vite 官方中文文档 (vitejs.dev)

代码分割(拆包)

  • 拆包前

    image-20241124205853925.png

  • 问题

    • 无法进行并发请求
    • 缓存复用率低
  • 拆包后

    image-20241124210032844.png

JS编译工具(Babel)

  • 出现的原因

    • JavaScript 语法标准繁多,浏览器支持程度不一
    • 开发者需要用到高级语法
  • 原理

    image-20241124210604587.png

语法安全降级

例子
  • 以Promise语法为例,IE11没有支持

    image-20241124210918799.png

服务端渲染(SSR)

一种常见的渲染模式,用于提升首屏性能和SEO优化

image-20241124212946155.png

深入了解底层标准

image-20241124213558349.png

Vite社区生态

  • Github 40k+star(可参考webpack 61.3 K,rollup 21.8k),并且目前还在持续维护
  • 官方提供插件:

    • @vitejs/plugin-vue,提供Vue 3 支持
    • @vitejs/plugin-vue-jsx,提供 Vue 3 JSX 支持
    • @vitejs/plugin-react,提供 React 支持
    • @vitejs/plugin-legacy,提供低版本浏览器降级支持
  • 被众多框架内置

    • Nuxt
    • SvelteKit
    • Astro
    • Vitepress