webpack中require.context的使用

概述

You can create your own context with the require.context() function.javascript

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.html

webpack parses for require.context() in the code while building.vue

webpack文檔 - require.contextjava

require.context是webpack中,用來建立本身的(模塊)上下文;
webpack會在代碼構建的時候去解析該函數

解析

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

該方法有3個參數:react

  1. 須要搜索的文件夾目錄(必傳)
  2. 是否須要搜索它的子孫目錄,默認爲false
  3. 匹配文件名的正則表達式

例子

// 示例
const test = require.context('./string', false, /\.js$/);

個人目錄結構以下:webpack

  • Stringweb

    • trim.js
    • trimLeft.js
    • trimRight.js
    • test正則表達式

      • test1.js
    • *

這時候若是console.log(test),就會發現調用require.context以後返回的是一個函數express

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

此次若是還須要深刻就須要去webpack打包以後的文件中尋找了:react-router

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中的基礎組件的自動化全局註冊

具體就很少說了,直接看文檔
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;

參考

  1. 分享:使用 webpack 的 require.context 實現路由「去中心化」管理
  2. webpack 之 require.context 用法
  3. vue的基礎組件的自動化全局註冊
  4. webpack官方文檔 - require-context
相關文章
相關標籤/搜索