正值前端組件化開發時代,那麼必然離不開目前最火的構建工具——webpack(grunt,gulp等暫且不談)。說到這裡,剛好有幾個問題: 為什麼運行打包命令之後, 文件可以轉成 文件 為什麼運行打包命令之後, 文件可以轉成 文件 為什麼運行打包命令之後, 語法可以轉成 語法 "[外鏈圖片轉存失敗,源 ...
正值前端組件化開發時代,那麼必然離不開目前最火的構建工具——webpack(grunt,gulp等暫且不談)。說到這裡,剛好有幾個問題:
- 為什麼運行打包命令之後,
.vue
文件可以轉成.js
文件 - 為什麼運行打包命令之後,
.less
文件可以轉成.css
文件 為什麼運行打包命令之後,
ES6+
語法可以轉成ES5
語法
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mr86zPPH-1570953160209)(https://img.shields.io/npm/v/vue-hash-calendar.svg)]上面這幾個問題,就引出了我們的主角——【loader】。
loader
是webpack
的一塊很重要的組成部分。我們都知道webpack
是用於資源打包的,裡面的所有資源都是“模塊”,內部實現了對模塊資源進行載入的機制。但是Webpack
本身只能處理js
模塊,如果要處理其他類型的文件,就需要使用loader
進行轉換。Loader
可以理解為是模塊和資源的轉換器,它本身是一個函數,接收文件源碼作為參數,返迴轉換的結果,例如可以使用loader
載入器可以快速編譯預處理器(less,sass,coffeeScript)
。Loader
可以在require()
引用模塊的時候添加,也可以在webpack
全局配置中進行綁定,還可以通過命令行的方式使用。(本篇中的參數配置及使用方式均基於webpack4.0
版本)
一、loader的特點
1、loader
的執行順序和代碼書寫的順序是相反的,即:從下至上,從右至左。
2、第一個執行的 loader
會接收源文件做為參數,下一次執行的 loader
會接收前一個 loader
執行的返回值做為參數
3、需要嚴格遵循“單一職責”原則,即每個 loader
只負責自己需要負責的事情
二、loader API
methods | 含義 |
---|---|
this.request | 被解析出來的 request 字元串。例子:"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr" |
this.loaders | 所有 loader 組成的數組。它在 pitch 階段的時候是可以寫入的。 |
this.loaderIndex | 當前 loader 在 loader 數組中的索引。 |
this.async | 告訴 loader-runner 這個 loader 將會非同步地回調 |
this.callback | 一個可以同步或者非同步調用的可以返回多個結果的函數 |
this.data | 在 pitch 階段和正常階段之間共用的 data 對象。 |
this.cacheable | 設置是否可緩存標誌的函數 |
this.resource | request 中的資源部分,包括 query 參數 |
this.resourcePath | 資源文件的路徑。 |
this.resourceQuery | 資源的 query 參數 |
this.target | 編譯的目標。從配置選項中傳遞過來的。 |
this.webpack | 如果是由 webpack 編譯的,這個布爾值會被設置為真 |
this.sourceMap | 應該生成一個 source map。因為生成 source map 可能會非常耗時,你應該確認 source map 確實有必要請求。 |
this.emitWarning | 發出一個警告。 |
this.emitError | 發出一個錯誤。 |
this.loadModule | 解析給定的 request 到一個模塊,應用所有配置的 loader ,並且在回調函數中傳入生成的 source 、sourceMap 和 模塊實例(通常是 NormalModule 的一個實例)。如果你需要獲取其他模塊的源代碼來生成結果的話,你可以使用這個函數。 |
this.resolve | 像 require 表達式一樣解析一個 request 。 |
this.emitFile | 產生一個文件。這是 webpack 特有的。 |
this.fs | 用於訪問 compilation 的 inputFileSystem 屬性。 |
this.value | 向下一個 loader 傳值。如果你知道了作為模塊執行後的結果,請在這裡賦值(以單元素數組的形式)。 |
this.inputValue | 從上一個 loader 那裡傳遞過來的值。如果你會以模塊的方式處理輸入參數,建議預先讀入這個變數(為了性能因素)。 |
更多詳細API,以及各API的用法示例,可以訪問官網查看。地址:https://www.webpackjs.com/api/loaders
三、寫loader之前的需求整理
現在有這樣一個需求,使用 hxkj-loader
載入並處理名稱為 *.hxkj.vip
的文件,將裡面的哈希空間
全部替換為 www.hxkj.vip
。需要實現的轉換如下:
轉換前的內容:
<div>
<h1>歡迎訪問哈希空間</h1>
<p>哎喲,終於等到你。這裡就是讓人流連忘返的哈希空間呀!</p>
</div>
轉換後的內容:
<div>
<h1>歡迎訪問www.hxkj.vip</h1>
<p>哎喲,終於等到你。這裡就是讓人流連忘返的www.hxkj.vip呀!</p>
</div>
四、編寫loader
在與 webpack.config.js
同級目錄下新建 hxkj-loader.js
,文件的內容如下:
module.exports = function(source){
var content="";
content = source.replace("/哈希空間/g","www.hxkj.vip");
return content;
}
接下來,需要在 webpack.config.js
文件中增加以下的配置:
const path = require("path"); // 引入 node 的 path 模塊
...
module:{
rules:[{
test: /\.hxkj\.vip$/, // 正則匹配以 hxkj.vip 結尾的文件
use:[{
loader:path.resolve(__dirname, "hxkj-loader") // 使用 path 模塊找到 hxkj-loader 的路徑
}]
}]
}
好,到此,一個簡易版的 loader
就已經寫完了。目前 loader
是直接寫在本地的,可以考慮將自己寫好的 loader
發佈到 npm
,這樣就更加完善了。
At last,看完之後有什麼不懂的,可以留言反饋。
轉載請註明出處:https://www.jianshu.com/p/51b793f6fa0e
作者:TSY
個人空間:https://hxkj.vip