[这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天]
1. 前端为什么需要构建工具
- 前端工程的痛点
- 模块化规范不统一
- 资源编译的问题,针对高级语法的编译
- 产物质量问题
- 代码需要压缩, 以此来提升性能
- 对于未使用的模块,需要剔除来优化体积
- 产物的语法兼容问题
- 开发效率
- 前端构建工具的意义
- 模块化方案
- 提供模块加载方案
- 比如
webpack中的runtime便是一个模块加载器,对每个模块的导入和导出进行规范统一- 兼容不同的模块化规范
- 语法转移
- 高级语法转译,如 sass, ts 等
- 资源加载,如字体,图片
- 产物质量
- 产物压缩,无用代码删除
- 语法降级
- 开发效率
- 热更新
2. vite
- 两大组成部分
- No-bundle 开发服务,源文件无需打包
- 生产环境基于 Rollup 的 Bundle
- 核心特征
- 高性能,dev 启动速度更快, 热更新的速度很快
- 简单易用
- 浏览器原生 ESM 支持
- 两大要素
- script 标签新增加 type = " module " 属性, vite 的
dev server也正是基于此来实现不打包- 使用 ESM 模块导入导出语法
- dev server 基于原生 ESM 的开发服务优势
- 无需打包项目源代码,去除了 bundle 的开销
- 天然的按需加载
- 可以利用文件级的浏览器缓存
- 内置的 Web 构建能力
3. 如何使用 vite
- 项目初始化
- 使用静态资源
- 静态资源可以直接 import 使用
- 除了常见的图片格式,Vite 也内置了对于 JSON,Worder,WASM 资源的加载支持
- 使用 HMR
- HMR 可以保持组件的状态
- 生产环境的 Tree Shaking
- 优化原理
- 基于 ESM 的 import / export 语句依赖关系,与运行时无关
- 在构建阶段将未使用到的代码进行删除
4. Vite 整体架构
- 关键技术:开发环境的依赖预打包
node_modules中包的依赖关系十分复杂,可能你想要引入一个包,最终会引入多个其他依赖包node_modules中代码的格式是不规范的- 所以为了解决以上问题,
Vite进行了预打包
- 如何进行预打包
- 首先在
dev server启动之前,会扫描代码中用到的依赖- 接着对依赖的代码采用
esbuild进行打包, 之后对业务代码中的import语句进行改写- 关键技术:单文件的编译
- 使用
esbuild进行打包- 优点: 编译速度提升 10 - 100x
- 缺点
- 不支持类型检查,这也是为什么
vite在生产环境构建的时候要调用一次tsc- 不支持将语法降级到
es5- 关键技术:代码压缩
- 是生产环境当中重要的一个阶段
Esbuild作为默认压缩工具,替换传统的 Terser 、 Uglify.js 等压缩工具- 关键技术:插件机制
- 开发阶段: 模拟
Rollup插件机制- 生产环境: 直接使用
Rollup- 最终就是
Vite的插件既可以用到dev阶段也可以用到 生产环境- 但是
Rollup中的插件不一定能使用到Vite当中
5. Vite 进阶之路
- 进修之路 !
- 深入双引擎
- 在
Vite的底层中非常依赖的两个引擎:Esbuild和Rollup- 先了解基本使用,动手尝试各种配置项
- 然后学习插件开发
- Vite 的插件开发
- 为什么需要插件机制?
- 抽离核心逻辑
- 易于拓展
- Vite 提供的 hook
- 插件实例
- Vite 代码分割(拆包)
- 不拆包的问题
- 因为最终文件没有进行拆包操作,所以打包产物只有一个文件,无法进行并发请求,无法发挥浏览器的优势
- 由于产物没有进行拆包操作,一旦某个地方进行改动,那么就要重新打包,重新请求,缓存复用率低
- JS 编译工具 Babel
- JS 语法标准繁多,浏览器支持程度不一
- 开发者需要用到高级语法
- 语法的安全降级
- 如何在构建产物中避免这类问题
- 上层解决方案:
@vitejs/plugin-legacy- 底层原理
- 借助
Babel进行语法自动降级- 提前注入
Polyfill实现, 如core-js- 服务端渲染
- 一种常见的渲染模式,用于提升首屏性能和 SEO 优化