require.context是什么
我们可以先看一下webpack官网有这么个例子:
You can create your own context with the require.context()
function.
It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched too, and a regular expression to match files against.
webpack parses for require.context()
in the code while building.
The syntax is as follows:
require.context(directory, useSubdirectories = true, regExp = /^\.\/.*$/, mode = 'sync');
Examples:
require.context('./test', false, /\.test\.js$/);
// a context with files from the test directory that can be required with a request ending with `.test.js`.
require.context('../', true, /\.stories\.js$/);
// a context with all files in the parent folder and descending folders ending with `.stories.js`.
require.context是webpack的api,可以获取一个特定的上下文,主要用来实现自动化导入模块。在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以考虑使用这个api,遍历文件夹中的匹配文件,然后自动导入,取代逐个导入的写法。
require.context的用法
require.context('.', false, /\.js$/)
先看一下入参:
参数一: 要查询的目录,上述代码指的是当前目录
参数二: 是否要查询子孙目录,方法默认的值为false
参数三: 要匹配的文件的一个正则表达式,上述我要查询的是以.js结尾的文件
require.context函数执行后返回的是一个函数,并且这个函数有3个属性,如下:
resolve (Function):接受一个参数request,request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径
keys (Function) :返回匹配成功模块的名字组成的数组
id (String) :执行环境的id,返回的是一个字符串
与传统做法的对比
传统的做法,在页面路由较少时,通常可能都写在同一个文件内。当页面路由较多通过import引入各个模块,再合并成一个总的路由对象。
某个module路由文件,如下图:
import asyncComponent from "utils/asyncComponent";
const PageManage = asyncComponent(() =>
import("@/app/layout/pageManage/index")
);
const PageAuthority = asyncComponent(() =>
import("@/app/layout/pageManage/authority.js")
);
export default [
{
name: "页面管理",
url: "/pageManage",
icon: "snippets",
key: "ly-upp_pageManage",
children: [
{
name: "页面管理",
url: "/pageManage/pageDetail",
key: "ly-upp_pageManage_pageManege",
component: PageManage,
},
{
name: "页面授权",
url: "/pageManage/pageAuthority",
key: "ly-upp_pageManage_pageAuth",
component: PageAuthority,
}
]
}
];
index总路由文件,如下图:
import home from './module/home.js'
import account from './module/account.js'
import theme from './module/theme.js'
import page from './module/page.js'
import system from './module/system.js'
export const allMenu = [
...home,
...account,
...theme,
...page,
...system
]
通过require.context的方法,当路由模块文件较多,达到简化的效果就越明显,并且在以后添加新的路由模块时,仅需要新增一个路由模块文件,无须在总路由文件手动引入,代码可以直接简化如下图。
// 读取文件路径,是否查找子目录,正则匹配
const routeList = importAll(require.context('./module', true, /\.js/))
export const allMenu = [
...routeList
]
需要注意的一点是,这种方式引入的文件的顺序是以文件名排序的,如果要以特定的顺序还需在额外处理一下。
当然,除了应用在路由模块组件的引入,其实还可以应用在很多地方,例如组件、接口api文件等等,具体需要结合项目进行使用,以达到前端工程自动化。