# 服务器启动前触发
通过源码中的注释: // overwrite listen to run optimizer before server start, 可以发现在服务器启动前, httpServer.listen启动前运行优化器。
调用 createServer 启动前,将会重写 listen 方法,调用优化器之后,再进行 listen 启动。
const listen = httpServer.listen.bind(httpServer)
httpServer.listen = (async (port: number, ...args: any[]) => {
try {
await runOptimize()
}
return listen(port, ...args)
}) as any
如果采用其它框架做为服务器时, 服务的器的启动是由开发者自行调用, 但在执行启动前 createServer 内部同样也会等到优化器执行完毕。
if (!middlewareMode && httpServer) {
...
} else {
await runOptimize()
}
# 浏览器导入资源时触发
在服务器启动前, 会对从 启动的html入口 和 自定义 optimizeDeps.entries 进行递归检查导入扫描, 收集构建依赖进行优化, 但是往往有些情况下, 优化扫描器并不能完全扫描收集到所有的构建依赖, 会有以下情况:
import动态加载
const root = 'util'
import(/* @vite-ignore */ `./${root}/index.js`)
// util/index.js
import lodash from 'lodash'
lodash 对于 Vite 是需要进行构建的模块, 但在启动前虽然导入了 util/index.js 模块, 将不会深入文件内部扫描。
注意
动态 import 导入模块时, 路径存在 动态变量 时, 扫描器无法对 动态变量 的导入路径进行准确的扫描, 因为 动态变量 是不确定的因素, 在扫描期间并不会对动态变量 进行转换, 无法准确判断导入的路径。
- 通过插件
API中transform方法转换源代码
// one.js
export default {}
// 插件方法
function myPlugin () {
return {
transform(src, id) {
if (id.indexOf('one.js') >= 0) {
return `
import dayjs from 'dayjs'
${src}
`
}
},
}
}
dayjs 对于 Vite 是需要进行构建的模块, 在服务启动前并不会执行插件 transform 方法。
注意
插件 API 中 transform 是浏览器加载资源时, 服务器会经过此函数进行转换后再把内容发送到浏览器, 扫描器将无法提前识别转换后的文件内容。
- 通过插件
resolveId和load插件API引入虚拟文件
// 引入的虚拟模块
import File from '@my-virtual-file'
// 插件内容
function myPlugin () {
return {
resolveId (id) {
if (id === '@my-virtual-file') {
return '@my-virtual-file'
}
},
load(id) {
if (id === '@my-virtual-file') {
return `
import moment from 'moment'
export default {}
`
}
},
}
}
@my-virtual-file 虚拟模块在扫描依赖时, 解析导入模块 id 时会原封动返回, 会被扫描器当作虚拟模块进行过滤, 返回 true。
// virtual id
if (resolvedId === rawId || resolvedId.includes('\0')) {
return true
}
注意
load 同样和 transform 原理一样, 只有在浏览加载虚拟模块时, 服务器执行 load 向浏览器返回生成后的内容, 也无法在服务器启动前被扫描器收集到需要构建依赖。
← 为什么需要预构建(二) 预构建执行逻辑 →