webpack中require.context的使用
阿新 • • 發佈:2019-02-04
概述
You can create your own context with the require.context() function.
It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched too, and a regular expression to match files against.
webpack parses for require.context() in the code while building.
require.context是webpack中,用來建立自己的(模組)上下文;
webpack會在程式碼構建的時候去解析該函式
解析
require.context(directory, useSubdirectories = false, regExp = /^\.\//);
該方法有3個引數:
- 需要搜尋的資料夾目錄(必傳)
- 是否需要搜尋它的子孫目錄,預設為false
- 匹配檔名的正則表示式
例子
// 示例
const test = require.context('./string', false, /\.js$/);
我的目錄結構如下:
-
String
- trim.js
- trimLeft.js
- trimRight.js
-
test
- test1.js
- *
這時候如果console.log(test)
,就會發現呼叫require.context之後返回的是一個函式
webpackContext(req) {
var id = webpackContextResolve(req);
return __webpack_require__(id);
}
這次如果還需要深入就需要去webpack打包之後的檔案中尋找了:
var map = { "./test/test1.js": "./src/string/test/test1.js", "./trim.js": "./src/string/trim.js", "./trimLeft.js": "./src/string/trimLeft.js", "./trimRight.js": "./src/string/trimRight.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/string sync recursive \\.js$";
由上面的程式碼可以看出,在webpackContext
定義了多個方法和屬性
console.log(webpackContext.id) // "./src/string sync recursive \.js$"
console.log(webpackContext('./trim.js')) // "./src/string/trim.js"
console.log(webpackContext.keys()) // ["./test/test1.js", "./trim.js", "./trimLeft.js", "./trimRight.js"]
使用場景
vue中的基礎元件的自動化全域性註冊
大型單頁應用中,路由過多
當你的單頁應用變成了大型應用後,路由也在慢慢的增多
// rootRoute.js
const rootRoute = {
childRoutes: [
{
path: "/",
component: AppLayout,
childRoutes: [
{
path: "shop", // 購買詳情頁
component: ShopLayout,
childRoutes: [
{
path: "foodDetail",
component: FoodDetail
},
{
path: "shoesDetail",
component: ShoesDetail
}
// 其他
]
},
{
path: "order", // 訂單頁
component: Order,
childRoutes: [
{
path: "remark", //訂單備註
component: Remark
},
{
path: "invoice", //發票擡頭
component: Invoice
},
{
path: "payment", //付款頁面
component: Payment
},
{
path: "userValidation", //使用者驗證
component: UserValidation
},
{
path: "chooseAddress", //選擇地址
component: ChooseAddress,
childRoutes: [
{
path: "addAddress", //新增地址
component: AddAddress,
childRoutes: [
{
path: "searchAddress", //搜尋地址
component: SearchAddress
}
]
}
]
}
]
}
// ...
// 大量新增路由
// ...
]
}
]
};
當路由變的越來越大,大到已經難以維護時。我們按照react-router
提供的思路,對路由按業務模組進行拆分。
// rootRoute.js
const rootRoute = {
childRoutes: [
{
path: '/',
component: AppLayout,
childRoutes: [
require('./modules/shop/route'), //購買詳情頁
require('./modules/order/route'), // 訂單頁
require('./modules/login/route'), // 登入註冊頁
require('./modules/service/route'), // 服務中心
// ...
// 其他大量新增路由
// ...
]
}
]
};
再進一步優化的話,就可以使用require.context
const rootRoute = {
childRoutes: [
{
path: '/',
component: AppLayout,
childRoutes: (r => {
return r.keys().map(key => r(key));
})(require.context('./', true, /^\.\/modules\/((?!\/)[\s\S])+\/route\.js$/))
}
]
};
自動引用目錄下的檔案
比如我現在想要造一個自己的工具庫utils,那麼隨著工具函式數量的增加,勢必需要將程式碼分割得更小,甚至細化到一個工具函式對應一個js檔案。
這時如果還需要在入口js檔案中一個個手動引用,那麼每增加一個js檔案,就需要重新去修改入口js一次,工程量是非常大的。
這時就可以使用到require.context
了~
/**
* @desc webpack打包入口檔案
* @example 自動引入子目錄下所有js檔案
*/
let moduleExports = {};
const r = require.context('./', true, /^\.\/.+\/.+\.js$/);
r.keys().forEach(key => {
let attr = key.substring(key.lastIndexOf('/') + 1, key.lastIndexOf('.'));
moduleExports[attr] = r(key);
});
module.exports = moduleExports;