DEV Community

Masui Masanori
Masui Masanori

Posted on

3

[Windows] Try Electron 2

Intro

This time, I will try using Electron on Windows.

Environments

  • Windows 11 Pro Insider Preview ver.22H2
  • Node.js ver.18.12.1

package.json

{
  "name": "electron-sample",
  "version": "1.0.0",
  "description": "",
  "main": "views/js/main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make"
  },
  "author": "Masui Masanori",
  "license": "MIT",
  "devDependencies": {
    "@electron-forge/cli": "^6.0.4",
    "@electron-forge/maker-deb": "^6.0.4",
    "@electron-forge/maker-rpm": "^6.0.4",
    "@electron-forge/maker-squirrel": "^6.0.4",
    "@electron-forge/maker-zip": "^6.0.4",
    "@typescript-eslint/eslint-plugin": "^5.46.0",
    "@typescript-eslint/parser": "^5.46.0",
    "electron": "^22.0.0",
    "eslint": "^8.29.0",
    "ts-loader": "^9.4.2",
    "typescript": "^4.9.4",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1"
  },
  "dependencies": {
    "electron-log": "^4.4.8",
    "electron-squirrel-startup": "^1.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Unable to load preload script

First, I wrote an Electron application with these code below.

global.d.ts

declare global {
    interface Window {
        myapi: Sandbox
    };
}
export interface Sandbox {
    logDebug: (callFrom: string, message: string) => void,
    logError: (callFrom: string, message: string) => void
};
Enter fullscreen mode Exit fullscreen mode

[Electron side] main.ts

import { app, BrowserWindow, ipcMain } from 'electron';
import * as log from "electron-log";
import * as path from 'path';

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    }
  });
  win.loadFile('./views/index.html');
}
app.whenReady().then(() => {
  createWindow();
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
ipcMain.handle("debugLog", (_, message: string) => {
  log.debug(message);
});
Enter fullscreen mode Exit fullscreen mode

[Electron side] preload.ts

import { ipcRenderer, contextBridge } from 'electron';
import * as log from 'electron-log';

window.addEventListener('DOMContentLoaded', () => {
    console.log("Loaded");
});
contextBridge.exposeInMainWorld('myapi', {
    logDebug: async (callFrom: string, message: string) => await ipcRenderer.invoke("debugLog", `[${callFrom}] ${message}`),
    logError: (callFrom: string, message: string) => log.error(`[${callFrom}] ${message}`)
  }
);
Enter fullscreen mode Exit fullscreen mode

[Client side] main.page.ts

export function init() {
    window.myapi.logDebug("main.page", "Hello");
    window.myapi.logError("main.page", "Hello Error");
}
Enter fullscreen mode Exit fullscreen mode

But I got an exception on client-side.

Unable to load preload script: C:\Users\example\OneDrive\Documents\workspace\ElectronSample\out\electron-sample-win32-x64\resources\app\views\js\preload.js   VM4 sandbox_bundle:2

Error: module not found: electron-log
    at preloadRequire (VM4 sandbox_bundle:2:82516)
    at <anonymous>:37:26
    at runPreloadScript (VM4 sandbox_bundle:2:83356)
    at VM4 sandbox_bundle:2:83615
    at VM4 sandbox_bundle:2:83770
    at ___electron_webpack_init__ (VM4 sandbox_bundle:2:83774)
    at VM4 sandbox_bundle:2:83897   VM4 sandbox_bundle:2
Failed to load resource: net::ERR_FILE_NOT_FOUND    main.page.js:1
Enter fullscreen mode Exit fullscreen mode

In this situation、I have to set "nodeIntegration" enabled.

main.ts

...
function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      preload: path.join(__dirname, 'preload.js'),
    }
  });
  win.loadFile('./views/index.html');
}
...
Enter fullscreen mode Exit fullscreen mode

I have to write "nodeIntegration" before "preload".
Otherwise I will get the same error.

This is because I use "electron-log" in "preload.ts".
If I remove it, I also can write like below.

main.ts

...
function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
    }
  });
  win.loadFile('./views/index.html');
}
...
Enter fullscreen mode Exit fullscreen mode

Adding extra resource files

I can load external files like below.

But the files aren't output by "electron-forge make".
To do this, I should add "extraResource" into forge.config.js.

appSettings.json

{
    "message": "Hello world!"
}
Enter fullscreen mode Exit fullscreen mode

forge.config.js

module.exports = {
  packagerConfig: {
    "extraResource": [
      "./appSettings.json"
    ]
  },
  rebuildConfig: {},
  makers: [
    {
      name: '@electron-forge/maker-squirrel',
      config: {
        authors: 'Masui Masanori',
        description: 'WebRTC sample'
      },
    },
    {
      name: '@electron-forge/maker-zip',
      platforms: ['darwin'],
    },
    {
      name: '@electron-forge/maker-deb',
      config: {},
    },
    {
      name: '@electron-forge/maker-rpm',
      config: {},
    },
  ],
};
Enter fullscreen mode Exit fullscreen mode

The file will be output into "{ProjectDirectory}/out/electron-sample-win32-x64/resources".
So I can read it by "process.resourcesPath".

main.ts

...
export async function load() {
  const fileData = await fs.promises.readFile(path.join(process.resourcesPath, "appSettings.json"), {
      encoding: 'utf-8'
  });
  log.debug(JSON.parse(fileData));
}
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more