# 前端工程自动化

# require.context (opens new window)

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

# 异步组件加载

  1. 批量用:require.context('locales', true, /\.js$/, 'lazy')
  2. 单个组件:import(/* webpackChunkName: "home" */ '@/xxxx')
  3. webpack 把这个模块导出一个 js 文件,然后用到这个模块的时候,就动态构造 script 标签插入 DOM,再由浏览器去请求。

# 什么时候用

在 Vue 写的项目中,路由通过不同的功能划分成不同的模块,在 index.js 中一个个导入,但是如果项目变大了之后,每次手动 import 会显得代码很长,这里可以使用 require.context 函数遍历 modules 文件夹的所有文件一次性导入到 index.js 中。

// 一个个文件导入
import a from './modules/a'
import b from './modules/b'
import c from './modules/c'
import d from './modules/d'
import e from './modules/e'
import f from './modules/f'
import g from './modules/g'
import h from './modules/h'
// ....

// 再一个个解构
export default new Router({
  routes: [
    ...a,
    ...b,
    ...c,
    ...d,
    ...e,
    ...f,
    ...g,
    ...h
    // ...
  ]
})

# 如何使用

  1. 新建获取全路由的方法
/**
 * 获取全路由
 * @param {Array} context 数组
 * @param {Object} ignore 字符
 */
export const getRoutes = (context, ignore) => {
  const children = []
  context.keys().forEach(key => {
    if (key !== ignore) {
      try {
        let arr = context(key).default
        if (arr && arr.length) {
          children.push(...arr)
        }
      } catch (e) {
        console.error(e)
      }
    }
  })
  return children
}
  1. 在 router/modules 下新建index.js文件
import { getRoutes } from '_utils/utils'
/**
 * @desc require.context函数三个参数
 * @param directory {String} -读取文件的路径
 * @param useSubdirectories {Boolean} -是否遍历文件的子目录
 * @param regExp {RegExp} -匹配文件的正则
 */
export default getRoutes(require.context('./', false, /\.js$/), './index.js')
  1. 修改路由index.js文件
import Router from 'vue-router'
import routes from './modules'

export default new Router({
  mode: 'history',
  base: '/vue',
  routes
})
  1. 同理 store 自动加载改造如下
/**
 * @desc 加载所有store文件
 */
const getModules = (context, ignore) => {
  const modules = {}
  context.keys().forEach(key => {
    if (!ignore.includes(key)) {
      modules[key.replace(/\.\/|\.js/g, '')] = context(key).default
    }
  })
  return modules
}

export default getModules(require.context('./', false, /\.js$/), './index.js')

# 拓展 globEager

vite 脚手架下使用import.meta.globEager替换require.contextAPI

import { getRoutes } from '@/utils/common'

export default getRoutes(import.meta.globEager('./*.ts'), './index.ts')