由两部分组成
- 一个开发服务,服务于开发环境,ESM+HMR
- 一套构建指令,服务于生产环境,用Rollup打包
什么是打包
使用工具抓取、处理并将我们的源码模块串联成可以在浏览器运行的文件
常用前端打包构建工具
- webpack
- rollup
- parcel
- gulp
webpack的缺点
webpack需要遍历整个应用程序,从入口文件开始,把其依赖的所有文件都打包成bundle.js,然后devServer会把js文件传递给客户端的浏览器进行展示。每一次我们修改并保存,都会促发这样一个流程,大型项目消耗大量时间。
传统打包器
ESM打包器
Vite原生支持ESM,浏览器发出HTTP请求,请求响应的entry文件,如果只用到当前文件,它就不会去加载其他文件,只用到当前页面依赖的模块,这样就避免了每次构建都要打包所有文件。类似于按需加载
💥那么Vite是如何实现上述模式的呢?
Vite将模块区分为依赖和源码
- 依赖:开发时不变动的纯js,相当于node_modules文件下的模块,Vite会使用esbuild预构建依赖,esbuild使用go语言编写,效率高
- 源码:包括一些非原生js文件,如.jsx、.css、.vue文件等,这些文件经常会被编译,需要转换,基于路由对其进行拆分,这样就可以避免重复打包,Vite以原生ESM方式提供源码,让浏览器接管打包工作,浏览器请求时按需提供源码,根据具体情境在当前页面被使用到才会被处理
源码模块可能会进行协商缓存,依赖模块会进行强缓存,这样请求速度会更快,应用启动会更快
esm加载对比
接下来我们做一个浏览器原生加载ESM模块的实验
新建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ESM Browser</title>
<!-- 引入main.js文件,类型为module -->
<script src="main.js" type="module"></script>
</head>
<body>
</body>
</html>
引入lodash包
yarn add lodash-es
从lodash中引入filter方法
// 从lodash中引入filter方法
import { filter } from 'lodash-es'
let students = [{ name: tom, age: 20 }, { name: jerry, age: 30 }]
let filterStudent = filter(students, student => student.age > 20)
console.log(filterStudent)
💢出现错误,这是因为浏览器加载模块需要路径,我们修改一下引入路径,改成./node_modules/lodash-es/lodash.js
❗打印出来了 成功❗
查看一下network,发现加载了lodash.js中所有导入的文件,lodash.js中如 export { default as add } from './add.js' 相当于两个操作,先import再export,而浏览器遇到import就是请求模块,所以所有都被请求了,太多无效请求了,那么Vite是如何解决的呢
❤Vite的解决方法
初始化一个Vite项目,选用原生js;选择Vanilla
yarn create vite
同样像上面一样安装lodash-es,并修改 main.js文件,浏览器控制台依然正常打印,可以看到文件变少了
查看一下main.js,发现路径被vite修改了,vite对其进行了处理