DefinePlugin 是 Webpack 在编译时进行静态字符串替换的插件,需用 JSON.stringify 包裹值以避免 ReferenceError,支持环境变量注入与死代码消除,配合 mode 参数可统一管理多环境配置。

Webpack 的 DefinePlugin 是在编译时做**静态字符串替换**的插件,不是运行时读取环境变量。它把你在代码里写的变量(比如 process.env.NODE_ENV)直接替换成你配置的值,所以必须确保传入的是字符串字面量,且用 JSON.stringify() 包裹,否则会报 ReferenceError: xxx is not defined。
正确写法:必须用 JSON.stringify 包裹值
比如你想让开发环境的 API 地址是 'http://localhost:8080',生产环境是 'https://api.example.com':
- 在
webpack.dev.config.js中:new webpack.DefinePlugin({ 'process.env.API_BASE_URL': JSON.stringify('http://localhost:8080'), 'process.env.NODE_ENV': JSON.stringify('development') }) - 在
webpack.prod.config.js中:new webpack.DefinePlugin({ 'process.env.API_BASE_URL': JSON.stringify('https://api.example.com'), 'process.env.NODE_ENV': JSON.stringify('production') })
这样你在 JS 里写 console.log(process.env.API_BASE_URL),打包后就直接变成 console.log("http://localhost:8080") —— 没有运行时开销,也不会暴露未使用的分支。
在业务代码中安全使用
因为是编译期替换,你可以放心写条件判断,Uglify 或 Terser 会自动删掉死代码:
-
if (process.env.NODE_ENV === 'development') { console.log('debug info') }→ 生产包里这整行会被移除 -
const baseUrl = process.env.API_BASE_URL→ 直接替换成字符串字面量,不依赖全局process
注意:不要写 process.env.NODE_ENV === 'dev' 这种没定义的值,否则替换失败,运行时报错。
配合 mode 参数统一管理更省事
Webpack 4+ 支持 mode,推荐用函数式导出配置,避免维护多份 config 文件:
- 在
webpack.config.js中导出函数:
module.exports = (env, argv) => ({<br> mode: argv.mode,<br> plugins: [<br> new webpack.DefinePlugin({<br> 'process.env.NODE_ENV': JSON.stringify(argv.mode),<br> 'process.env.API_BASE_URL': JSON.stringify(<br> argv.mode === 'production'<br> ? 'https://api.example.com'<br> : 'http://localhost:8080'<br> )<br> })<br> ]<br>}) - 脚本里调用:
"scripts": {<br> "dev": "webpack serve --mode development",<br> "build": "webpack --mode production"<br>}
常见错误避坑
这些写法都会出问题:
-
'process.env.NODE_ENV': '"development"'→ 少了JSON.stringify,引号不匹配,编译报错 -
'process.env.NODE_ENV': 'development'→ 没加引号,Webpack 当成变量名,提示development is not defined -
process.env.NODE_ENV在 Node 环境(如配置文件里)直接读取 → 它是空的,DefinePlugin只影响打包后的浏览器代码
本质上,DefinePlugin 就是“找-替换”工具,它不关心变量来源,只认你给它的字符串。写对格式,就能稳稳区分环境。


















