我有一个要求,我们需要根据它是在生产环境还是在开发环境中执行来设置dll路径。所以我决定将该值放在环境变量中并尝试使用webpack.DefinePlugin({})来实现它。
方法1:
webpack.config.json
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV' : JSON.stringify('production')
})
然后我试图在电子的主要过程中获得这个价值,在我的案例中是elec.js
elec.js
const Electron = require("electron");
const app = require("electron");
var dllPath = "";
function createWindow() {
let win = new BrowserWindow({
width: 800,
height: 600,
title: "Test",
icon: "Test.ico"
});
win.setMenu(null);
win.loadURL(
url.format({
pathname: path.join(__dirname, "../renderer/index.html"),
protocol: "file:",
slashes: true
})
);
if (process.env.NODE_ENV ==='production') {
dllPath = path.join(
__dirname,
"./../../dll/test.dll"
);
} else {
dllPath = path.join(
__dirname,
"./../../../dll/test.dll"
);
}
}
app.on("ready", createWindow);
但问题是当我尝试在createWindow()函数中访问该值时,它是未定义的,所以flow总是转到else块。
我有什么遗失的吗?
方法2:
我尝试使用cross-env节点包实现相同,但没有运气。请在下面的代码块中找到我尝试使用cross-env。
package.json
"scripts": {
"build": "cross-env process.env.NODE_ENV=production && rimraf ./dist/ && webpack --progress && node-sass
./src/renderer/scss/ -o ./dist/renderer/ && rimraf ./dist/renderer/includes/"
}
答案 0 :(得分:0)
问题是多方面的。
首先,在加载应用之前,您的 elec.js 由Electron执行。 Electron运行elec.js,它创建浏览器窗口(let win = new BrowserWindow(...)
)并在浏览器进程中加载HTML文件(win.loadURL(...)
),然后HTML加载你的webpack' ed js。因此,elec.js中没有任何webpacked js代码。 webpack的代码也在elec.js以外的其他进程中运行。
需要注意的另一件事是webpack插件不会为它指向的变量创建任何赋值。它通过简单的文本搜索和替换完成,在您的示例中,process.env.NODE_ENV的所有实例将替换为" production"源代码中的字符串是webpack' ed。这不是太明显,但会弄乱预期的结果。
最后一件事 - webpack插件不会更改elec.js文件中的任何代码,因为该文件不是webpack'
所以这一切使得build / webpack时间的process.env.NODE_ENV在elec.js代码中不可用。
一旦机制明确,解决问题的方法很少,我会给出一般性的想法,因为每个都有很多讨论,根据情况和期望的用例,有些比其他更好:
在构建期间根据环境变量生成具有必要赋值的js文件(例如,复制env-prod.js / env-dev.js - > env.js中的一个),将其复制到elec旁边。 js,并在elec.js中引用它(require(env.js)
。
从命令行传递环境变量(例如NODE_ENV=1 electron .
) - 它将转到elec.js。
根据环境变量将文件包含到webpack中(例如复制env-prod.js / env-dev.js - > env.js中的一个)并查看webpacked'来自elec.js的文件,例如使用asar
命令。
根据构建情况在package.json中使用不同的版本(例如版本:" 1.0.0-DEBUG"用于调试),并阅读&通过在elec.js中调用app.getVersion()来解析它。这很棘手,因为package.json应该是一个单独的文件,但是可以使用OS命令(例如在"脚本"中)来复制一个准备好的package.json文件,然后再调用npm。
以下是一些可能有用的链接:
Electron issue #7714 - 关于Electron相关功能的讨论
electron-is-dev - 模块检查它是否在dev
中Electron boilerplate - 使用config / env-prod / dev文件的示例样板
答案 1 :(得分:0)
也许晚了,但是可以在elec.js中使用简单的技巧
const isProduction = process.env.NODE_ENV === 'production' || (!process || !process.env || !process.env.NODE_ENV);
答案 2 :(得分:0)
iva2k提供的见解使我得以解决同一问题。
使用dotenv为我的配置创建一个.env
文件使我到了想要的位置(设置了一些环境变量以用于生产环境)。问题是,Electron默认不会将它们从 Main 进程传递到 Renderer 进程。
解决方法很简单:使用Electron自己的ipcMain
和ipcRenderer
模块在两者之间传递dotenv对象。
在您的主文件(例如您的 elec.js 文件)中,在需要模块之后放置一个ipcMain
事件监听器:
const config = require('dotenv').config();
const electron = require('electron');
const { app, BrowserWindow, ipcMain } = electron;
...
ipcMain.on('get-env', (event) => {
event.sender.send('get-env-reply', config);
});
在其他地方,在应用程序的呈现端,将其放置在必要的位置:
async function getConfig()
{
const { ipcRenderer } = window.require('electron');
let config = null;
ipcRenderer.on('get-env-reply', (event, arg) => {
// The dotenv config object should return an object with
// another object inside caled "parsed". Change this if need be.
config = arg.parsed;
});
ipcRenderer.send('get-env');
return config;
}
这基本上使我可以在Main进程文件中声明一个事件,然后在所需的任何进程端文件中重复使用它,从而使我能够混淆与构建一起提供的文件中的配置变量,但不能如果不打开开发工具,最终用户将无法访问。
答案 3 :(得分:0)
在您的控制台中
对于Windows 设置MY_VARIABLE = true
对于Linux $ export MY_VARIABLE = true
window.process.env.MY_VARIABLE