require.context是什么
一個webpack的api,通過執行require.context函數獲取一個特定的上下文,主要用來實現自動化導入模塊,在前端工程中,如果遇到從一個文件夾引入很多模塊的情況,可以使用這個api,它會遍歷文件夾中的指定文件,然后自動導入,使得不需要每次顯式的調用import導入模塊
什么時候需要用到require.context
如果有以下情況,可以考慮使用require.context替換

index.js

modules
在Vue寫的項目中,我把路由通過不同的功能划分成不同的模塊,在index.js中一個個導入(原諒ide的警告-.-),但是如果項目變大了之后,每次手動import會顯得有些力不從心,這里可以使用require.context函數遍歷modules文件夾的所有文件一次性導入到index.js中
分析require.context
require.context函數接受三個參數
- directory {String} -讀取文件的路徑
- useSubdirectories {Boolean} -是否遍歷文件的子目錄
- regExp {RegExp} -匹配文件的正則
語法: require.context(directory, useSubdirectories = false, regExp = /^.//);
借用webpakc官網的例子
require.context('./test', false, /.test.js$/);
上面的代碼遍歷當前目錄下的test文件夾的所有.test.js結尾的文件,不遍歷子目錄
大概用圖片來表示的話就是這樣子的

在index.js中調用 require.context('./test', false, /.test.js$/);會得到test文件下3個文件的執行環境
值得注意的是require.context函數執行后返回的是一個函數,並且這個函數有3個屬性
- resolve {Function} -接受一個參數request,request為test文件夾下面匹配文件的相對路徑,返回這個匹配文件相對於整個工程的相對路徑
- keys {Function} -返回匹配成功模塊的名字組成的數組
- id {String} -執行環境的id,返回的是一個字符串,主要用在module.hot.accept,應該是熱加載?
這三個都是作為函數的屬性(注意是作為函數的屬性,函數也是對象,有對應的屬性)
talk is cheap ,show me the code
結合工程看一下這3個屬性返回了什么
我們在里層的modules文件夾新建一個index.js,用來收集所有的模塊然后一次性導出給外層的index.js

這里我們先上代碼,代碼是寫在里層的index.js中的(代碼借鑒於加快Vue項目的開發速度)

這里我把require.context函數執行后的代碼賦值給了files變量,files中保存了圖一的以.js結尾的文件,files是個函數,我們分別調用者3個屬性看看會返回什么


控制台打印結果
可以看到
執行了keys方法返回了一個由匹配文件的文件名組成的數組 id屬性返回了匹配的文件夾的相對於工程的相對路徑,是否遍歷子目錄,匹配正則組成的字符串
對於resolve方法可以看到它是一個函數接受req參數,經過實踐我發現這個req參數的值是keys方法返回的數組的元素,接着我們傳入其中一個元素執行resolve函數


resolve方法返回了一個字符串代表着傳入參數的文件相對於整個工程的相對路徑
同時files作為一個函數,也接受一個req參數,這個和resolve方法的req參數是一樣的,即匹配的文件名的相對路徑,而files函數返回的是一個模塊,這個模塊才是真正我們需要的


這個Module模塊和使用import導入的模塊是一樣的
回到工程
- 首先調用require.context導入某個文件夾的所有匹配文件,返回執行上下文的環境賦值給files變量
- 聲明一個configRouters用來暴露給外層index.js作為vue-router的數組
- 調用files函數的keys方法返回modules文件夾下所有以.js結尾的文件的文件名,返回文件名組成的數組
- 遍歷數組每一項,如果是index.js就跳過(index.js並不是路由模塊),調用files函數傳入遍歷的元素返回一個Modules模塊
- 因為我的路徑是用export default導出的,所以在Module模塊的default屬性中獲取到我導出的內容(即路由的結構),類似這種樣子

- 將上一步返回的所有路由結構添加到configRouters數組然后暴露給外層的index.js

外層index.js
- 外層引入后導入到vue-router中就可以使用了
寫在后面
在使用require.context自動導入路由文件時發現一個問題,路由的順序不是你期望的樣子,因為webpack是根據你文件夾中文件的位置排序的,這個時候需要定義一個標識符來給路由數組排序,這里我們給每個文件夾最上層的路由添加一個sort屬性用於排序

隨后在讀取模塊后,給外層index傳入路由配置前,給路由的模塊排序

require.context另外一個常用的地方是svg圖標,可以不用每次導入圖標文件,相對於以前的iconfont,svg。
作者:心_c2a2
轉發鏈接:https://www.jianshu.com/p/c894ea00dfec
喜歡這篇文章?歡迎打賞~~