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

和自甴很熟 提交于 2019-12-11 04:47:43

问题


I have a requirement where we need to set dll path based upon whether it is executing in production or in development environment. So I decided to place that value in environment variable and tried to achieve that using webpack.DefinePlugin({}).

Method 1:

webpack.config.json

plugins: [
new webpack.DefinePlugin({
    'process.env.NODE_ENV' : JSON.stringify('production')
})

And then I tried to get that value in electron's main process, In my case 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);

But problem is that when I try to access that value in createWindow() function it is undefined so flow always goes to else block.

Is there anything I am missing?

Method 2:

I tried to achieve the same using cross-env node package, but no luck. Please find below code block which I tried using 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/"
    }

回答1:


The problem is multi-faceted.

First, your elec.js is executed by Electron before the app is loaded. Electron runs elec.js, which creates the Browser window (let win = new BrowserWindow(...)) and loads HTML file (win.loadURL(...)) into it inside the browser process, the HTML then loads your webpack'ed js. So none of the webpacked js code is available in the elec.js. The webpack'ed code is also running in another process than the elec.js.

Another thing to note is that webpack plugin does not create any assignment to the variable it points too. It is done by simple text search and replace, in your example, all instances of process.env.NODE_ENV will be replaced with "production" string in the source code that is webpack'ed. That is not too obvious, but messes up the expected results.

One last thing - webpack plugin does not change any code in elec.js file, as that file is not webpack'ed.

So all that makes process.env.NODE_ENV from the build/webpack time not available in the elec.js code.

Once the mechanisms are clear, there are few ways to solve the problem, I will give general ideas, as there are plenty of discussions on each, and depending on circumstances and desired use case, some are better than others:

  1. Generate a js file with necessary assignments based on environment variable during build (e.g. copy one of env-prod.js / env-dev.js -> env.js), copy it next to the elec.js, and reference it (require(env.js)) in elec.js.

  2. Pass environment variable from command line (e.g. NODE_ENV=1 electron .) - it will get to elec.js.

  3. Include a file into webpack based on environment variable (e.g. copy one of env-prod.js / env-dev.js -> env.js) and peek into webpacked' files from elec.js, e.g. using asar commands.

  4. Use different version in package.json depending on build (e.g. version: "1.0.0-DEBUG" for debug), and read & parse it by calling app.getVersion() in elec.js. It is tricky as package.json should be a single file, but OS commands could be used (e.g. in "scripts") to copy one of prepared package.json files before invoking npm.

Here are some links that could help too:

Electron issue #7714 - discussion on relevant features in Electron

electron-is-dev - module checking if it is in dev

Electron boilerplate - example boilerplate that uses config/env-prod/dev files




回答2:


Maybe late but can use simple hack in elec.js

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



回答3:


The insight provided by iva2k is what allowed me to come to a solution for this same problem.

Using dotenv to create a .env file for my config got me halfway to where I wanted to be (setting up a few environment variables for use in a production setting). The problem then became that Electron wasn't passing those from the Main process down to the Renderer process by default.

The work-around is simple: use Electron's own ipcMain and ipcRenderer modules to pass the dotenv object between the two.

In your main file (e.g. your elec.js file), place an ipcMain event listener after requiring the module:

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);
});

Elsewhere, in your application's rendering-side, place this anywhere necessary:

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;
}

This basically allowed me to declare one event in the Main process file, and then re-use it in any process-side file I wanted, thus allowing me to obfuscate config variables in a file that goes with the build, but isn't accessible to end-users without opening up the dev-tools.



来源:https://stackoverflow.com/questions/48661312/environment-variable-is-undefined-in-electron-even-it-has-been-set-inside-webpac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!