前端工程化背景
在当下的前端项目开发中,主要的模式时都是模块化开发,模块与模块之间都是通过import导入和export导出进行关联。在项目比较小,模块比较少时,我们手动的进行import,export比较的方便,但是当项目比较大,此时模块比较多时,我们如果还是手动的进行导入导出,就有点麻烦,并且如果文件进行了目录移动,维护起来也会比较的费时费力。那么有没有比较简便的办法可以批量进行导出导入操纵呢?这个必须有,它就是require.context
什么是require.context?
require.context是webpack的一个api。通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块。
应用场景
- vue路由文件的自动化注册
- api层请求方法的自动化注册
- vuex modules的合并
- 组件库的开发应用
- ...
如何使用require.context进行工程化
我们以vuex modules的合并为例进行说明
- 查找目标文件夹中的模块信息
/*
* 遍历获取指定文件夹中的目录
* directory:指定的文件目录
* deep:是否递归查找[true|false]
* regExp:正则表达式匹配文件格式
* return webpackContext
*/
const importAll = require.context(directory, deep, regExp)
返回值webpackContext又返回了__webpack_require__, __webpack_require__ 有两个方法和一个属性:(我们主要用到keys方法)
keys: 返回匹配成功模块的名字组成的数组ressolve: 接受一个参数request,request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径id: 执行环境的id,返回的是一个字符串,主要用在module.hot.accept,应该是热加载
- 通过
forEach解析返回的模块数组,并生成目标对象
let modules = {};
importAll.keys().forEach(path => {
//根据文件的相对路径获取模块的文件名
let moduleName = path.replace(/(.*\/)*([^.]+).*/ig, "$2");
//兼容处理:.default获取ES6规范暴露的内容; 后者获取commonJS规范暴露的内容
modules[moduleName] = importAll(path).default || importAll(path)
});
此时modules对象就已经自动合并了目标文件夹匹配到的文件export出来的模块信息。
- 将模板对象添加到vuex模块
const store = new Vuex.Store({
modules: {
...modules,
}
})
总结
通过使用require.context这个api,可以帮助我们在开发大型项目时实现模块的自动化导入功能,极大的解放了我们的注意力,使得的我们的关注点在模块的应用,而不需要过分的关注模块是否注册,并且一旦配置,一劳永逸。