Webpack中的require.context妙用


require.context简介

require.context是Webpack中用来管理依赖的一个函数,它的参数如下:

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

使用方式如下所示:

// 创建一个test文件夹(不包含子目录)的上下文,可以require其下的所有js文件
const context = require.context("./test", false, /\.js$/)
const importAll = context => {
    // context.keys() 返回找到的js文件路径
    context.keys().forEach(key => context(key)
}
importAll()

实践 —- 自动注册Vue组件

利用Vue开发时,我们常会抽离出一些组件并将其放到components文件夹,然后在Vue中进行引用,例如:

<template>
    <search-input placeholder="搜索"></search-input>
    <dynamic-table></dynamic-table>
</template>
<script>
import SearchInput from '../components/SearchInput'
import DynamicTable from '../components/DynamicTable'
export default {
    name: 'App',
    components: {
        SearchInput,
        DynamicTable
    }
}
</script>

这是一种很好的代码复用方式,但是如果要引入的组件比较多时,一个一个引用会比较头疼,有没有一劳永逸的方法呢?有的,require.context可以上场了。 为了方便使用,我们可以写一个Vue插件

// plugins/component.js
export default {

    install(Vue){
        const context = require.context('../components', true, /\.vue/)
        context.keys().forEach(key => {
            const component = context(key).default
            Vue.component(component.name, component)
        })
    }
}

// app.js
import Vue from 'vue'
import globalComponents from './plugins/components'
Vue.use(globalComponents)

原理很简单,我们拿到组件后,通过Vue.component进行全局注册。这样注册后,我们可以在Vue中的template里面直接引入组件了。怎么样,是不是方便多啦?

实践 —- 简化Vuex开发

首先上一张Vuex的架构图

从架构图上可以看到,我们开发时,会有 actionmuations以及store三个部分,开发时,我们会将这三个部分进行拆开,会有如下的文件夹结构:

.
├── actions
│   ├── index.js
│   ├── overview.js
│   └── settings.js
├── mutations
│   ├── index.js
│   ├── overview.js
│   └── settings.js
└── store
    └── index.js

actions文件下的index.js用来引用其他js文件,例如

// actions/index.js

import overviewActions from './overview'
import settingsActions from './settings'
export default {
    ...overviewActions
    ...settingsActions
}

muations文件下的index.js用来引用其他js文件,例如:

// muations/index.js

import overview from './overview'
import settings from './settings'
export default {
    overview,
    settings
}

store文件夹下的index.js用来将actionmutation进行载入:

import Vue from "vue"
import Vuex from "vuex"
import actions from "../actions"
import mutations from "../mutations"

Vue.use(Vuex)

Vue.config.devtools = __DEV__

!__DEV__ && (Vue.config.errorHandler = function (err, vm) {
    vm.$store.dispatch("hidePageLoading")
    console.error(err.message)
})

export default new Vuex.Store({
    actions,
    modules: mutations,
    strict: false
})

这样代码结构很清晰,但是大家是否意识到,每次我们增加一个模块,都需修改actions以及mutations下的index.js, 很烦有没有?git提交时偶尔还发生冲突,很不爽哇!怎么解决?require.context来帮忙~~

我们现在删除actions以及mutations下的index.js文件,然后修改store/index.js

import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)

Vue.config.devtools = __DEV__

!__DEV__ && (Vue.config.errorHandler = function (err, vm) {
    vm.$store.dispatch("hidePageLoading")
    console.error(err.message)
});

// 自动引入actions下的js文件,将文件的各个对象合并为一个大对象
const actionContext = require.context('../actions', false, /.*\.js/)
const actions = actionContext
    .keys()
    .reduce((prev, cur) => ({ ...prev, ...actionContext(cur).default }), {})

// 自动引入mutation文件下的js文件,以文件名字作为对象的key
const mutationContext = require.context('../mutations', false, /.*\.js/)
const modules = mutationContext.keys().reduce((prev, cur) => {
    const key = cur.match(/(\w+)\.js/)[1]
    prev[key] = mutationContext(cur).default
    return prev
}, {})

export default new Vuex.Store({
    actions,
    modules,
    strict: false
})

这样处理后,我们以后增加一个模块,直接往actionsmuations下直接加js文件就好了,大家互不干扰,快乐协作!

总结

以上是我开发中总结的一些小技巧,希望对大家有所帮助:-)


文章作者: Asyncoder
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Asyncoder !
  目录