即Vite 支持从文件系统导入多个模块:
说明:vite是通过特殊的 import.meta.glob
函数达到该功能的
用法:
const modules = import.meta.glob('./dir/*.js')
上面的内容将会转化为下面的内容:
匹配的文件默认通过动态导入延迟加载,并在构建过程中被分割成单独的块。
// code produced by vite
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js'),
}
如果您希望直接导入所有模块(例如,首先依赖于这些模块中的副作用),您可以传递 { eager: true }
作为第二个参数:
const modules = import.meta.glob('./dir/*.js', { eager: true })
上面的内容将会转化为下面的内容:
// code produced by vite
import * as __glob__0_0 from './dir/foo.js'
import * as __glob__0_1 from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
然后,您可以迭代 modules
对象的键来访问相应的模块:
for (const path in modules) {
modules[path]().then((mod) => {
console.log(path, mod)
})
}
将文件导入为字符串或者URl
将文件作为字符串导入
const modules = import.meta.glob('./dir/*.js', { as: 'raw', eager: true })
//上面的内容将会转化为下面的内容:
// code produced by vite
const modules = {
'./dir/foo.js': 'export default "foo"\n',
'./dir/bar.js': 'export default "bar"\n',
}
将资源作为url导入
{ as: 'url' }
即第一个参数可以是一个混合glob数组
const modules = import.meta.glob(['./dir/*.js', './another/*.js'])
即使用排除的glob模式(以!为前缀)添加到第一个参数来从结果中排除忽略某些文件
const modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])
// code produced by vite
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
}
可以仅使用 import
选项导入部分模块。
const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
// code produced by vite
const modules = {
'./dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),
'./dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),
}
与 eager
结合使用时,甚至可以为这些模块启用树摇动。
const modules = import.meta.glob('./dir/*.js', {
import: 'setup',
eager: true,
})
// code produced by vite:
import { setup as __glob__0_0 } from './dir/foo.js'
import { setup as __glob__0_1 } from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
将 import
设置为 default
以导入默认导出。
const modules = import.meta.glob('./dir/*.js', {
import: 'default',
eager: true,
})
// code produced by vite:
import __glob__0_0 from './dir/foo.js'
import __glob__0_1 from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
使用 query
选项为导入提供自定义查询,以供其他插件使用
const modules = import.meta.glob('./dir/*.js', {
query: { foo: 'bar', bar: true },
})
// code produced by vite:
const modules = {
'./dir/foo.js': () => import('./dir/foo.js?foo=bar&bar=true'),
'./dir/bar.js': () => import('./dir/bar.js?foo=bar&bar=true'),
}
以上这是 Vite 独有的功能,不是 Web 或 ES 标准。
glob 模式被视为导入说明符:它们必须是相对的(以 ./
开头)或绝对的(以 /
开头,相对于项目根解析)或别名路径
全局匹配是通过 fast-glob
完成的
import.meta.glob
中的所有参数都必须作为文字传递。您不能在其中使用变量或表达式。
即Vite 支持带变量的动态导入。
变量仅代表一层深度的文件名。如果 file
是 'foo/bar'
,导入将会失败。
对于更高级的用法,您可以使用 glob 导入功能。
const module = await import(`./dir/${file}.js`)
预编译的 .wasm
文件可以使用 ?init
导入。默认导出将是一个返回 WebAssembly.Instance
的 Promise 的初始化函数:
import init from './example.wasm?init'
init().then((instance) => {
instance.exports.test()
})
init 函数还可以将 importObject 传递给 WebAssembly.instantiate
作为其第二个参数:
init({
imports: {
someFunc: () => {
/* ... */
},
},
}).then(() => {
/* ... */
})
在生产版本中,小于 assetInlineLimit
的 .wasm
文件将内联为 base64 字符串。否则,它们将被视为静态资产并按需获取。
目前不支持 WebAssembly 的 ES 模块集成提案。可使用 vite-plugin-wasm
或其他社区插件来处理此问题。
如果您需要访问 Module
对象,例如要多次实例化它,请使用显式 URL 导入来解析资产,然后执行实例化:
import wasmUrl from 'foo.wasm?url'
const main = async () => {
const responsePromise = fetch(wasmUrl)
const { module, instance } =
await WebAssembly.instantiateStreaming(responsePromise)
/* ... */
}
main()
在 SSR 中,作为 ?init
导入的一部分发生的 fetch()
可能会失败并出现 TypeError: Invalid URL
。
这里有一个替代方案,假设项目库是当前目录:
import wasmUrl from 'foo.wasm?url'
import { readFile } from 'node:fs/promises'
const main = async () => {
const resolvedUrl = (await import('./test/boot.test.wasm?url')).default
const buffer = await readFile('.' + resolvedUrl)
const { instance } = await WebAssembly.instantiate(buffer, {
/* ... */
})
/* ... */
}
main()
可以使用 new Worker()
和 new SharedWorker()
导入 Web Worker 脚本。与worker后缀相比,这种语法更接近标准,是创建worker的推荐方法。
const worker = new Worker(new URL('./worker.js', import.meta.url))
工作构造函数还接受选项,可用于创建“模块”works
const worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module',
})
可以通过将 ?worker
或 ?sharedworker
附加到导入请求来直接导入 Web Worker 脚本。默认导出将是自定义工作构造函数:
import MyWorker from './worker?worker'
const worker = new MyWorker()
worker脚本还可以使用 ESM import
语句代替 importScripts()
。注意:在开发过程中,这依赖于浏览器本机支持,但对于生产版本,它会被编译掉。
默认情况下,worker脚本将作为生产构建中的单独块发出。如果您希望将worker程序内联为 base64 字符串,请添加 inline
查询:
import MyWorker from './worker?worker&inline'
下面列出的功能将作为构建过程的一部分自动应用,除非您想禁用它们,否则不需要显式配置。
Vite 自动提取异步块中模块使用的 CSS 并为其生成单独的文件。当加载关联的异步块时,CSS 文件会通过 <link>
标签自动加载,并且保证异步块仅在 CSS 加载后才被评估以避免 FOUC。
果您希望将所有 CSS 提取到一个文件中,可以通过将 build.cssCodeSplit
设置为 false
来禁用 CSS 代码拆分。
Vite 自动为条目块生成 <link rel="modulepreload">
指令,并在构建的 HTML 中直接导入它们。
在现实世界的应用程序中,Rollup 通常会生成“公共”块 - 在两个或多个其他块之间共享的代码。结合动态导入,下面的场景是很常见的:
在非优化场景中,当导入异步块 A
时,浏览器必须请求并解析 A
才能发现它还需要公共块 C
。这会导致额外的网络往返:Entry ---> A ---> C
Vite 使用预加载步骤自动重写代码分割动态导入调用,以便在请求 A
时,并行获取 C
:Entry ---> (A + C)
C
可能会进行进一步的导入,这将导致在未优化的情况下出现更多的往返次数。 Vite的优化??将跟踪所有直接导入,以完全消除往返,无论导入深度如何。