vite启动项目
<!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>Document</title>
</head>
<body>
<script type="module" src="./main.js"></script>
</body>
</html>
export const num = 1
import { num } from './counter.js'
console.log(num)
可以看到浏览器支持 ESModule 规范,但是当我们引入 lodash 看看呢?
import { num } from './counter.js'
import _ from 'lodash'
console.log(num)
console.log(_)
可以发现直接报错了,提示我们只能通过绝对路径或者相对路径去查找模块,那么为什么浏览器不直接帮我们从node_modules里面去寻找 lodash 呢?这跟浏览器加载资源有关。
可以看到首先请求了html,然后请求了main.js,在main.js里面使用了counter.js,就会下载counter.js,那么我们想一下,如果浏览器去帮我们寻找node_modules里面的文件的话,例如 lodash 又会依赖其他第三方库,这样就会去把所有的依赖都下载下来,那将会消耗非常大的性能,而在服务器端这样是可以的,因为服务器端是直接去读写文件找寻的,浏览器端是通过网络请求去下载资源的。
这个时候我们可以请出vite来帮我们解决,只需要安装 vite 便可以了,vite 提供了开箱即用的功能
那么 vite 是怎么来处理的呢?
vite依赖与构建
我们可以从浏览器的 network 看看
vite在处理的过程中如果是看到了非绝对路径或者相对路径的引用,他就会尝试开启路径补全。
// lodash可能也import了其他的东西
import _ from "lodash"
// 上面的代码会被打包成下面的形式
import __vite__cjsImport0_lodash from "/node_modules/.vite/deps/lodash.js?v=1272fc7f
依赖构建的过程是自当前目录依次向上查找的过程,直到搜索到根目录或者搜寻到相应的依赖为止。
- 开发环境:在开发环境下我们可以确定路径,比如我们设置了相对路径是 ../ ,那么在执行 yarn dev 开发环境下每次依赖构建时重新构建的相对路径都是正确的。
- 生产环境:vite会全权交给 rollup 库完成生产环境的打包,那么此时是怎样考虑路径问题的呢?我们可以先看看vite的依赖预构建过程
依赖预构建: 首先vite会找到对应的依赖,然后调用esbuild ( 对js语法进行处理的一个库 ) ,将其代码转化成 esmodule 规范,然后放到当前目录下的 node_modules/.vite/deps 下,同时对esmodule规范的各个模块进行统一集成。
export default function a() {}
export { default as a } form '../a.js'
// vite重写以后
function a(){}
我们可以看看下面这个库 lodash-es 这个库是 lodash 通过esmodule导出的,然后又会有很多互相依赖,
import { num } from './counter.js'
import _ from 'lodash'
import lodashEs from 'lodash-es'
console.log(num)
console.log(_)
console.log(lodashEs)
这个时候我们需要学习vite的第一个配置项
import { defineConfig } from 'vite'
export default defineConfig({
optimizeDeps: {
exclude: ['lodash-es'] // 排除指定依赖不进行依赖预构建
}
})
这是没有进行依赖预构建的浏览器请求,可以看到浏览器发起了非常多的请求。
下面是官网截取的一张图
vite的依赖预构建解决了三个问题:
- 不同的第三方包有不同的导出格式,统一进行处理
- 对路径的处理上直接使用 /.vite/deps ,方便路径重写
- 解决网络多包传输性能问题 ( 这也是原生esmodule规范不敢支持node_modules的原因之一 ) 有了依赖预构建以后无论有多少的 import,export,vite都会可能的将他们最后处理成一个或者几个模块