Search code examples
typescriptecmascript-6electronecma

How can I import ES user modules (used in renderer process) into Electron main process


https://github.com/Jazzepi/bunny-tracker

I'm working on a small localized database for a nonprofit Ohio House Rabbit Rescue (they're great) and I'm struggling with the deployed version of the Electron application.

When I pass messages from the renderer to the main process often times I pass entire Typescript objects. I would like to use those Typescript definitions in the main process without replicating them by hand. You can see those imports here. Anything that comes from an import starting with ./src/ is pulling from ES "user" modules.

https://github.com/Jazzepi/bunny-tracker/blob/master/main.ts

import { app, BrowserWindow, ipcMain, Menu, MenuItem, MenuItemConstructorOptions, screen, shell } from 'electron';
import * as path from 'path';
import * as url from 'url';
import * as moment from 'moment';
import Bunny from './src/app/entities/Bunny';
import * as sqlite from 'sqlite';
import { Database } from 'sqlite';
import * as log from 'electron-log';
import SQL from 'sql-template-strings';
import IPC_EVENT from './src/app/ipcEvents';
import GENDER from './src/app/entities/Gender';
import RESCUE_TYPE from './src/app/entities/RescueType';

The error I get when running the production-ready app image is this. I get this image in Linux using app-image and in Mac using a dmg.

ohrr@ohrr:~/repos/bunny-tracker$ release/bunny-tracker-2.0.0-x86_64.AppImage 
A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module './src/app/ipcEvents'
Require stack:
- /tmp/.mount_bunny-45gwlx/resources/app.asar/main.js
- 
    at Module._resolveFilename (internal/modules/cjs/loader.js:659:15)
    at Function.Module._resolveFilename (/tmp/.mount_bunny-45gwlx/resources/electron.asar/common/reset-search-paths.js:43:12)
    at Function.Module._load (internal/modules/cjs/loader.js:577:27)
    at Module.require (internal/modules/cjs/loader.js:715:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/tmp/.mount_bunny-45gwlx/resources/app.asar/main.js:50:19)
    at Module._compile (internal/modules/cjs/loader.js:808:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:820:10)
    at Module.load (internal/modules/cjs/loader.js:677:32)

Everything works fine in development mode, but it can't find the modules in production deploys.

I've read about custom protocols at the below links, but they seem to be more about letting you fetch values from custom URL schemas and I want to import stuff not messing around with HTML.

Electron ES6 module import https://github.com/electron/electron/issues/12011 https://gist.github.com/smotaal/f1e6dbb5c0420bfd585874bd29f11c43

Any help with an answer or even just steering me in the right direction would be great! My go to solution if I can't figure this out is symlink the user imported modules into a space the main processor can actually import from.


Solution

  • electron-builder.json had an entry for "!src/" telling it to ignore that folder. I'm sure this made my executable bigger but I don't care about packing up a few extra text files.

    Removing the "!src/", fixed the production runtime problem! Woot.

        "files": [
            "**/*",
            "!**/*.ts",
            "!*.code-workspace",
            "!LICENSE.md",
            "!package.json",
            "!package-lock.json",
            "!src/",
            "!e2e/",
            "!hooks/",
            "!angular.json",
            "!_config.yml",
            "!karma.conf.js",
            "!tsconfig.json",
            "!tslint.json"
        ],