webpack - 自定義loader


自定義loader基本方法,節選自 webpack實戰。

 

1、loader初始化

如果已知loader無法滿足我們的需求的時候,就需要動手開發一個定制的loader,我們將實現一個loader:它會為所有的JS文件啟用嚴格模式,也就是說它會在文件頭部加上如下代碼:

"use strict";
  1. 創建一個force-strict-loader目錄,然后在該目錄下執行npm初始化命令。npm init -y
  2. 創建index.js,也就是loader的主體
    module.exports = function(content){
      var useStrictPrefix = '\'use strict\'; \n\n';
      return useStrictPrefix + content;   
    }

    現在我們可以在webpack工程中安裝並使用這個loader了

  3. npm install <path-to-loader>/force-strict-loader;在webpack工程目錄下使用相對路徑安裝,會在項目的node_modules中創建一個指向實際force-strict-loader目錄的軟鏈,也就是說之后我們可以隨時修改loader源碼並且不需要重復安裝了
  4. 修改webpack配置
    module: {
      rules:[
        {
            test: /\.js$/,
            use: 'force-strict-loader'  
        }  
      ]  
    }

    我們將這個loader設置為對所有js文件生效,此時對該工程進行打包,應該可以看到js文件的頭部都已經加上了啟用嚴格模式的語句。

 

2、啟用緩存

  當文件輸入和其依賴沒有發生變化時,應該讓loader直接使用緩存。在webpack中可以使用this.cacheable進行控制,修改我們的loader。

//force-strict-laoder/index.js
module.exports = function(content){
    if(this.cacheable){
        this.cacheable();
    }
    var useStrictPrefix = '\'use strict\';\n\n';
    return useStrictPrefix + content;  
}

      通過啟用緩存可以加快webpack的打包速度,並且可保證相同的輸入產生相同的輸出。

 

3、獲取options

    loader的配置項通過use.options傳進來,如:

{
            test: /\.js$/,
            use: [
                
                {
                    loader: 'force-strict-loader',
                    options: {
                        sourceMap: true
                    }
                },
            ],
        }

    下面我們在loader中獲取它

    需要先安裝一個依賴庫 "loader-utils" 

// force-strict-laoder/index.js
var
loaderUtils = require('loader-utils'); module.exports = (content) => { if(this.cacheable){ this.cacheable(); } // 獲取和打印 options var options = loaderUtils.getOptions(this) || {} console.log('options', options); //處理content var useStrictPrefix = '\'use strict\'\n\n'; return useStrictPrefix + content; }

    通過loaderUtils.getOptions可以獲取到配置對象,這里我們只是把它打印了出來。

 

4、實現Soure-Map

  source-map可以便於實際開發者在瀏覽器控制台查看源碼。如果沒有對source-map進行處理,最終也就無法生成正確的map文件,在瀏覽器的dev tool中可能就會看到錯訊的源碼。

下面是支持了source-map特性后的版本:

var loaderUtils = require('loader-utils');
var SourceNode = require('source-map').SourceNode;
var SourceMapConsumer = require('source-map').SourceMapConsumer;
module.exports = (content, sourceMap) => {
    var useStrictPrefix = '\'use strict\'\n\n';
    if(this.cacheable){
        this.cacheable();
    }
    
    // 獲取和打印 options
    var options = loaderUtils.getOptions(this) || {}
    console.log('options', options);
    // source-map
    if(options.sourceMap && sourceMap){
        var currentRequest = loaderUtils.getCurrentRequest(this);
        var node = SourceNode.fromStringWithSourceMap(content, new SourceMapConsumer);
    }
    node.prepend(useStrictPrefix);
    var result = node.toStringWithSourceMap({
        file: currentRequest
    });
    var callback = this.async();
    callback(null, result.code, result.map.toJSON());
    
    //不支持source-map情況
    return useStrictPrefix + content;
}

首先,在loader函數的參數中我們獲取到sourceMap對象,這是由webpack或者上一個loader傳遞下來的,只有當它存在時我們的loader才能進行繼續處理和向下傳遞。

之后,我們通過source-map這個庫來對map進行操作,包括接收和消費之前的文件內容和source-map,對內容節點進行修改,最后產生新的source-map。

在函數返回的時候要使用this.async獲取callback函數(主要是為了一次性返回多個值)。callback函數的3個參數分別是拋出的錯誤、處理后的源碼、以后source-map。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM