Vite学习总结 | 青训营

62 阅读4分钟

为什么需要vite?

前端工程化难点

  1. 模块化

模块化是将一个大型程序或项目分解为更小、更易管理的模块或组件的开发方法。

模块化的优点:

  • 可维护性:将代码分解为模块可以使代码更易于维护。每个模块负责特定功能或特性,这使得修改和更新代码更加直观和容易。当出现错误或需要改进时,可以更快速地定位和修复问题。
  • 可重用性
  • 可扩展性:通过添加新模块来增加功能
  • 代码可读性
  • 性能优化:按需加载,只在需要的时候加在特定模块
  1. 资源编译

    浏览器的标准赶不上前端开发者的需求

  2. 产物质量

    • 代码需要压缩

    • 对于未使用的模块从构建产物中剔除

    • 语法兼容性

  3. 开发效率

构建工具的意义

  1. 模块化方案
    • 提供模块加载方案
    • 兼容不同模块方案
  2. 语法转译
    • 高级语法转译
    • 资源加载
  3. 产物质量
    • 产物压缩
    • 无用代码删除
    • 语法降级
  4. 开发效率
    • 热更新

构建工具的作用实际上是让开发者可以模块化开发,只需要适当的配置,就能在开发完成后轻松的打包项目。

Vite介绍

组成

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

核心特征

  1. 高性能,dev启动速度和热更新速度非常快
  2. 简单易用

传统构建工具问题

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

瓶颈

  • 打包带来的性能开销
  • js语言的性能瓶颈

两大行业趋势

  1. 浏览器对原生ESM的普遍支持
    • 使用ESM模块导入导出语法
    • 无需打包

Vite利用了浏览器对原生 ES 模块的支持

  • 无需打包项目源代码,可以实现快速的冷启动和模块热更新

冷启动:开发者启动开发服务器,以在开发环境中运行应用程序。

热重载:在应用程序正在运行的情况下,通过替换或更新代码,实时更新应用程序的部分或全部内容,而无需重新加载整个应用程序或页面。

  • 按需编译:让浏览器接管打包程序的部分工作。Vite 只会编译和构建当前正在被浏览器请求的那些模块,而不是整个应用程序。
  • 可以利用文件级的浏览器缓存
  1. 基于原生语言(Go、Rust)编写前端编译工具链

原生语言:具有较低的抽象级别,编译型语言,需要通过编译器将源代码转换成机器码或汇编代码,然后执行。

Esbuild

  • 打包器
  • 编译器
  • 压缩器

Vite使用Esbuild预构建依赖

  • 原生 ES 导入不支持下面这样的裸模块导入:
import { someMethod } from 'my-dep'

上面的代码会在浏览器中抛出一个错误。Vite 将会检测到所有被加载的源文件中的此类裸模块导入,并执行以下操作:

  1. 预构建 它们可以提高页面加载速度,并将 CommonJS / UMD 转换为 ESM 格式。预构建这一步由 esbuild 执行,这使得 Vite 的冷启动时间比任何基于 JavaScript 的打包器都要快得多。
  2. 重写导入为合法的 URL,例如 /node_modules/.vite/deps/my-dep.js?v=f3sf2ebd 以便浏览器能够正确导入它们。
  • Vite 使用 esbuild 将 TypeScript 转译到 JavaScript,约是 tsc 速度的 20~30 倍,同时 HMR 更新反映到浏览器的时间小于 50ms。

Vite实战与架构解析

项目初始化

npm create vite@latest在命令行内选择一些项目模板

通过脚手架创建的 Vite 项目中默认的 npm scripts:

{
  "scripts": {
    "dev": "vite", // 启动开发服务器,别名:`vite dev``vite serve`
    "build": "vite build", // 为生产环境构建产物
    "preview": "vite preview" // 本地预览生产构建产物
  }
}

处理CSS

CSS 预处理器

安装预处理器依赖:

# .scss and .sass
npm add -D sass

# .less
npm add -D less

# .styl and .stylus
npm add -D stylus

CSS Modules

任何以 .module.css 为后缀名的 CSS 文件都被认为是一个 CSS modules 文件。导入这样的文件会返回一个相应的模块对象:

/* example.module.css */
.red {
  color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red

使用静态资源

导入一个静态资源会返回解析后的 URL:

import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

添加一些特殊的查询参数可以更改资源被引入的方式:

// 显式加载资源为一个 URL
import assetAsURL from './asset.js?url'
// 以字符串形式加载资源
import assetAsString from './shader.glsl?raw'
// 加载为 Web Worker
import Worker from './worker.js?worker'
// 在构建时 Web Worker 内联为 base64 字符串
import InlineWorker from './worker.js?worker&inline'

生产环境Tree Shaking

通过静态代码分析,从应用程序的模块依赖关系图中识别和移除未使用代码的优化技术,以减小最终生成的包的大小,提高前端应用程序性能。