1. 程式人生 > 其它 >webpack中require.context的作用

webpack中require.context的作用

在我們專案開發中,經常需要import或者export各種模組,那麼有沒有什麼辦法可以簡化這種引入或者匯出操作呢?答案是肯定的,下面就為大家介紹一下require.context

我們會這樣引入元件:

import A from 'components/A'
import B from 'components/B'
import C from 'components/C'
import D from 'components/D'
// ...

這樣很蛋疼,因為每加一個元件,可能都要寫這麼一句,這樣有規律的事,是否可以通過自動化完成?

看下Webpack [Dependency Management | webpack

]

require.context

require.context(directory, useSubdirectories, regExp)
  1. directory: 要查詢的檔案路徑
  2. useSubdirectories: 是否查詢子目錄
  3. regExp: 要匹配檔案的正則

用法

require.context('./components/', true, /\.js$/)

目錄結構

上面呼叫方法,到底返回的是什麼?

var map = {
	"./A.js": "./src/components/test/components/A.js",
	"./B.js": "./src/components/test/components/B.js",
	"./C.js": "./src/components/test/components/C.js",
	"./D.js": "./src/components/test/components/D.js"
};


function webpackContext(req) {
	var id = webpackContextResolve(req);
	return __webpack_require__(id);
}
function webpackContextResolve(req) {
	var id = map[req];
	if(!(id + 1)) { // check for number or string
		var e = new Error("Cannot find module '" + req + "'");
		e.code = 'MODULE_NOT_FOUND';
		throw e;
	}
	return id;
}
webpackContext.keys = function webpackContextKeys() {
	return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
module.exports = webpackContext;
webpackContext.id = "./src/components/test/components sync recursive \\.js$";

程式碼很簡單,require.context執行後,返回一個方法webpackContext,這個方法又返回一個__webpack_require__,這個__webpack_require__就相當於require或者import。同時webpackContext還有二個靜態方法keys與resolve,一個id屬性。

  1. keys: 返回匹配成功模組的名字組成的陣列
  2. resolve: 接受一個引數request,request為test資料夾下面匹配檔案的相對路徑,返回這個匹配檔案相對於整個工程的相對路徑
  3. id: 執行環境的id,返回的是一個字串,主要用在module.hot.accept,應該是熱載入

看下keys是作用

const ctx = require.context('./components/', true, /\.js$/)
console.log(ctx.keys())
// ["./A.js", "./B.js", "./C.js", "./D.js"]

其實就是

var map = {
	"./A.js": "./src/components/test/components/A.js",
	"./B.js": "./src/components/test/components/B.js",
	"./C.js": "./src/components/test/components/C.js",
	"./D.js": "./src/components/test/components/D.js"
};

Object.keys(map)

只不過map是模組內部變數,無法直接訪問,所以通過其實提供的keys方法訪問

那麼如何引入ABCD元件呢?

const ctx = require.context('./components/', true, /\.js$/)
const map = {}
for (const key of ctx.keys()) {
  map[key] = ctx(key)
}
console.log(map)

看到了吧!成功import進來了,但'./A.js'這樣的key有點不太好,自己可以處理字串生成自己想要的key

可以優化一下,生成一個公共的方法

const importAll = context => {
  const map = {}

  for (const key of context.keys()) {
    const keyArr = key.split('/')
    keyArr.shift() // 移除.
    map[keyArr.join('.').replace(/\.js$/g, '')] = context(key)
  }

  return map
}

export default importAll

使用

import importAll from '$common/importAll'
export default importAll(require.context('./', true, /\.js$/))