以下说明都以批量导入路由为例
1.基于Webpack的require.context批量导入
//files返回一个函数
const files = require.context('./modules', false, /\.tsx$/, 'sync')//默认是sync模式
//如果是路由这种开始就要导入的就用同步sync模式,如果是异步组件这种就用异步导入
export const rootRouter: RouteObject[] = [
{
path: '/',
//非懒加载组件
element: <Login />,
//路由元信息
},
]
//通过files.keys()遍历获取每个id,然后调用files(id),把遍历获取的id传入这个函数,最后返回一个模块,通过.default获取
files.keys().forEach(key => {
//1.通过sync方式(会阻塞同步代码)
rootRouter.push(...files(key).default)
//2.通过lazy,lazy-once,eager方式,返回一个promise,(调用时不会阻塞同步代码)
files(key).then((module: any) => {
rootRouter.push(...module.default)
})
})
require.context的第四个参数模式:
前言:我现在有四个路由模块,批量导入,可以理解为bundle是打包后当前整个文件的代码,chunk相当于是当前导入部分用到的的代码块
-
sync直接打包到当前文件的bundle中(导入的这部分代码会被立即打包到bundle中并且直接执行,可以理解为开始就加载并执行),不生成单独chunk,同步加载并执行四个模块全部被打包到当前文件的bundle了
-
lazy延迟加载(异步导入)会为每个模块分离出单独的 chunk 文件(发起导入的这部分代码不会被预打包到bundle中,在执行时生成chunk加载该部分的代码并且执行,可以理解为开始不加载,调用执行时再加载代码并执行),返回promise需要时调用(调用时异步执行代码不阻塞同步代码,每次执行都会重新发起请求异步导入一次)可以看到被分离为了四个不同的chunk,并且每次重载都会重新导入一次这四个模块
-
lazy-once延迟加载会分离出单独的 chunk 文件但是多个模块会合成一个chunk(发起导入的这部分代码不会被预打包到bundle中,在执行时生成chunk加载该部分的代码并且执行,可以理解为开始不加载,调用执行时再加载代码并执行),返回promise需要时调用,加载过下次再加载直接读取内存里的代码(并建立缓存,后续再次导入使用第一次导入的数据)
eager和sync相同,代码会预先被打包到一个bundle中(发起导入的这部分代码会预打包到bundle中,可以理解为开始就加载,但是不立即执行),区别是eager返回的promise可以延迟执行(但是代码其实是预加载到了bundle中,只是何时执行由我们决定)
2.基于Vite的glob和globEager(代码以globEager为例)
const metaRouters = import.meta.globEager("./modules/*.ts");
export const routerArray: RouteRecordRaw[] = [];
//globEager不像require.context返回一个函数,然后接收keys再回头调用这个函数,它可以直接用Object.values遍历返回的值
Object.values(metaRouters).forEach(item => {
console.log(item["default"]);
routerArray.push(...item["default"]);
});
glob和globEager的区别:与require.context的第四个参数一样,globEager相当于sync,glob相当与lazy
3.node基于fs模块导入后端路由(代码以sync为例)
import Koa from 'koa'
import Router from 'koa-router'
import fs from 'fs'
const useRoutes = function (app: Koa) {
fs.readdirSync(__dirname).forEach((file: any) => {
try {
if (file === 'index.js' || file === 'index.ts') return
else if (/.[jt]s$/.test(file)) {
const router: Router = require(`./${file}`).default
app.use(router.routes()).use(router.allowedMethods())
}
} catch (error) {
console.errtime('路由注册失败:' + error + '文件名:' + file)
}
})
}
fs如果想要变成异步可以用fs/promise
import fs from 'fs/promise'
fs.readdir()//node中从xx/promise导入node自带的异步方法的模块,方法不需要以Sync结尾