關於webpack的require.context

yeyan1996發表於2018-12-12

隨便記錄一些東西,如有錯誤歡迎指出

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函式接受三個引數

  1. directory {String} -讀取檔案的路徑

  2. useSubdirectories {Boolean} -是否遍歷檔案的子目錄

  3. regExp {RegExp} -匹配檔案的正則

語法: require.context(directory, useSubdirectories = false, regExp = /^.//);

借用webpakc官網的例子

require.context('./test', false, /.test.js$/);

上面的程式碼遍歷當前目錄下的test資料夾的所有.test.js結尾的檔案,不遍歷子目錄

大概用圖片來表示的話就是這樣子的

關於webpack的require.context

在index.js中呼叫require.context('./test',false,/.test.js)會得到test檔案下3個檔案的執行環境

值得注意的是require.context函式執行後返回的是一個函式,並且這個函式有3個屬性

  1. resolve {Function} -接受一個引數request,request為test資料夾下面匹配檔案的相對路徑,返回這個匹配檔案相對於整個工程的相對路徑

  2. keys {Function} -返回匹配成功模組的名字組成的陣列

  3. id {String} -執行環境的id,返回的是一個字串,主要用在module.hot.accept,應該是熱載入?

這三個都是作為函式的屬性(注意是作為函式的屬性,函式也是物件,有對應的屬性)

talk is cheap ,show me the code

結合工程看一下這3個屬性返回了什麼

我們在裡層的modules資料夾新建一個index.js,用來收集所有的模組然後一次性匯出給外層的index.js

關於webpack的require.context

這裡我們先上程式碼,程式碼是寫在裡層的index.js中的(程式碼借鑑於加快Vue專案的開發速度)

關於webpack的require.context

這裡我把require.context函式執行後的程式碼賦值給了files變數,files中儲存了圖一的以.js結尾的檔案,files是個函式,我們分別呼叫者3個屬性看看會返回什麼

關於webpack的require.context

控制檯列印結果

可以看到

執行了keys方法返回了一個由匹配檔案的檔名組成的陣列 id屬性返回了匹配的資料夾的相對於工程的相對路徑,是否遍歷子目錄,匹配正則組成的字串

對於resolve方法可以看到它是一個函式接受req引數,經過實踐我發現這個req引數的值是keys方法返回的陣列的元素,接著我們傳入其中一個元素執行resolve函式

關於webpack的require.context

關於webpack的require.context

resolve方法返回了一個字串代表著傳入引數的檔案相對於整個工程的相對路徑

同時files作為一個函式,也接受一個req引數,這個和resolve方法的req引數是一樣的,即匹配的檔名的相對路徑,而files函式返回的是一個模組,這個模組才是真正我們需要的

關於webpack的require.context

關於webpack的require.context

這個Module模組和使用import匯入的模組是一樣的

回到工程

  • 首先呼叫require.context匯入某個資料夾的所有匹配檔案,返回執行上下文的環境賦值給files變數

  • 宣告一個configRouters用來暴露給外層index.js作為vue-router的陣列

  • 呼叫files函式的keys方法返回modules資料夾下所有以.js結尾的檔案的檔名,返回檔名組成的陣列

  • 遍歷陣列每一項,如果是index.js就跳過(index.js並不是路由模組),呼叫files函式傳入遍歷的元素返回一個Modules模組

  • 因為我的路徑是用export default匯出的,所以在Module模組的default屬性中獲取到我匯出的內容(即路由的結構),類似這種樣子

關於webpack的require.context

  • 將上一步返回的所有路由結構新增到configRouters陣列然後暴露給外層的index.js

外層index.js

  • 外層引入後匯入到vue-router中就可以使用了

寫在後面

  • 在使用require.context自動匯入路由檔案時發現一個問題,路由的順序不是你期望的樣子,因為webpack是根據你資料夾中檔案的位置排序的,這個時候需要定義一個識別符號來給路由陣列排序,這裡我們給每個資料夾最上層的路由新增一個sort屬性用於排序

關於webpack的require.context

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

關於webpack的require.context

  • require.context另外一個常用的地方是svg圖示,可以不用每次匯入圖示檔案,相對於以前的iconfont,svg有很多好處強烈推薦,詳情可以看這個

手摸手,帶你優雅的使用 icon

相關文章