val-loader

免责声明 val-loader是一个由社区成员维护的第三方包,它可能不具备与 webpack 相同的支持、安全策略或许可证,并且不受 webpack 维护。

npm node tests coverage discussion size

val-loader

一个 webpack loader,在构建时执行给定模块,并在模块在 bundle 中被需要时返回执行结果。通过这种方式,该 loader 将模块从代码转换为结果。

另一种看待 val-loader 的方式是,它允许用户实现自定义 loader 逻辑,而无需编写完整的自定义 loader。

目标模块会以两个参数调用:(options, loaderContext)

  • options: loader 选项(例如在 webpack 配置中提供。请参阅下面的示例)。
  • loaderContext: loader 上下文

入门

首先,你需要安装 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(例如,通过 CLI 或 npm 脚本)。

选项

executableFile

类型

type executableFile = string;

默认值:undefined

允许指定可执行文件的路径。

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",
      },
    ],
  },
};

返回对象属性

此 loader 的目标模块必须导出一个返回对象的函数,或解析为对象的 Promise(例如 async function),其中至少包含一个 code 属性,但也可以包含其他属性。

code

类型

type code = string | Buffer;

默认值:undefined 必填

传递给 webpack 或下一个 loader 的代码,它将替换原始模块。

sourceMap

类型

type sourceMap = object;

默认值:undefined

传递给 webpack 或下一个 loader 的 Source Map。

ast

类型

type ast = Array<object>;

默认值:undefined

一个将传递给下一个 loader 的抽象语法树 (AST)。如果下一个 loader 使用相同的 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 都没有改变,则代码可以在监听模式下重复使用。

示例

简单

在此示例中,loader 被配置为处理名为 years-in-ms.js 的文件,执行代码,并将执行结果存储在 bundle 中。此示例将 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,
            },
          },
        ],
      },
    ],
  },
};

在 bundle 中,require 该模块将返回

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",
            },
          },
        ],
      },
    ],
  },
};

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

贡献

许可证

MIT