繁体   English   中英

环境变量在电子中未定义,即使它已在 webpack.DefinePlugin 中设置

[英]Environment variable is undefined in electron even it has been set inside webpack.DefinePlugin

我有一个要求,我们需要根据它是在生产环境还是在开发环境中执行来设置 dll 路径。 所以我决定将该值放在环境变量中,并尝试使用 webpack.DefinePlugin({}) 来实现。

方法一:

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() 函数中访问该值时,它是未定义的,因此流程总是转到 else 块。

有什么我想念的吗?

方法二:

我尝试使用跨环境节点包实现相同的目标,但没有运气。 请在下面找到我尝试使用 cross-env 的代码块。

包.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/"
    }

问题是多方面的。

首先,您的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 的所有实例都将替换为 webpack 源代码中的“生产”字符串。 这不是太明显,但会破坏预期的结果。

最后一件事 - webpack 插件不会更改 elec.js 文件中的任何代码,因为该文件未经过 webpack。

因此,所有这些都使得 elec.js 代码中无法使用 build/webpack 时的 process.env.NODE_ENV。

一旦机制明确,解决问题的方法很少,我将给出一般性的想法,因为每个人都有很多讨论,并且根据情况和所需的用例,有些比其他更好:

  1. 在构建期间根据环境变量生成具有必要分配的js文件(例如复制env-prod.js / env-dev.js -> env.js之一),将其复制到elec.js旁边,并引用它( require(env.js) ) 在 elec.js 中。

  2. 从命令行传递环境变量(例如NODE_ENV=1 electron . ) - 它将到达 elec.js。

  3. 根据环境变量将文件包含到 webpack 中(例如复制 env-prod.js / env-dev.js -> env.js 之一)并从 elec.js 查看 webpacked 文件,例如使用asar命令。

  4. 根据构建在 package.json 中使用不同的版本(例如,用于调试的版本:“1.0.0-DEBUG”),并通过在 elec.js 中调用 app.getVersion() 来读取和解析它。 这很棘手,因为 package.json 应该是单个文件,但可以使用操作系统命令(例如在“脚本”中)在调用 npm 之前复制准备好的 package.json 文件之一。

这里有一些链接也可以提供帮助:

Electron issue #7714 - 讨论 Electron 中的相关特性

电子是开发- 模块检查它是否在开发中

电子样板- 使用 config/env-prod/dev 文件的示例样板

iva2k 提供的洞察力使我能够为同样的问题找到解决方案。

使用dotenv为我的配置创建一个.env文件让我达到了我想要的目标(设置一些环境变量以在生产环境中使用)。 然后问题变成了默认情况下,Electron 没有将这些从Main进程传递到Renderer进程。

解决方法很简单:使用 Electron 自己的ipcMainipcRenderer模块在两者之间传递 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;
}

这基本上允许我在主进程文件中声明一个事件,然后在我想要的任何进程端文件中重新使用它,从而允许我在与构建一起但无法访问的文件中混淆配置变量无需打开开发工具即可提供给最终用户。

也许晚了,但可以在 elec.js 中使用简单的 hack

const isProduction = process.env.NODE_ENV === 'production' || (!process || !process.env || !process.env.NODE_ENV);

在您的控制台中

对于 Windows设置 MY_VARIABLE=true

对于 linux $ export MY_VARIABLE=true

window.process.env.MY_VARIABLE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM