工程化与Vite | 字节青训营

71 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天

前端工程化的痛点:模块化(ESM、CommonJS、UMD);资源编译(高级语法的编译);产物质量(代码体积、代码性能);开发效率(热更新)

image.png

Vite特点:
  1. No-bundle开发服务,源文件无需打包
  2. 生产环境基于Rollup的Bundler
  3. 高性能,dev启动速度和热更新速度非常快
  4. 简单易用,开发者体验好
优化
  1. 浏览器原生ESM支持,script标签增加type="module"
    1. 无需打包项目源代码
    2. 天然按需加载
    3. 利用文件级浏览器缓存
  2. 基于Esbuild的编译性能优化,基于golang开发的前端工具
  • 生产环境TreeShaking,在Vite中无需配置默认开启,基于ESM的import/export语句依赖关系,与运行时状态无关

image.png

关键技术
  1. 预打包Pre-bundle

    1. 避免 node_modules 过多的文件请求,将 CommonJS 格式转换为 ESM 格式
    2. 原理:
      1. 服务启动前扫描代码中用到的依赖
      2. 用 Esbuild 对依赖代码进行预打包
      3. 改写 import 语句,指定依赖为预构建产物路径
  2. 单文件编译

    • 用Esbuild编译TS/JSX
    • 但不支持类型检查,不支持语法降级到ES5
  3. 代码压缩

    • Esbuild 作为默认压缩工具,替换传统的 Terser、Uglify.js 等压缩工具
  4. 插件机制

    • 开发阶段模拟 Rollup 插件机制;生产环境直接使用 Rollup
进阶
  1. 深入双引擎:esbuild和rollup
  2. 插件开发:抽离核心逻辑,易于拓展

image.png

  1. 代码分割 分包
  2. 语法安全降级
    • 使用@vitejs/plugin-legacy,实际是借助babel,然后提前注入polyfill实现
  3. 服务端渲染SSR
Vite和webpack对比

区别关键在于是否采用bundle机制

webpack

Webpack 能大行其道,归功于它划时代的采用了 bundle 机制。通过这种 bundle 机制,Webpack 可以将项目中各种类型的源文件转化供浏览器识别的 jscssimg 等文件,建立源文件之间的依赖关系,并将数量庞大的源文件合并为少量的几个输出文件。

bundle 工作机制的核心部分分为两块:构建模块依赖图 - module graph 和将 module graph 分解为最终供浏览器使用的几个输出文件。

webpack构建速度慢的主要原因是构建 module graph 的过程中,涉及到大量的文件 IO、文件 transfrom、文件 parse 操作;以及分解 module graph 的过程中,需要遍历 module graph、文件 transform、文件 IO 等。这些操作,往往需要消耗大量的时间,导致构建速度变得缓慢。

Vite

而Vite采取unbundle机制,即不需要构建、分解 module graph,源文件之间的依赖关系完全通过浏览器对 ESM 规范的支持来解析。这就使得 dev server 在启动过程中只需做一些初始化的工作,剩下的完全由浏览器支持。源文件的 resolveloadtransformparse 会在浏览器发起请求以后,dev server 端会通过 middlewares 对请求做拦截,然后对源文件做 resolveloadtransformparse 操作,然后再将转换以后的内容发送给浏览器。

结论
  • webpack构建慢启动慢,热更新慢
  • Vite首屏性能差,懒加载慢

借鉴:juejin.cn/post/712904…