构建后无法访问dotenv-webpack变量,Electron公证脚本变量未定义
Electron构建后公证脚本中process.env变量未定义的问题
我正在开发一个Electron + Webpack + React + TypeScript应用,用electron-builder打包并公证。本地运行时能正常访问process.env变量,但执行构建后的公证脚本时,这些变量却显示未定义。
我的配置文件如下:
webpack.config.mjs
import { fileURLToPath } from 'url'; import CopyPlugin from 'copy-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; import webpack from 'webpack'; import { merge } from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; /* eslint-disable no-underscore-dangle */ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /* eslint-enable */ const isEnvProduction = process.env.NODE_ENV === 'production'; const isEnvDevelopment = process.env.NODE_ENV === 'development'; const commonConfig = { devtool: isEnvDevelopment ? 'eval-cheap-module-source-map' : false, mode: isEnvProduction ? 'production' : 'development', output: { path: path.join(__dirname, 'dist') }, node: { __dirname: false, __filename: false }, plugins: [ new webpack.NormalModuleReplacementPlugin(/^\S+\/\S+\.js$/, (resource) => { // eslint-disable-next-line no-param-reassign resource.request = resource.request.replace(/\.js$/, ''); }), ], resolve: { extensions: ['.js', '.json', '.ts', '.tsx'], plugins: [ new TsconfigPathsPlugin({ configFile: './tsconfig.json', extensions: ['.js', '.json', '.ts', '.tsx'], }), ], }, module: { rules: [ { test: /\.(ts|tsx)$/, exclude: /node_modules/, loader: 'ts-loader', }, { test: /\.(scss|css)$/, use: ['style-loader', 'css-loader'], }, { test: /\.(jpg|png|svg|ico|icns)$/, loader: 'file-loader', options: { name: '[path][name].[ext]', }, }, { test: /\.m?js/, type: 'javascript/auto', }, { test: /\.m?js/, resolve: { fullySpecified: false, }, }, { test: /\.wav$|\.mp3$/, exclude: /node_modules/, loader: 'file-loader', }, ], }, }; const mainConfig = merge(commonConfig, { entry: './src/main/main.ts', target: 'electron-main', output: { filename: 'main.bundle.js' }, plugins: [ new CopyPlugin({ patterns: [ { from: 'package.json', to: 'package.json', transform: (content, _path) => { const jsonContent = JSON.parse(content); const electronVersion = jsonContent.devDependencies.electron; delete jsonContent.devDependencies; delete jsonContent.optionalDependencies; delete jsonContent.scripts; delete jsonContent.build; jsonContent.main = './main.bundle.js'; jsonContent.scripts = { start: 'electron ./main.bundle.js' }; jsonContent.devDependencies = { electron: electronVersion }; return JSON.stringify(jsonContent, undefined, 2); }, }, { from: '../ableton-js/midi-script', to: './dist/' }, ], }), new Dotenv({ }), ], }); const preloadConfig = merge(commonConfig, { entry: './src/preload/preload.ts', target: 'electron-preload', output: { filename: 'preload.bundle.js' }, }); const rendererConfig = merge(commonConfig, { entry: './src/renderer/renderer.tsx', target: 'electron-renderer', output: { filename: 'renderer.bundle.js' }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, './public/index.html'), }), ], }); export default [mainConfig, preloadConfig, rendererConfig];
package.json相关配置
"build": { "afterSign": "./notarize.js", } "dependencies": { "dotenv-webpack": "^8.0.1", }
notarize.js
const notarize = require('@electron/notarize'); exports.default = async function notarizing(context) { const { electronPlatformName, appOutDir } = context; if (electronPlatformName !== 'darwin') { return; } const appName = context.packager.appInfo.productFilename; console.log('notarizing', process.env.REACT_APP_APPLEID); return await notarize.notarize({ appBundleId: 'com.yourcompany.yourAppId', appPath: `${appOutDir}/${appName}.app`, appleId: process.env.REACT_APP_APPLEID, appleIdPassword: process.env.APPLEIDPASS, }); };
我已经按照dotenv-webpack的官方文档配置了,但还是遇到这个问题。
问题原因及解决方案
核心原因
dotenv-webpack仅负责在Webpack打包过程中把环境变量注入到应用代码(main/renderer/preload),但它不会影响electron-builder的构建流程脚本——notarize.js是electron-builder在打包完成后单独启动的Node脚本,不属于Webpack编译范围,因此无法获取dotenv-webpack注入的变量。
另外,你注释掉了直接调用dotenv.config()的代码,导致Webpack启动前没有将环境变量加载到Node.js的process.env中,而公证脚本依赖Node进程本身的环境变量才能读取到值。
解决方案
方案1:在Webpack配置前加载dotenv
恢复注释的dotenv代码,让Node进程在启动Webpack前就加载环境变量,这样公证脚本就能读取到:
修改webpack.config.mjs开头:
import { fileURLToPath } from 'url'; import path from 'path'; // 补上缺失的path模块导入 import CopyPlugin from 'copy-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; import webpack from 'webpack'; import { merge } from 'webpack-merge'; import dotenv from 'dotenv'; dotenv.config(); // 恢复这一行 import Dotenv from 'dotenv-webpack';
方案2:构建时直接传入环境变量
如果不想用dotenv,也可以在执行构建命令时直接注入变量:
REACT_APP_APPLEID=你的苹果ID APPLEIDPASS=你的密码 npm run build
这种方式会直接把变量注入到Node进程中,公证脚本可直接读取。
方案3:在公证脚本中单独加载dotenv
仅让公证脚本获取环境变量,可在notarize.js开头添加dotenv加载逻辑:
const dotenv = require('dotenv'); dotenv.config(); // 加载项目根目录的.env文件 const notarize = require('@electron/notarize'); exports.default = async function notarizing(context) { // ... 原有代码 };
额外注意事项
- 确保
.env文件在项目根目录,敏感信息(如密码)需加入.gitignore,建议用密钥管理工具而非明文存储。 - dotenv-webpack仅影响Webpack编译后的应用代码,构建流程相关的脚本依赖Node进程本身的环境变量,需单独处理。
内容的提问来源于stack exchange,提问作者brutus
相关产品推荐
相关产品推荐

