使用require.context实现前端工程自动化

1,453 阅读2分钟

使用require.context实现前端工程自动化

本文大量参考:使用require.context实现前端工程自动化

主要介绍webpack的 api :requir.context。以及这个requir.context实现工程化的常用场景。

什么是requir.context?

一个webpack的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块。在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块。

requir.context的语法

  • 语法如下:

    require.context(directory, useSubdirectories = false, regExp = /^\.\//)

  • require.context函数接受三个参数:

    1. directory {String}:读取文件的目录路径
    2. useSubdirectories {Boolean}:是否深入遍历,即是否遍历子目录(二级目录)
    3. regExp {RegExp}:匹配目录内文件的正则表达式
  • 实例:

    require.context('./test', false, /.test.js$/)

    上面的实例即匹配当前目录下的test目录中的所有 .test.js 结尾的文件,不匹配子目录。

深入了解requir.context

以下文字的代码示例以及目录结构:

let ceshi = require.context('@/assets/icons', true, /\.svg$/);

console.dir(ceshi);
console.log('ceshi',ceshi);
console.log('ceshi.keys()',ceshi.keys());
console.log('ceshi.resolve',ceshi.resolve(ceshi.keys()[0]));
console.log('ceshi.id',ceshi.id);
console.log('ceshi(ceshi.keys()[0])',ceshi(ceshi.keys()[0]));
# 目录结构

src/assets/
|-- icons
|   |-- label.svg
|   |-- left.svg
|   |-- money.svg
|   |-- right.svg
|   `-- statistics.svg
`-- style
    |-- helper.scss
    `-- reset.scss

我们可以通过一个变量来接收require.context的返回值:let ceshi = require.context('../assets/icons', true, /\.svg$/);

通过 console.log这个变量 我们发现require.context执行后的返回值是一个函数。再通过console.dir可以看到这个函数内部有3个属性:id{String},keys{Function},resolve{Function}。

  • id:执行环境的id,返回的是一个字符串,主要用在module.hot.accept。

  • keys:返回匹配成功模块的名字组成的数组。

  • resolve:接受一个参数request,返回这个匹配文件相对于整个项目目录的相对路径。术语:request参数,但这个参数一般会传入 require.context 创建context时传入的目录下文件的路径。

同时,require.context返回的函数可以接收一个参数:request。 这个返回的函数执行后返回request所对应文件暴露的Module对象。我们 import 的东西就是其它文件暴露出来的Module。

实现工程化

现在我们已经了解了require.context,这个api通常应用于加载svg图标以及合并多个路由文件。

  • 加载svg图标

    let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
    try {importAll(require.context('@/assets/icons', true, /\.svg$/));} catch (error) {console.log(error);}
    

    上面的实例中就将 @/assets/icons 目录下的所有svg文件都加载进当前文件。

  • 合并多个路由文件

    路由文件:

    export default [
        {
            path: '/',
            redirect: '/label'
        }
    ]
    

    当有多个路由文件时,我们可以将它们合并成一个:

    let myRoutr = []
    let mergeRouter = require.context('@/router',true,/.js$/)
    mergeRouter.key().forEach(key=>{
        myRouter.concat(mergeRouter(key).default)
    })
    export default myRouter
    

    这个router直接暴露给外层的 main.js 即可。

    小技巧:在使用require.context自动导入路由文件时发现一个问题,路由的顺序不是你期望的样子,因为webpack是根据你文件夹中文件的位置排序的,这个时候需要定义一个标识符来给路由数组排序,这里我们给每个文件夹最上层的路由添加一个sort属性用于排序