Vite入门 | 青训营笔记

100 阅读2分钟

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

为什么要使用构建工具

构建工具用于解决模块化、编译高级语法、提高产物质量、提升开发效率等。

  • 模块化:
    1. 提供模块加载方案
    2. 兼容不同模块规范
  • 语法转译:
    1. 高级语法转译:如Sass、ts等
    2. 资源加载:如图片、字体等
  • 产物质量:产物压缩、无用代码删除、语法降级
  • 开发效率:热更新

Vite

概览

  • 定位:新一代前端构建工具
  • 组成:
    1. No-bundle开发服务,源文件无需打包
    2. 生产环境基于Roolup的Bundler
  • 核心特征:
    1. 高性能,dev启动速度和热更新速度快
    2. 简单易用,开发者体验好

浏览器原生ESM的支持

两大要素:

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

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

  • 无需打包项目源代码
  • 天然的按需加载
  • 利用文件级别的浏览器缓存

EsBuild具备如下能力

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

使用

项目初始化

# 提前安装pnmp
npm i -g pnpm
# 初始化
pnpm create vite
# 安装依赖
pnpm install
# 启动项目
npm run dev

生产环境Tree Shaking

image.png

优化原理:

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

整体架构

image.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)

  • 优势:编译速度提升
  • 局限性
    • 不支持类型检查
    • 不支持语法降级到ES5

代码压缩

image.png

进阶

插件开发(抽离核心逻辑、易于拓展)

  1. 服务启动阶段
graph LR
config --> configResolved --> options --> configureServer --> buildStart
  1. 请求响应阶段
graph LR
请求响应阶段 --> transformIndexHtml
请求响应阶段 --> resolveId --> load --> transfrom
  1. 热更新阶段
graph TD
handleHotUpdate
  1. 服务关闭阶段
graph LR
bulidEnd --> closeBundle

代码分割(拆包)

问题

  • 无法进行并发请求
  • 缓存复用率降低

Babel

原理图

image.png

Babel出现的原因

  • JS语法标准繁多,浏览器支持程度不同
  • 开发者需要使用高级语法

语法安全降级

image.png

graph LR
A[如何在构建产物中避免这类问题] --> B["上层解决方案:@vitejs/plugin-legacy"]
A --> C[底层原理] --> 借助Babel进行语法自动降级
C --> D["提前注入Ployfill实现,如core-js、regenerator-runtime"]

服务端渲染(SSR)

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

构建阶段

graph LR
项目源码 --> 构建流程 --> 客户端参数 --- 运行在浏览器
构建流程 --> SSR产物 --- a["运行在服务端(Node.js)"]

代码执行阶段

graph LR
加载SSR入口 --> 数据预取 --> 组件渲染 --> HTML拼接