Vite到底有多好用| 青训营

216 阅读7分钟

Vite到底有多好用

Vite 概要介绍

什么是Vite?Why Vite?

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

  • 两大组成部分:

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

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

当下问题

  • 缓慢的启动:项目编译等待成本太高
  • 缓慢的热更新:修改代码后不能实时更新

瓶颈:

  • bundle 带来的性能开销
  • JavaScript 语言的性能瓶颈

两大行业趋势

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

image-20230815012911943image-20230815012927292

浏览器原生 ESM 支持的两大要素:

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

基于原生 ESM 的开发服务优势:image-20230815013039129

  • 无需打包项目代码(减少了bundle的开销)
  • 天然的按需加载
  • 可以利用文件级的浏览器缓存

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

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

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

性能极高,在 Vite 中被深度使用。

内置的 Web 构建能力

Vite 开箱即用的功能等价于

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

构建工具的意义

前端工程的痛点

核心要素——资源

  • 模块化

    • ESM、CommonJS、UMD

      • ES Modules (ESM) 是 JavaScript 的官方模块系统,它提供了一种标准化的方式来导入和导出模块。
      • CommonJS 是 Node.js 中广泛使用的模块化方案,它使用 requiremodule.exports 来导入和导出模块。
      • UMD (Universal Module Definition) 是一种通用的模块化方案,兼容在不同的环境中使用,包括浏览器和 Node.js。
  • 资源的编译

    • 高级语法的编译(JSX,TS等)
  • 产物质量

    • 代码体积、代码性能

      • 代码体积优化:通过使用代码压缩工具(如UglifyJS、Terser)和消除未使用的代码(Tree Shaking)等技术,可以减小代码体积,提高页面加载速度。
      • 代码性能优化:通过使用性能分析工具(如Webpack Bundle Analyzer)和优化技术(如代码分割、懒加载)等,可以提升代码的执行性能,减少页面加载时间。
  • 开发效率

    • 热更新:热更新是一种开发工具提供的功能,它可以在代码修改保存后,自动更新应用程序的部分或全部内容,无需手动刷新页面。这样可以减少开发者的等待时间,提高开发效率。

前端构建工具的意义

  • 模块化方案

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

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

    1. 产物压缩、无用代码删除、语法降级
  • 开发效率

    1. 热更新

Vite上手实战

项目初始化

Pasted image 20220811114207.pngPasted image 20220811114217.png

使用 Sass/Scss & CSS Modules

目录结构:

image-20230815185608131

引用组件

组件内容(上方为组件地址

App.tsx内使用Header组件:

组件中引用样式

component文件夹下新建indexs.module.scss样式表:

index.tsx中引入样式:image-20230815192030533

不出意外的话,可能会出意外这个时候Install the sass package就可以解决意外

npm install --save-dev sass

成了!现在,我们已经在App.tsx使用了一个已引用样式的组件

使用静态资源

以为svg图片为例:

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

生产环境 Tree Shaking

Tree Shaking 是指通过静态分析的方式,从代码中剔除未使用的部分,以减小最终打包输出的文件大小。

在 Vite 中,Tree Shaking 是通过 Rollup 的功能来实现的。当你使用 Vite 打包项目时,Vite 会使用 Rollup 分析你的代码,并识别出哪些部分是未使用的。然后,它会将这些未使用的部分从最终的打包输出中移除,以减小文件大小。

优化原理:

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

util.ts中写上两条函数addmutilimage-20230815211355347

index.tst中引用并使用add函数,不使用multi函数image-20230815211431049

为了调试暂时把代码压缩功能关闭:在vite.config.tsimage-20230815212036168

对生产环境进行打包image-20230815212029866

在打包的代码中找到了add函数,但是没有找到mutil函数image-20230815212317835

PS:image-20230815211538508

Vite整体架构

image-20230815212755153

依赖预打包

为什么要进行预打包:

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

Pasted image 20220811114939.png

实现原理:

  1. 服务器启动前扫描代码中用到的依赖
  2. 用 Esbuild 对依赖代码进行预打包
  3. 改写 import 语句,指定依赖为预构建产物路径
// before
import React from "react";
// after
import React from '/node_modules/.vite/react.js'

单文件编译

用 Esbuild 编译 TS/JSX

Pasted image 20220811115750.png

优势:

  • 编译速度提升 10 - 100 倍

局限性:

  • 不支持类型检查
  • 不支持语法降级到 ES5

代码压缩

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

Pasted image 20220811115858.png

插件机制

Pasted image 20220811115931.png

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

插件具体兼容性可查阅 Vite Rollup Plugins

Vite进阶路线

深入双引擎

学习顺序:

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

Vite 插件开发

为什么需要插件机制:

  • 抽离核心逻辑:构建和dev server分开,形成解耦的效果
  • 易于拓展

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

实例:

  1. 开发Vite插件image-20230815214214261
  2. 配置文件引入插件image-20230815214224096

参考资料:

Vite插件开发文档

复杂度较低的插件:json加载插件

复杂度中等的插件:Esbuild接入插件

复杂度较高的插件:官方React插件

代码分割(拆包)

拆包前:

Pasted image 20220811121057.png

问题:

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

拆包后:

image-20230815220336857

参考资料:

cn.vitejs.dev/config/buil…

rollupjs.org/configurati…

JS 编译工具(Babel)

Babel 原理:

Pasted image 20220811121201.png

出现的原因:

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

参考资料:

语法安全降级

以 Promise 语法为例:

Pasted image 20220811121408.png

Pasted image 20220811121415.png

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

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

  • 底层原理

    • 借助 Babel 进行语法自动降级
    • 提前注入 Polyfull 实现,如 core-js、regenerator-runtime

参考资料:

服务端渲染 SSR

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

构建阶段:

Pasted image 20220811121720.png

代码执行阶段:

Pasted image 20220811121729.png

参考资料

深入了解底层标准

重点特性:

  • CJS 规范
  • ESM 规范
  • HTTP 2.0 特性

参考资料:

Vite 社区生态

  • Github 40k+ star(可参考 webpack 61.3k 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