Webpack中require.context函数 & 应用实践

857 阅读1分钟

require.context() 函数

可以使用 require.context() 函数创建自己的上下文(context),在 webpack 构建时会解析代码中的 require.context()

用于加载一个目录中的所有文件或过滤部分文件,简化代码,进而实现自动化导入模块

语法如下:

/**
 * @param directory {String} 必传。目录路径,可使用相对路径,用于创建上下文
 * @param useSubdirectories {Boolean} 非必传。是否包含子目录,默认值为true
 * @param regExp {RegExp} 非必传。过滤结果的正则表达式,默认值为 /^\.\/.*$/ 表示所有文件
 * @returns 导出一个 require 函数,同时它也是一个对象
 */
require.context(directory,  (useSubdirectories = true),  (regExp = /^\.\/.*$/));

示例:

require.context('../', true, /\.stories\.js$/);
// 创建出一个 context,其中所有文件都来自父文件夹及其所有子级文件夹,request 以 `.stories.js` 结尾。

WARNING:传递给 require.context 的参数必须是字面量【文末有名词介绍】。

require.context() 导出的 require 函数

require.context() 会导出一个 require 函数:


// 此导出函数可以接收一个参数 : req

ƒ webpackContext(req) {
	var id = webpackContextResolve(req);
	return __webpack_require__(id);
}

此导出函数有三个属性: keysresolveid

  • keys 也是一个函数,它返回一个数组,由所有可能被此 context module 处理的请求组成(匹配到的所有模块路径字符串组成的数组,如 ['./top.stories.js', 'footer.stories.js'])。将数组中的任一请求作为实参传入导出的 require 函数,则返回这个文件的 ES Module,访问这个 ES Moduledefault 就可以访问模块的默认导出

  • resolve 是一个函数,它返回 request 被解析后得到的模块 id

  • id 是 context module 的模块 id. 它可能在你使用 module.hot.accept 时会用到

应用实践

注册全局组件

语法:

Vue.component('my-component-name', { /* ... */ })

代码:

import Vue from 'vue'
const requireAll = require.context('./components', false, /\.vue$/)

requireAll.keys().forEach(req => {
  const { default: module } = requireAll(req)
  const name = req.replace(/\.\/(.*)\.vue/, '$1')
  // const name = module.name 使用此方式获取name,需要组件默认导出中含有name属性
  Vue.component(name, module)
})

文件目录:

image.png

注册局部组件

语法

let ComponentA = { /* ... */ } 
let ComponentB = { /* ... */ } 
let ComponentC = { /* ... */ }
new Vue({ 
    el: '#app', 
    components: { 
        'ComponentA': ComponentA, 
        'ComponentB': ComponentB 
    } 
 })

代码

const requireAll = require.context('../components', false, /\.vue$/)

const modules = {}

requireAll.keys().forEach(req => {
  const {default: module} = requireAll(req)
  modules[module.name] = module
})

export default modules

文件目录:

image.png

vuex中自动导入子模块

语法

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

代码

const requireAll = require.context('./modules', true, /\.js$/)
const modules = requireAll.keys().reduce((modules, req) => {
  const name = req.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = requireAll(req)
  modules[name] = value.default
  return modules
}, {})

文件目录:

image.png

SVG 的雪碧图

请参考文章: 手摸手,带你优雅的使用 icon

文末拓展

变量、常量与字面量

  • 字面量是指由字母、数字等构成的字符串或者数值,它只能作为右值出现(右值是指等号右边的值,如:let top = 10,这里的 top 为左值,10为右值)

  • 常量和变量都属于变量,只不过常量是赋过值后不能再更改的变量,而普通的变量可以再进行赋值操作

ES6 语法中属性的简写

ES6 中,当一个对象的属性名和本地变量同名时,不必再写冒号 : 和 值,简单的只写属性名即可:

// 简写前
let ComponentA = { /* ... */ } 
let ComponentB = { /* ... */ } 
let ComponentC = { /* ... */ }
new Vue({ 
    el: '#app', 
    components: { 
        'ComponentA': ComponentA, 
        'ComponentB': ComponentB 
    } 
 })
 
 // ES6 语法简写后
 let ComponentA = { /* ... */ } 
let ComponentB = { /* ... */ } 
let ComponentC = { /* ... */ }
new Vue({ 
    el: '#app', 
    components: { 
        ComponentA, 
        ComponentB
    } 
 })