知海

DefinePlugin 插件

webpackjsorg-main插件参考

DefinePlugin 插件

DefinePlugin编译时将代码中的变量替换为其他值或表达式。这对于在开发构建和生产构建之间实现不同行为非常有用。如果你在开发构建中执行日志记录,但在生产构建中不执行,则可以使用一个全局常量来确定是否进行日志记录。这正是 DefinePlugin 的用武之地——为开发和生产构建设定好规则,然后无需再操心。

js 复制代码
new webpack.DefinePlugin({
  // Definitions...
});

用法

传递给 DefinePlugin 的每个键都是一个标识符,或者是用 . 连接的多个标识符。

  • 如果值是字符串,它将被用作代码片段。
  • 如果值不是字符串,它将被字符串化(包括函数)。
  • 如果值是对象,则其所有键都将以相同方式定义。
  • 如果在键前加上 typeof 前缀,则仅针对 typeof 调用进行定义。

这些值将被内联到代码中,从而使压缩(minification)过程能够移除冗余的条件判断。

js 复制代码
new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify("5fa3b9"),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: "1+1",
  "typeof window": JSON.stringify("object"),
  "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
});
js 复制代码
console.log(`Running App version ${VERSION}`);
if (!BROWSER_SUPPORTS_HTML5) require("html5shiv");

警告:process 定义值时,优先使用 'process.env.NODE_ENV': JSON.stringify('production'),而不是 process: { env: { NODE_ENV: JSON.stringify('production') } }。使用后者会覆盖 process 对象,这可能破坏与某些模块的兼容性,因为这些模块期望 process 对象上定义其他值。

提示: 请注意,由于插件执行的是直接文本替换,因此赋予它的值必须包含字符串自身的实际引号。通常,可以使用交替引号(如 '"production"'),或使用 JSON.stringify('production')

js 复制代码
if (!PRODUCTION) {
  console.log("Debug info");
}

if (PRODUCTION) {
  console.log("Production log");
}

经过 webpack 处理(未压缩)后,结果为:

js 复制代码
if (!true) {
  console.log("Debug info");
}
if (true) {
  console.log("Production log");
}

再经过压缩处理后,结果为:

js 复制代码
console.log("Production log");

特性标志(Feature Flags)

使用特性标志在生产/开发构建中启用/禁用特性。

js 复制代码
new webpack.DefinePlugin({
  NICE_FEATURE: JSON.stringify(true),
  EXPERIMENTAL_FEATURE: JSON.stringify(false),
});

服务 URL

在生产/开发构建中使用不同的服务 URL:

js 复制代码
new webpack.DefinePlugin({
  SERVICE_URL: JSON.stringify("https://dev.example.com"),
});

通过 runtimeValue 实现运行时值

function (getterFunction, [string] | true | object) => getterFunction()

可以定义一些变量,其值依赖于文件,并且当这些文件在文件系统中发生变化时会重新求值。这意味着当此类被监听的文件发生变化时,webpack 将重新构建。

webpack.DefinePlugin.runtimeValue 函数有两个参数:

  • 第一个参数是一个 function(module, key, version),应返回要赋给该定义的值。
  • 第二个参数可以是需要监听的文件路径数组,也可以是 true 以将该模块标记为不可缓存。自 5.26.0 起,它还可以接受一个对象参数,包含以下属性:
    • fileDependencies?: string[] 该函数所依赖的文件列表。
    • contextDependencies?: string[] 该函数所依赖的目录列表。
    • missingDependencies?: string[] 该函数所依赖的、当前不存在的文件列表。
    • buildDependencies?: string[] 该函数所依赖的构建依赖列表。
    • version?: string | () => string 该函数的版本。
js 复制代码
import path from "node:path";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const fileDep = path.resolve(__dirname, "sample.txt");

new webpack.DefinePlugin({
  BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now, {
    fileDependencies: [fileDep],
  }),
});

BUILT_AT 的值将是 'sample.txt' 在文件系统中最后一次被更新的时间,例如 1597953013291

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。