一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - 編程技術 - Webpack - 手把手教你寫一個 loader / plugin

Webpack - 手把手教你寫一個 loader / plugin

2021-06-22 23:41微醫大前端技術焦傳鍇 編程技術

webpack 只能理解 JavaScript 和 JSON 文件,這是 webpack 開箱可用的自帶能力。**loader **讓 webpack 能夠去處理其他類型的文件,并將它們轉換為有效模塊,以供應用程序使用,以及被添加到依賴圖中。

Webpack - 手把手教你寫一個 loader / plugin

一、Loader

 

1.1 loader 干啥的?

webpack 只能理解 JavaScript 和 JSON 文件,這是 webpack 開箱可用的自帶能力。**loader **讓 webpack 能夠去處理其他類型的文件,并將它們轉換為有效模塊,以供應用程序使用,以及被添加到依賴圖中。

也就是說,webpack 把任何文件都看做模塊,loader 能 import 任何類型的模塊,但是 webpack 原生不支持譬如 css 文件等的解析,這時候就需要用到我們的 loader 機制了。 我們的 loader 主要通過兩個屬性來讓我們的 webpack 進行聯動識別:

  1. test 屬性,識別出哪些文件會被轉換。
  2. use 屬性,定義出在進行轉換時,應該使用哪個 loader。

那么問題來了,大家一定想知道自己要定制一個 loader 的話需要怎么做呢?

1.2 開發準則

俗話說的好,沒有規矩不成方圓,編寫我們的 loader 時,官方也給了我們一套用法準則(Guidelines),在編寫的時候應該按照這套準則來使我們的 loader 標準化:

  • 簡單易用。
  • 使用鏈式傳遞。(由于 loader 是可以被鏈式調用的,所以請保證每一個 loader 的單一職責)
  • 模塊化的輸出。
  • 確保無狀態。(不要讓 loader 的轉化中保留之前的狀態,每次運行都應該獨立于其他編譯模塊以及相同模塊之前的編譯結果)
  • 充分使用官方提供的 loader utilities。
  • 記錄 loader 的依賴。
  • 解析模塊依賴關系。

根據模塊類型,可能會有不同的模式指定依賴關系。例如在 CSS 中,使用@import 和 url(...)語句來聲明依賴。這些依賴關系應該由模塊系統解析。 可以通過以下兩種方式中的一種來實現:

  • 通過把它們轉化成 require 語句。
  • 使用 this.resolve 函數解析路徑。
  • 提取通用代碼。
  • 避免絕對路徑。
  • 使用 peer dependencies。如果你的 loader 簡單包裹另外一個包,你應該把這個包作為一個 peerDependency 引入。

1.3 上手

