isemaj
isemaj

Reputation: 587

Ways to detect node environment in electron

I would like to know how can I detect the NODE_ENV variable inside the electron main file.

What I'm trying to do is to set the loadURL to localhost:8080 if my NODE_ENV === 'dev' otherwise to /dist/index.html. Because I want to use some webpack-dev-server features such as the HMR and live reload during the development.

I set my npm script in this way but I'm not sure if it is correct.

package.json

  "scripts": {
    "start": "electron .",
    "start:dev": "NODE_ENV=dev webpack-dev-server --config webpack.dev.js && electron .",
    "build": "NODE_ENV=prod webpack --config webpack.prod.js && electron ."
  },

Here is my electron main file.

main.js

const electron = require('electron');
const url = require('url');
const path = require('path');

const { app, BrowserWindow } = electron;

let mainWindow = null;

app.on('ready', function() {   // eslint-disable-line 
  mainWindow = new BrowserWindow({
    webPreferences: {
      nodeIntegration: true,
    },
  });

  // mainWindow.loadURL('http://localhost:8080/');

  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, '/dist/index.html'),
    protocol: 'file:',
    slashes: true,
  }));

  mainWindow.on('closed', function(){  
    app.quit();
  });
});

Upvotes: 4

Views: 3972

Answers (2)

danst3in
danst3in

Reputation: 79

I will share some of the code from a project I am working on that deals with this issue and hopefully it will help clarify how you might be able to solve your issue. Electron considers the environment to always be "development" if you are not loading the app from an executable file after packaging the app with something like electron-builder or electron-packager. Distinguishing "development" from "production" #7714

This has made it time consuming for me to test other items that behave differently in prod vs. dev, but at least that seems to consistently work.

Once this is understood you can use electron.app.isPackaged to set a variable in your main.js file that can be used to control certain functionality.

Demo below...let me know if you have confusion that is not explained in the commented parts of the code.

Here are the npm scripts I am using in a project running Electron v7.0.1:

"main": "main.js",
  "scripts": {
    "test": "jest",
    "prod": "webpack --mode production --config webpack.build.config.js && electron --noDevServer .",
    "start": "webpack-dev-server --hot --host 0.0.0.0 --config=./webpack.dev.config.js --mode development",
    "build": "webpack --config webpack.build.config.js --mode production",
    "package-mac": "electron-builder  build --x64 --mac",
    "package-all": "electron-builder  build -mwl",
    "package-linux": "electron-builder build --linux",
    "gh-publish-mac": "electron-builder build --x64 --mac -p always",
    "gh-publish": "electron-builder build -mwl -p always",
    }

Here is code from the main.js file that is used to manage some functionality based on dev vs prod:

// Keep a reference for dev mode
let dev = false;

// this works if npm run build, followed by npm run package-(any of the scripts),
// and then open from executable file
dev = !app.isPackaged;

function createWindow() {
  // Create the new browser window instance. devtools set to false in production
  if (!dev) {
    mainWindow = new BrowserWindow({
      width: 2000,
      height: 1000,
      minWidth: 1304,
      minHeight: 700,
      backgroundColor: "-webkit-linear-gradient(top, #3dadc2 0%,#2f4858 100%)",
      show: false,
      title: "Swell",
      allowRunningInsecureContent: true,
      webPreferences: {
        devTools: false,
        nodeIntegration: true,
        sandbox: false,
        webSecurity: true,
      },
      icon: `${__dirname}/src/assets/icons/64x64.png`,
    });
  } else {
    mainWindow = new BrowserWindow({
      width: 2000,
      height: 1000,
      minWidth: 1304,
      minHeight: 700,
      backgroundColor: "-webkit-linear-gradient(top, #3dadc2 0%,#2f4858 100%)",
      show: false,
      title: "Swell",
      allowRunningInsecureContent: true,
      webPreferences: {
        nodeIntegration: true,
        sandbox: false,
        webSecurity: true,
      },
      icon: `${__dirname}/src/assets/icons/64x64.png`,
    });
  }

  if (dev) {
    const {
      default: installExtension,
      REACT_DEVELOPER_TOOLS,
      REDUX_DEVTOOLS,
    } = require("electron-devtools-installer");
    // If we are in developer mode Add React & Redux DevTools to Electon App
    installExtension(REACT_DEVELOPER_TOOLS)
      .then((name) => console.log(`Added Extension:  ${name}`))
      .catch((err) => console.log("An error occurred: ", err));

    installExtension(REDUX_DEVTOOLS)
      .then((name) => console.log(`Added Extension:  ${name}`))
      .catch((err) => console.log("An error occurred: ", err));
  }

  // and load the index.html of the app.
  let indexPath;

  if (dev && process.argv.indexOf("--noDevServer") === -1) {
    // if we are in dev mode load up 'http://localhost:8080/index.html'
    indexPath = url.format({
      protocol: "http:",
      host: "localhost:8080",
      pathname: "index.html",
      slashes: true,
    });
  } else {
    indexPath = url.format({
      // if we are not in dev mode load production build file
      protocol: "file:",
      pathname: path.join(__dirname, "dist", "index.html"),
      slashes: true,
    });
  }

  // our new app window will load content depending on the boolean value of the dev variable
  mainWindow.loadURL(indexPath);

  // give our new window the earlier created touchbar
  mainWindow.setTouchBar(touchBar);

  // prevent webpack-dev-server from setting new title
  mainWindow.on("page-title-updated", (e) => e.preventDefault());

  // Don't show until we are ready and loaded
  mainWindow.once("ready-to-show", () => {
    mainWindow.show();

    // Open the DevTools automatically if developing
    if (dev) {
      mainWindow.webContents.openDevTools();
    }
  });

  // Emitted when the window is closed.
  mainWindow.on("closed", () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.

    //tldr: Remove the BrowserWindow instance that we created earlier by setting its value to null when we exit Swell
    mainWindow = null;
  });

  //require menu file
  require("./menu/mainMenu");
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", () => {
  // createLoadingScreen();
  createWindow();
  if (!dev) {
    autoUpdater.checkForUpdates();
  }
});

ipcMain.on("check-for-update", () => {
  //listens to ipcRenderer in UpdatePopUpContainer.jsx
  if (!dev) autoUpdater.checkForUpdates();
});

Upvotes: 1

JozeV
JozeV

Reputation: 696

Well, some quick solution would be if statement

if(process.env.NODE_ENV === 'dev') {
  mainWindow.loadURL('http://localhost:8080/')
} else {
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, '/dist/index.html'),
    protocol: 'file:',
    slashes: true,
  }));
}

Upvotes: 0

Related Questions