前端工程自动化——动态导入

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文件等等,具体需要结合项目进行使用,以达到前端工程自动化。

上一篇:servlet 具体实现


下一篇:Mysql学习笔记(十三)权限管理