val-loader

免責聲明: val-loader 是由社群成員維護的第三方套件,它可能沒有與 webpack 相同的支援、安全政策或授權,而且它並非由 webpack 維護。

npm node tests coverage discussion size

一個 webpack loader,它會執行給定的模組,並在建置時回傳執行結果,當模組在套件中需要時。這樣一來,loader 會將模組從程式碼變更為結果。

檢視 val-loader 的另一種方式是,它允許使用者建立自己的自訂 loader 邏輯,而不用撰寫自訂 loader。

目標模組會使用兩個參數呼叫:(options, loaderContext)

  • 選項:載入器選項(例如在 webpack 設定檔中提供。請參閱以下的 範例)。
  • loaderContext載入器內容

開始使用

首先,您需要安裝 val-loader

npm install val-loader --save-dev
yarn add -D val-loader
pnpm add -D val-loader

然後將載入器新增至您的 webpack 設定檔。例如

target-file.js

module.exports = (options, loaderContext) => {
  return { code: "module.exports = 42;" };
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /target-file.js$/,
        use: [
          {
            loader: `val-loader`,
          },
        ],
      },
    ],
  },
};

src/entry.js

const answer = require("target-file");

並透過您偏好的方式執行 webpack

選項

executableFile

類型

type executableFile = string;

預設:未定義

允許指定可執行檔的路徑

data.json

{
  "years": "10"
}

executable-file.js

module.exports = function yearsInMs(options, loaderContext, content) {
  const { years } = JSON.parse(content);
  const value = years * 365 * 24 * 60 * 60 * 1000;

  return {
    cacheable: true,
    code: "module.exports = " + value,
  };
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(json)$/i,
        rules: [
          {
            loader: "val-loader",
            options: {
              executableFile: path.resolve(
                __dirname,
                "fixtures",
                "executableFile.js",
              ),
            },
          },
        ],
      },
      {
        test: /\.json$/i,
        type: "asset/resource",
      },
    ],
  },
};

傳回物件屬性

此載入器的目標模組必須匯出傳回物件的 Function,或解析物件的 Promise(例如非同步函式),至少包含一個 code 屬性,但可以包含任意數量的其他屬性。

code

類型

type code = string | Buffer;

預設:未定義 必要

傳遞至 webpack 或將取代模組的下一個載入器的程式碼。

sourceMap

類型

type sourceMap = object;

預設:未定義

傳遞至 webpack 或下一個載入器的原始碼對應。

ast

類型

type ast = Array<object>;

預設:未定義

將傳遞至下一個載入器的 抽象語法樹。如果下一個載入器使用相同的 AST,則有助於加快建置時間。

dependencies

類型

type dependencies = Array<string>;

預設值:[]

一個絕對的原生路徑陣列,指向 webpack 應監控變更的文件依賴項。

也可以使用 loaderContext.addDependency(file: string) 來新增依賴項。

contextDependencies

類型

type contextDependencies = Array<string>;

預設值:[]

一個絕對的原生路徑陣列,指向 webpack 應監控變更的目錄依賴項。

也可以使用 loaderContext.addContextDependency(directory: string) 來新增目錄依賴項。

buildDependencies

類型

type buildDependencies = Array<string>;

預設值:[]

一個絕對的原生路徑陣列,指向 webpack 應監控變更的目錄依賴項。

也可以使用 loaderContext.addBuildDependency(file: string) 來新增建置依賴項。

cacheable

類型

type cacheable = boolean;

預設值:false

如果為 true,則指定在監控模式下,只要沒有任何 dependencies 變更,就可以重新使用程式碼。

範例

簡單

在此範例中,載入器已設定為針對檔案名稱 years-in-ms.js 執行操作,執行程式碼,並將結果儲存在套件中,作為執行的結果。此範例將 years 傳遞為 option,這對應到目標模組匯出函式中的 years 參數

years-in-ms.js

module.exports = function yearsInMs({ years }) {
  const value = years * 365 * 24 * 60 * 60 * 1000;

  // NOTE: this return value will replace the module in the bundle
  return {
    cacheable: true,
    code: "module.exports = " + value,
  };
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve("src/years-in-ms.js"),
        use: [
          {
            loader: "val-loader",
            options: {
              years: 10,
            },
          },
        ],
      },
    ],
  },
};

在套件中,需要模組後會傳回

import tenYearsMs from "years-in-ms";

console.log(tenYearsMs); // 315360000000

Modernizr

範例顯示如何建置 modernizr

entry.js

import modenizr from "./modernizr.js";

modernizr.js

const modernizr = require("modernizr");

module.exports = function (options) {
  return new Promise(function (resolve) {
    // It is impossible to throw an error because modernizr causes the process.exit(1)
    modernizr.build(options, function (output) {
      resolve({
        cacheable: true,
        code: `var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; ${output} modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;`,
      });
    });
  });
};

webpack.config.js

const path = require("path");
module.exports = {
  module: {
    rules: [
      {
        test: path.resolve(__dirname, "src", "modernizr.js"),
        use: [
          {
            loader: "val-loader",
            options: {
              minify: false,
              options: ["setClasses"],
              "feature-detects": [
                "test/css/flexbox",
                "test/es6/promises",
                "test/serviceworker",
              ],
            },
          },
        ],
      },
    ],
  },
};

Figlet

範例顯示如何建置 figlet

entry.js

import { default as figlet } from "./figlet.js";

console.log(figlet);

figlet.js

const figlet = require("figlet");

function wrapOutput(output, config) {
  let figletOutput = "";

  if (config.textBefore) {
    figletOutput += encodeURI(`${config.textBefore}\n`);
  }

  output.split("\n").forEach((line) => {
    figletOutput += encodeURI(`${line}\n`);
  });

  if (config.textAfter) {
    figletOutput += encodeURI(`${config.textAfter}\n`);
  }

  return `module.exports = decodeURI("${figletOutput}");`;
}

module.exports = function (options) {
  const defaultConfig = {
    fontOptions: {
      font: "ANSI Shadow",
      horizontalLayout: "default",
      kerning: "default",
      verticalLayout: "default",
    },
    text: "FIGLET-LOADER",
    textAfter: null,
    textBefore: null,
  };

  const config = Object.assign({}, defaultConfig, options);

  return new Promise(function (resolve, reject) {
    figlet.text(config.text, config.fontOptions, (error, output) => {
      if (error) {
        return reject(error);
      }

      resolve({
        cacheable: true,
        code: "module.exports = " + wrapOutput(output, config),
      });
    });
  });
};

webpack.config.js

const path = require("path");
module.exports = {
  module: {
    rules: [
      {
        test: path.resolve(__dirname, "src", "figlet.js"),
        use: [
          {
            loader: "val-loader",
            options: {
              text: "FIGLET",
            },
          },
        ],
      },
    ],
  },
};

貢獻

如果您尚未執行此操作,請花點時間閱讀我們的貢獻指南。

CONTRIBUTING

授權

MIT