为什么需要vite?
前端工程化难点
- 模块化
模块化是将一个大型程序或项目分解为更小、更易管理的模块或组件的开发方法。
模块化的优点:
- 可维护性:将代码分解为模块可以使代码更易于维护。每个模块负责特定功能或特性,这使得修改和更新代码更加直观和容易。当出现错误或需要改进时,可以更快速地定位和修复问题。
- 可重用性
- 可扩展性:通过添加新模块来增加功能
- 代码可读性
- 性能优化:按需加载,只在需要的时候加在特定模块
-
资源编译
浏览器的标准赶不上前端开发者的需求
-
产物质量
-
代码需要压缩
-
对于未使用的模块从构建产物中剔除
-
语法兼容性
-
-
开发效率
构建工具的意义
- 模块化方案
- 提供模块加载方案
- 兼容不同模块方案
- 语法转译
- 高级语法转译
- 资源加载
- 产物质量
- 产物压缩
- 无用代码删除
- 语法降级
- 开发效率
- 热更新
构建工具的作用实际上是让开发者可以模块化开发,只需要适当的配置,就能在开发完成后轻松的打包项目。
Vite介绍
组成
- No-bundle开发服务,源文件无需打包
- 生产环境基于Rollup的Bundler
核心特征
- 高性能,dev启动速度和热更新速度非常快
- 简单易用
传统构建工具问题
- 缓慢的启动:项目编译等待成本高
- 缓慢的热更新:开发时修改代码后不能实时更新
瓶颈
- 打包带来的性能开销
- js语言的性能瓶颈
两大行业趋势
- 浏览器对原生ESM的普遍支持
- 使用ESM模块导入导出语法
- 无需打包
Vite利用了浏览器对原生 ES 模块的支持
- 无需打包项目源代码,可以实现快速的冷启动和模块热更新
冷启动:开发者启动开发服务器,以在开发环境中运行应用程序。
热重载:在应用程序正在运行的情况下,通过替换或更新代码,实时更新应用程序的部分或全部内容,而无需重新加载整个应用程序或页面。
- 按需编译:让浏览器接管打包程序的部分工作。Vite 只会编译和构建当前正在被浏览器请求的那些模块,而不是整个应用程序。
- 可以利用文件级的浏览器缓存
- 基于原生语言(Go、Rust)编写前端编译工具链
原生语言:具有较低的抽象级别,编译型语言,需要通过编译器将源代码转换成机器码或汇编代码,然后执行。
Esbuild
- 打包器
- 编译器
- 压缩器
Vite使用Esbuild预构建依赖
- 原生 ES 导入不支持下面这样的裸模块导入:
import { someMethod } from 'my-dep'
上面的代码会在浏览器中抛出一个错误。Vite 将会检测到所有被加载的源文件中的此类裸模块导入,并执行以下操作:
- 预构建 它们可以提高页面加载速度,并将 CommonJS / UMD 转换为 ESM 格式。预构建这一步由 esbuild 执行,这使得 Vite 的冷启动时间比任何基于 JavaScript 的打包器都要快得多。
- 重写导入为合法的 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
通过静态代码分析,从应用程序的模块依赖关系图中识别和移除未使用代码的优化技术,以减小最终生成的包的大小,提高前端应用程序性能。