3.一步步瞭解 Webpack Loader 開發

這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰node

Webpack Loader

loader 用於對模塊的源代碼進行轉換webpack

配置

  • 單個 loader,你能夠簡單經過在 rule 對象設置 path.resolve 指向這個本地文件
  • 多個 loaders,你可使用 resolveLoader.modules 配置
  • 測試的時候可使用 npm link
  • 當鏈式調用多個 loader 的時候,請記住它們會以相反的順序執行。取決於數組寫法格式,從右向左或者從下向上執行
    • 最後的 loader 最先調用,將會傳入原始資源內容。
    • 第一個 loader 最後調用,指望值是傳出 JavaScript 和 source map(可選)。
    • 中間的 loader 執行時,會傳入前一個 loader 傳出的結果。

demo: 將 var 關鍵詞替換爲 const

# loader.js
module.exports = function (source) {
    return source.replace(/var/g, 'const')
}

# index.js
function test() {
    var a = 1;
    var b = 2;
    var c = 3;
    console.log(a, b, c);
}

test()

# wepback.config.js
const path = require('path')

module.exports = {
    mode: 'development',
    entry: {
        main: './src/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /.js$/,
                use: [
                    {
                        loader: path.resolve('./src/loader1.js'),
                    },
                ]
            }
        ]
    },
}
# `npm run build`,獲得打包文件 `bundle.js`
複製代碼

用法準則

  • 簡單易用
  • 使用鏈式傳遞。
  • 模塊化的輸出。
  • 確保無狀態
  • 使用 loader utilities
  • 記錄 loader 的依賴
  • 解析模塊依賴關係
  • 提取通用代碼
  • 避免絕對路徑
  • 使用 peer dependencies

簡單

loaders 應該只作單一任務。這不只使每一個 loader 易維護,也能夠在更多場景鏈式調用。git

鏈式

利用 loader 能夠鏈式調用的優點。寫五個簡單的 loader 實現五項任務,而不是一個 loader 實現五項任務;github

loader 能夠被鏈式調用意味着不必定要輸出 JavaScript。只要下一個 loader 能夠處理這個輸出,這個 loader 就能夠返回任意類型的模塊web

無狀態

確保 loader 在不一樣模塊轉換之間不保存狀態。每次運行都應該獨立於其餘編譯模塊以及相同模塊以前的編譯結果。npm

loader 工具庫

充分利用 loader-utils 包。它提供了許多有用的工具,但最經常使用的一種工具是獲取傳遞給 loader 的選項。schema-utils 包配合 loader-utils,用於保證 loader 選項,進行與 JSON Schema 結構一致的校驗。這裏有一個簡單使用二者的例子:json

loader.jsapi

import { getOptions } from 'loader-utils';
import validateOptions from 'schema-utils';

const schema = {
  type: 'object',
  properties: {
    test: {
      type: 'string'
    }
  }
}

export default function(source) {
  const options = getOptions(this);

  validateOptions(schema, options, 'Example Loader');

  // 對資源應用一些轉換……

  return `export default ${ JSON.stringify(source) }`;
};
複製代碼

loader 依賴

若是一個 loader 使用外部資源(例如,從文件系統讀取),必須聲明它。這些信息用於使緩存 loaders 無效,以及在觀察模式(watch mode)下重編譯。下面是一個簡單示例,說明如何使用 addDependency 方法實現上述聲明:數組

loader.js緩存

import path from 'path';

export default function(source) {
  var callback = this.async();
  var headerPath = path.resolve('header.js');

  this.addDependency(headerPath);

  fs.readFile(headerPath, 'utf-8', function(err, header) {
    if(err) return callback(err);
    callback(null, header + "\n" + source);
  });
};
複製代碼

模塊依賴

根據模塊類型,可能會有不一樣的模式指定依賴關係。例如在 CSS 中,使用 @import 和 url(...) 語句來聲明依賴。這些依賴關係應該由模塊系統解析。

能夠經過如下兩種方式中的一種來實現:

  • 經過把它們轉化成 require 語句。
  • 使用 this.resolve 函數解析路徑

通用代碼

避免在 loader 處理的每一個模塊中生成通用代碼。相反,你應該在 loader 中建立一個運行時文件,並生成 require 語句以引用該共享模塊。

絕對路徑

不要在模塊代碼中插入絕對路徑,由於當項目根路徑變化時,文件絕對路徑也會變化。loader-utils 中的 stringifyRequest 方法,能夠將絕對路徑轉化爲相對路徑。

同等依賴(Peer Dependencies)

若是你的 loader 簡單包裹另一個包,你應該把這個包做爲一個 peerDependency 引入。這種方式容許應用程序開發者在必要狀況下,在 package.json 中指定所需的肯定版本

測試

當你遵循上面的用法準則編寫了一個 loader,而且能夠在本地運行。下一步該作什麼呢?讓咱們用一個簡單的單元測試,來保證 loader 可以按照咱們預期的方式正確運行。咱們將使用 Jest 框架。而後還須要安裝 babel-jest 和容許咱們使用 import / export 和 async / await 的一些預設環境(presets)。讓咱們開始安裝,而且將這些依賴保存爲 devDependencies

npm install --save-dev jest babel-jest babel-preset-env
複製代碼

.babelrc

{
  "presets": [[
    "env",
    {
      "targets": {
        "node": "4"
      }
    }
  ]]
複製代碼

僅供學習參考

參考

相關文章
相關標籤/搜索