一個 loader 就是一個 nodejs 模塊,他導出的是一個函數,這個函數只有一個入參,這個參數就是一個包含資源文件內容的字符串,而函數的返回值就是處理后的內容。也就是說,一個最簡單的 loader 長這樣:

  1. module.exports = function (content) { 
  2.  // content 就是傳入的源內容字符串 
  3.   return content 

當一個 loader 被使用的時候,他只可以接收一個入參,這個參數是一個包含包含資源文件內容的字符串。 是的,到這里為止,一個最簡單 loader 就已經完成了!接下來我們來看看怎么給他加上豐富的功能。

1.4 四種 loader

我們基本可以把常見的 loader 分為四種:

  • 同步 loader
  • 異步 loader
  • "Raw" Loader
  • Pitching loader

① 同步 loader 與 異步 loader

一般的 loader 轉換都是同步的,我們可以采用上面說的直接 return 結果的方式,返回我們的處理結果:

  1. module.exports = function (content) { 
  2.  // 對 content 進行一些處理 
  3.   const res = dosth(content) 
  4.   return res 

也可以直接使用 this.callback() 這個 api,然后在最后直接 **return undefined **的方式告訴 webpack 去 this.callback() 尋找他要的結果,這個 api 接受這些參數:

  1. this.callback( 
  2.   err: Error | null, // 一個無法正常編譯時的 Error 或者 直接給個 null 
  3.   content: string | Buffer,// 我們處理后返回的內容 可以是 string 或者 Buffer() 
  4.   sourceMap?: SourceMap, // 可選 可以是一個被正常解析的 source map 
  5.   meta?: any // 可選 可以是任何東西,比如一個公用的 AST 語法樹 
  6. ); 

接下來舉個例子:

Webpack - 手把手教你寫一個 loader / plugin

這里注意[this.getOptions()](https://webpack.docschina.org/api/loaders/#thisgetoptionsschema) 可以用來獲取配置的參數

從 webpack 5 開始,this.getOptions 可以獲取到 loader 上下文對象。它用來替代來自loader-utils中的 getOptions 方法。

  1. module.exports = function (content) { 
  2.   // 獲取到用戶傳給當前 loader 的參數 
  3.   const options = this.getOptions() 
  4.   const res = someSyncOperation(content, options) 
  5.   this.callback(null, res, sourceMaps); 
  6.   // 注意這里由于使用了 this.callback 直接 return 就行 
  7.   return 

這樣一個同步的 loader 就完成了!

再來說說異步: 同步與異步的區別很好理解,一般我們的轉換流程都是同步的,但是當我們遇到譬如需要網絡請求等場景,那么為了避免阻塞構建步驟,我們會采取異步構建的方式,對于異步 loader 我們主要需要使用 this.async() 來告知 webpack 這次構建操作是異步的,不多廢話,看代碼就懂了:

  1. module.exports = function (content) { 
  2.   var callback = this.async() 
  3.   someAsyncOperation(content, function (err, result) { 
  4.     if (err) return callback(err) 
  5.     callback(null, result, sourceMaps, meta) 
  6.   }) 

② "Raw" loader

默認情況下,資源文件會被轉化為 UTF-8 字符串,然后傳給 loader。通過設置 raw 為 true,loader 可以接收原始的 Buffer。每一個 loader 都可以用 String 或者 Buffer 的形式傳遞它的處理結果。complier 將會把它們在 loader 之間相互轉換。大家熟悉的 file-loader 就是用了這個。簡而言之:你加上 module.exports.raw = true; 傳給你的就是 Buffer 了,處理返回的類型也并非一定要是 Buffer,webpack 并沒有限制。

  1. module.exports = function (content) { 
  2.   console.log(content instanceof Buffer); // true 
  3.   return doSomeOperation(content) 
  4. // 劃重點↓ 
  5. module.exports.raw = true

③ Pitching loader

我們每一個 loader 都可以有一個 pitch 方法,大家都知道,loader 是按照從右往左的順序被調用的,但是實際上,在此之前會有一個按照從左往右執行每一個 loader 的 pitch 方法的過程。pitch 方法共有三個參數:

  • remainingRequest:loader 鏈中排在自己后面的 loader 以及資源文件的絕對路徑以!作為連接符組成的字符串。
  • precedingRequest:loader 鏈中排在自己前面的 loader 的絕對路徑以!作為連接符組成的字符串。
  • data:每個 loader 中存放在上下文中的固定字段,可用于 pitch 給 loader 傳遞數據。

在 pitch 中傳給 data 的數據,在后續的調用執行階段,是可以在 this.data 中獲取到的:

  1. module.exports = function (content) { 
  2.   return someSyncOperation(content, this.data.value);// 這里的 this.data.value === 42 
  3. }; 
  4.  
  5. module.exports.pitch = function (remainingRequest, precedingRequest, data) { 
  6.   data.value = 42; 
  7. }; 

注意! 如果某一個 loader 的 pitch 方法中返回了值,那么他會直接“往回走”,跳過后續的步驟,來舉個例子:

Webpack - 手把手教你寫一個 loader / plugin

假設我們現在是這樣:use: ['a-loader', 'b-loader', 'c-loader'],那么正常的調用順序是這樣:

Webpack - 手把手教你寫一個 loader / plugin

現在 b-loader 的 pitch 改為了有返回值:

  1. // b-loader.js 
  2. module.exports = function (content) { 
  3.   return someSyncOperation(content); 
  4. }; 
  5.  
  6. module.exports.pitch = function (remainingRequest, precedingRequest, data) { 
  7.   return "誒,我直接返回,就是玩兒~" 
  8. }; 

那么現在的調用就會變成這樣,直接“回頭”,跳過了原來的其他三個步驟:

Webpack - 手把手教你寫一個 loader / plugin

1.5 其他 API

  • this.addDependency:加入一個文件進行監聽,一旦文件產生變化就會重新調用這個 loader 進行處理
  • this.cacheable:默認情況下 loader 的處理結果會有緩存效果,給這個方法傳入 false 可以關閉這個效果
  • this.clearDependencies:清除 loader 的所有依賴
  • this.context:文件所在的目錄(不包含文件名)
  • this.data:pitch 階段和正常調用階段共享的對象
  • this.getOptions(schema):用來獲取配置的 loader 參數選項
  • this.resolve:像 require 表達式一樣解析一個 request。resolve(context: string, request: string, callback: function(err, result: string))
  • this.loaders:所有 loader 組成的數組。它在 pitch 階段的時候是可以寫入的。
  • this.resource:獲取當前請求路徑,包含參數:'/abc/resource.js?rrr'
  • this.resourcePath:不包含參數的路徑:'/abc/resource.js'
  • this.sourceMap:bool 類型,是否應該生成一個 sourceMap

官方還提供了很多實用 Api ,這邊只列舉一些可能常用的,更多可以戳鏈接

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲人成在线播放 | 亚洲国产精品婷婷久久久久 | 免费理伦片在线观看全网站 | 天天色视频 | 亚欧有色在线观看免费版高清 | 午夜精品在线视频 | 国产特级 | a黄色 | 精品久久免费视频 | 美日毛片 | 亚洲黄色免费在线观看 | 国产剧情麻豆刘玥视频 | 91麻豆国产福利在线观看 | 国产精品久久久久久久久免费 | 91九色麻豆 | 亚洲日本中文字幕天堂网 | 美女下面揉出水免费视频 | 美女用手扒自己下部 | 国产一区风间由美在线观看 | 日本伦理动漫在线观看 | 99日影院在线播放 | 国产美女亚洲精品久久久久久 | 我将她侵犯1~6樱花动漫在线看 | 日韩伦理在线看 | 久久久久久久久人体 | 韩国漂亮美女三级在线观看 | 亚洲黄色高清 | 高h生子双性美人受 | 免费看日产一区二区三区 | 欧美精品一线二线大片 | 成人综合网站 | 女人叉开腿让男人捅 | 色老板视频在线观看 | 男人猛进女人屁股免费 | 被黑人日 | 国产精品视频在这里有精品 | 美女奶口隐私免费视频网站 | 日韩在线 在线播放 | 亚洲欧洲淘宝天堂日本 | 青草视频网站 | 日本高清va不卡视频在线观看 |