簡體   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