这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战
本文内容已在本人项目中应用,欢迎clone查看。github.com/chris-zhu/c…
import.meta.glob
首先放出vite的官网:vite官网
本文的功能应用主要取决于vite
的glob
api
Vite 支持使用特殊的 import.meta.glob
函数从文件系统导入多个模块:
const modules = import.meta.glob('./dir/*.js')
复制代码
以上将会被转译为下面的样子:
// vite 生成的代码
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js')
}
复制代码
你可以遍历 modules
对象的 key 值来访问相应的模块:
for (const path in modules) {
modules[path]().then((mod) => {
console.log(path, mod)
})
}
复制代码
匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。如果你倾向于直接引入所有的模块(例如依赖于这些模块中的副作用首先被应用),你可以使用 import.meta.globEager
代替:
const modules = import.meta.globEager('./dir/*.js')
复制代码
以上会被转译为下面的样子:
// 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
}
复制代码
批量导入
通过对上面api的认识,于是我们就可以对项目中插件、模块等一次性导入,减少app.use(xxx)
的过程
例如:我的项目中引入了很多插件,我将它们统一管理放入modules
文件夹下
我们还需要定义每一个模块的定义,以方便于我们对其统一处理。
例如:
import { createPinia } from 'pinia'
import { piniaPluginPersist } from '@/plugins'
import { UserModule } from '@/types'
export const install: UserModule = (app) => {
const pinia = createPinia()
pinia.use(piniaPluginPersist)
app.use(pinia)
}
复制代码
其实每一个模块都是统一的格式:UserModule
export type UserModule = (ctx: App) => void
复制代码
我将其定义为一个函数,传入我们的app实例。可能聪明的小伙伴已经发现了,这其实就是vue中插件的写法。没错,我们将每一个module封装成了一个plugin,通过在插件中,我们也能拿到app的实例对其操作。
我们回忆一下插件的用法,顺便封装我们的工具函数,于是有
import { Component, createApp, App } from 'vue'
export const createCtx = async(App: Component, fn?: (context: App) => Promise<void> | void, rootContainer = '#app') => {
const context = createApp(App) // 创建app实例
await fn?.(context) // 应用插件
context.mount(rootContainer) // app的挂载
return context
}
复制代码
上面我们已经封装了我们的工具函数,下面我们只需要循环我们的modules,逐步应用就好了。
最后一步,如何导入?这就不得不用上 上面的api了 于是有
createCtx(App, (ctx) => {
Object.values(import.meta.globEager('./modules/*.ts')).map(i => i.install?.(ctx))
})
复制代码
于是,我们就完美应用上了我们所有的模块了。