概述
在工程化项目当中,有时候我们可能需要在运行时态自动批量处理某个文件夹下的所有文件,比如有个如下功能要做:
在一个有不同模块的多语言文件分割的文件中,需要将moudle文件夹下的多语言模块合并到index中进行合并,然后通过i18工具进行多语言注册,常规做法在index中一个个导入对于模块,然后合并,但是随着模块文件越来越多,index里面导入的文件就会变得越来越庞大,并且没有自动化的程度,导致每加一个模块都需要手动导入(很麻烦)。
针对上面的问题,引入模块运行时自动导入的概念,在工程化项目中(vue、react等),如果需要再运行时获取到工程项目文件的目录相关信息(编译时态),最终经过打包工具(webpack、vite)打包后(运行时态),处理对于文件相关逻辑,因此,根据环境webpack、vite,能够找到两个对于的api
- require.context
- import.meta.glob
介绍
(1)require.context(Webpack 特有)
require.context
是 Webpack 提供的一个 API,允许在编译时创建一个上下文,用于匹配指定目录下的文件,并支持动态导入。
(2)import.meta.glob(Vite/Rollup 特有)
import.meta.glob
是 Vite 和 Rollup 提供的功能,用于实现类似 require.context
的模块批量导入,但语法更现代化,支持 ESM(ES Module)。
特性 | require.context |
import.meta.glob |
---|---|---|
所属工具 | Webpack | Vite / Rollup |
加载方式 | 同步/动态导入 | 默认懒加载 |
返回值 | 函数 | 对象(Promise) |
适用场景 | Webpack 项目 | Vite / Rollup 项目 |
核心用途:为什么需要它们?
(1)自动注册全局组件
在 Vue 项目中,我们通常需要手动注册全局组件:
JavaScript
import Button from './components/Button.vue';
import Input from './components/Input.vue';
// ... 其他组件
app.component('Button', Button);
app.component('Input', Input);
// ... 重复注册
使用 require.context
或 import.meta.glob
可以自动扫描目录并注册,避免重复代码!
(2)动态加载路由
在大型项目中,路由可能非常多,手动导入会很麻烦:
JavaScript
// 传统方式
import Home from './views/Home.vue';
import About from './views/About.vue';
// ... 其他路由
使用批量导入,可以自动生成路由表,提高可维护性。
(3)按需加载语言包/配置文件
例如国际化(i18n)场景,不同语言包可以动态加载:
JavaScript
// 自动加载所有语言包
const locales = import.meta.glob('./locales/*.json');
使用方式对比
(1)require.context(Webpack)
基本语法:
JavaScript
const context = require.context(
directory, // 要搜索的目录
useSubdirectories, // 是否搜索子目录
regExp, // 匹配文件的正则表达式
mode // 加载模式(可选)
);
示例:自动注册 Vue 组件
JavaScript
const ctx = require.context('./components', true, /.vue$/);
ctx.keys().forEach(path => {
const component = ctx(path).default;
const name = path.split('/').pop().replace('.vue', '');
app.component(name, component);
});
(2)import.meta.glob(Vite)
基本语法:
JavaScript
const modules = import.meta.glob(globPattern, options);
示例 1:懒加载(默认)
JavaScript
const modules = import.meta.glob('./components/*.vue');
for (const path in modules) {
modules[path]().then((mod) => {
const name = path.split('/').pop().replace('.vue', '');
app.component(name, mod.default);
});
}
示例 2:直接导入(非懒加载)
JavaScript
const modules = import.meta.glob('./components/*.vue', { eager: true });
Object.entries(modules).forEach(([path, mod]) => {
const name = path.split('/').pop().replace('.vue', '');
app.component(name, mod.default);
});
核心区别与如何选择?
对比项 | require.context |
import.meta.glob |
---|---|---|
构建工具 | Webpack | Vite / Rollup |
加载方式 | 同步(默认) | 懒加载(默认) |
返回值 | 函数(context() ) |
对象({ path: Promise } ) |
适用场景 | 旧项目(Webpack) | 新项目(Vite) |
如何选择?
- 如果你的项目使用 Webpack ,用
require.context
。 - 如果是 Vite / Rollup 项目,用
import.meta.glob
。 import.meta.glob
更现代化,推荐新项目使用。
高级用法:动态路由、国际化等
(1)动态路由(Vite + Vue Router)
JavaScript
const pages = import.meta.glob('../views/**/*.vue');
const routes = Object.entries(pages).map(([path, component]) => {
const name = path.replace('../views/', '').replace('.vue', '');
return { path: `/${name}`, component };
});
const router = createRouter({
history: createWebHistory(),
routes,
});
(2)国际化(i18n 自动加载语言包)
JavaScript
const locales = import.meta.glob('./locales/*.json', { eager: true });
const messages = {};
Object.entries(locales).forEach(([path, mod]) => {
const lang = path.split('/').pop().replace('.json', '');
messages[lang] = mod.default;
});
const i18n = createI18n({
locale: 'zh',
messages,
});
总结
require.context
是 Webpack 提供的批量导入方案,适用于传统项目。import.meta.glob
是 Vite/Rollup 的现代化替代方案,默认懒加载,更灵活。- 两者都能用于 自动注册组件、动态路由、国际化 等场景。
- 新项目推荐使用 Vite +
import.meta.glob
,体验更佳! - 对于工程化项目(组件库)使用可以大大提高开发效率(组件注册)。