website/docs/en/plugins/webpack/define-plugin.mdx
import WebpackLicense from '@components/WebpackLicense';
<WebpackLicense from="https://webpack.js.org/plugins/define-plugin/" />The DefinePlugin replaces variables in your code with other values or expressions at compile time. This can be useful for allowing different behavior between development builds and production builds. If you perform logging in your development build but not in the production build you might use a global constant to determine whether logging takes place. That's where DefinePlugin shines, set it and forget it rules for development and production builds.
new rspack.DefinePlugin({
// Definitions...
});
type CodeValue = RecursiveArrayOrRecord<CodeValuePrimitive>;
type CodeValuePrimitive =
| null
| undefined
| RegExp
| Function
| string
| number
| boolean
| bigint;
type RecursiveArrayOrRecord<T> =
| { [index: string]: RecursiveArrayOrRecord<T> }
| Array<RecursiveArrayOrRecord<T>>
| T;
type DefinePluginOptions = Record<string, CodeValue>;
Each key passed into DefinePlugin is an identifier or multiple identifiers joined with ..
typeof to the key, it's only defined for typeof calls.The values will be inlined into the code allowing a minification pass to remove the redundant conditional.
new rspack.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),
});
console.log('Running App version ' + VERSION);
if (!BROWSER_SUPPORTS_HTML5) require('html5shiv');
:::warning
When defining values for process prefer 'process.env.NODE_ENV': JSON.stringify('production') over process: { env: { NODE_ENV: JSON.stringify('production') } }. Using the latter will overwrite the process object which can break compatibility with some modules that expect other values on the process object to be defined.
:::
:::tip
Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with alternate quotes, such as '"production"', or by using JSON.stringify('production').
:::
if (!PRODUCTION) {
console.log('Debug info');
}
if (PRODUCTION) {
console.log('Production log');
}
After passing through Rspack with no minification results in:
if (!true) {
console.log('Debug info');
}
if (true) {
console.log('Production log');
}
and then after a minification pass results in:
console.log('Production log');
Enable/disable features in production/development build using feature flags.
new rspack.DefinePlugin({
NICE_FEATURE: JSON.stringify(true),
EXPERIMENTAL_FEATURE: JSON.stringify(false),
});
Use a different service URL in production/development builds:
new rspack.DefinePlugin({
SERVICE_URL: JSON.stringify('https://dev.example.com'),
});
JSON.stringifyUse JSON.stringify when you want to inject a literal value rather than a code fragment.
Common cases include:
process.env.*.This is because string values passed to DefinePlugin are inserted directly as code and do not get quotes added automatically.
new rspack.DefinePlugin({
MODE: 'production',
MODE_STRINGIFIED: JSON.stringify('production'),
});
const mode = MODE;
const modeStringified = MODE_STRINGIFIED;
// Turns into
const mode = production;
const modeStringified = 'production';
In the example above, MODE is treated as the identifier production instead of the string 'production', which will usually cause a runtime error. MODE_STRINGIFIED is replaced with a valid string literal, making it the safer option.
If you need to inject an object or array, JSON.stringify is also recommended:
new rspack.DefinePlugin({
APP_INFO: JSON.stringify({
name: 'demo',
features: ['a', 'b'],
}),
});
This makes APP_INFO a usable object literal in the generated code. By contrast, APP_INFO: { ... } would be treated by DefinePlugin as a nested definition config and processed recursively, rather than being injected as an object literal into application code.