自定义Webpack项目中process.env在业务代码失效及版本输出问题
非CRA搭建的Webpack项目中process.env业务代码不生效的解决方案
问题场景
自行搭建非CRA(Create React App)的Webpack项目时,process.env在webpack.config.js中可正常读取,但在app.js等业务代码里无法生效。需求是将版本信息输出到控制台,构建后能在服务器端查看,拒绝硬编码版本号的方式,现有配置未达预期。
现有代码片段
App.js业务代码
import React from "react"; import styles from "./styles.scss"; const onClickEvent = (e) => { e.preventDefault(); alert("You Clicked Me!"); }; const App = () => { console.log(process.env.TERM_PROGRAM_VERSION); return ( <div className={styles.content}> <div className={styles.label}>OWN WEBPACK</div> <button className={styles.btn} onClick={onClickEvent}> Click Me 😎 </button> </div> ); }; export default App;
webpack.config.js配置
const webpack = require("webpack"); const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); const production = process.env.NODE_ENV === "production"; const Dotenv = require("dotenv-webpack"); console.log(process.env.TERM_PROGRAM_VERSION); module.exports = { entry: { myAppName: path.resolve(__dirname, "./src/index.js") }, output: { path: path.resolve(__dirname, "./dist"), filename: production ? "[name].[contenthash].js" : "[name].js", }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ["babel-loader"], }, { test: /\.s(a|c)ss$/, exclude: /node_modules/, use: [ production ? MiniCssExtractPlugin.loader : "style-loader", { loader: "css-loader", options: { modules: true, sourceMap: !production, }, }, { loader: "sass-loader", options: { sourceMap: !production, }, }, ], }, ], }, resolve: { extensions: ["*", ".js", ".jsx", ".scss"], }, plugins: [ new CleanWebpackPlugin(), new Dotenv(), new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin({ title: "Webpack & React", template: "./src/index.html", favicon: "./public/favicon.ico", }), new MiniCssExtractPlugin({ filename: production ? "[name].[contenthash].css" : "[name].css", }), new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), "process.env.MY_ENV": JSON.stringify(process.env.MY_ENV), }), ], devServer: { port: 3001, hot: true, }, mode: production ? "production" : "development", };
package.json脚本配置
"scripts": { "start": "npm run build && node server/index.js", "dev": "NODE_ENV=development test=$TERM_PROGRAM_VERSION webpack serve --config webpack.config.js", "build": "NODE_ENV=production webpack --config webpack.config.js", "build:dev": "NODE_ENV=development webpack --config webpack.config.js", "build:watch": "NODE_ENV=development node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --watch" },
服务器端代码server/index.js
const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const app = express(); if (process.env.NODE_ENV === 'development') { console.log('in development.'); } else { console.log('in production.'); } /* App Config */ app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(express.static(path.join(__dirname, '../dist'))); /* Server Initialization */ app.get('/', (req, res) => res.sendFile('index.html')); var port = process.env.PORT || 3000; app.listen(port, () => console.log(`Server initialized on: http://localhost:${port} // ${new Date()}`));
问题根源
- 环境变量传递错误:
dev脚本中把版本变量命名为test,但业务代码读取的是TERM_PROGRAM_VERSION,变量名不匹配 - 未显式注入业务代码:仅通过
Dotenv插件无法让业务代码直接读取系统环境变量,必须通过webpack.DefinePlugin显式注入 - 生产构建未传变量:
build等生产脚本未传递版本相关环境变量,导致构建后无版本信息
修复方案
1. 修正package.json的环境变量传递
将所有脚本中的版本变量名改为TERM_PROGRAM_VERSION,确保生产构建也传递该变量:
"scripts": { "start": "npm run build && node server/index.js", "dev": "NODE_ENV=development TERM_PROGRAM_VERSION=$TERM_PROGRAM_VERSION webpack serve --config webpack.config.js", "build": "NODE_ENV=production TERM_PROGRAM_VERSION=$TERM_PROGRAM_VERSION webpack --config webpack.config.js", "build:dev": "NODE_ENV=development TERM_PROGRAM_VERSION=$TERM_PROGRAM_VERSION webpack --config webpack.config.js", "build:watch": "NODE_ENV=development TERM_PROGRAM_VERSION=$TERM_PROGRAM_VERSION node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --watch" },
2. 通过DefinePlugin注入版本变量到业务代码
在webpack.config.js的DefinePlugin配置中添加TERM_PROGRAM_VERSION,确保业务代码能读取到:
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), "process.env.MY_ENV": JSON.stringify(process.env.MY_ENV), "process.env.TERM_PROGRAM_VERSION": JSON.stringify(process.env.TERM_PROGRAM_VERSION) }),
3. 验证业务代码输出
此时App.js中的console.log(process.env.TERM_PROGRAM_VERSION)应该能正常输出版本信息,可优化输出格式:
console.log(`当前应用版本: ${process.env.TERM_PROGRAM_VERSION}`);
4. 服务器端查看版本(可选)
如果需要在服务器启动时查看构建版本,可以在构建时生成version.json文件:
- 在
webpack.config.js的plugins数组中添加自定义插件:
{ apply: (compiler) => { compiler.hooks.done.tap('WriteVersionFile', () => { const fs = require('fs'); const version = process.env.TERM_PROGRAM_VERSION; fs.writeFileSync(path.resolve(__dirname, './dist/version.json'), JSON.stringify({ version })); }); } }
- 修改
server/index.js读取版本文件:
const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); const fs = require('fs'); const app = express(); // 读取版本信息 const versionFilePath = path.join(__dirname, '../dist/version.json'); if (fs.existsSync(versionFilePath)) { const { version } = require(versionFilePath); console.log(`当前构建版本: ${version}`); } if (process.env.NODE_ENV === 'development') { console.log('in development.'); } else { console.log('in production.'); } /* App Config */ app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(express.static(path.join(__dirname, '../dist'))); /* Server Initialization */ app.get('/', (req, res) => res.sendFile('index.html')); var port = process.env.PORT || 3000; app.listen(port, () => console.log(`Server initialized on: http://localhost:${port} // ${new Date()}`));
内容的提问来源于stack exchange,提问作者Виктория
相关产品推荐
相关产品推荐

