这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天
前端工程化的痛点:模块化(ESM、CommonJS、UMD);资源编译(高级语法的编译);产物质量(代码体积、代码性能);开发效率(热更新)
Vite特点:
- No-bundle开发服务,源文件无需打包
- 生产环境基于Rollup的Bundler
- 高性能,dev启动速度和热更新速度非常快
- 简单易用,开发者体验好
优化
- 浏览器原生ESM支持,script标签增加type="module"
- 无需打包项目源代码
- 天然按需加载
- 利用文件级浏览器缓存
- 基于Esbuild的编译性能优化,基于golang开发的前端工具
- 生产环境TreeShaking,在Vite中无需配置默认开启,基于ESM的import/export语句依赖关系,与运行时状态无关
关键技术
-
预打包Pre-bundle
- 避免 node_modules 过多的文件请求,将 CommonJS 格式转换为 ESM 格式
- 原理:
- 服务启动前扫描代码中用到的依赖
- 用 Esbuild 对依赖代码进行预打包
- 改写 import 语句,指定依赖为预构建产物路径
-
单文件编译
- 用Esbuild编译TS/JSX
- 但不支持类型检查,不支持语法降级到ES5
-
代码压缩
- Esbuild 作为默认压缩工具,替换传统的 Terser、Uglify.js 等压缩工具
-
插件机制
- 开发阶段模拟 Rollup 插件机制;生产环境直接使用 Rollup
进阶
- 深入双引擎:esbuild和rollup
- 插件开发:抽离核心逻辑,易于拓展
- 代码分割 分包
- 语法安全降级
- 使用@vitejs/plugin-legacy,实际是借助babel,然后提前注入polyfill实现
- 服务端渲染SSR
Vite和webpack对比
区别关键在于是否采用bundle机制
webpack
Webpack 能大行其道,归功于它划时代的采用了 bundle 机制。通过这种 bundle 机制,Webpack 可以将项目中各种类型的源文件转化供浏览器识别的 js、css、img 等文件,建立源文件之间的依赖关系,并将数量庞大的源文件合并为少量的几个输出文件。
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 在启动过程中只需做一些初始化的工作,剩下的完全由浏览器支持。源文件的 resolve、load、transform、parse 会在浏览器发起请求以后,dev server 端会通过 middlewares 对请求做拦截,然后对源文件做 resolve、load、transform、parse 操作,然后再将转换以后的内容发送给浏览器。
结论
- webpack构建慢启动慢,热更新慢
- Vite首屏性能差,懒加载慢