Aurelia v1 + Electron

Hi all,

I’m in the process of setting up an electron project, and I’d like to use Aurelia as the front end framework. Most of my experience is in back end/server-side tech, so bare with me as I navigate webpack, aurelia, electron, and surrounding projects.

I’ve been up and down the docs around bootstrapping aurelia. Making a straight-up aurelia project has gone well, but I’ve had less luck integrating aurelia with electon.

@timfish’s template project, GitHub - timfish/aurelia-electron-webpack: Aurelia Electron app built with Webpack, has been helpful and does work, however once I started digging deeper into aurela features such as routing, I realized that this is using Aurelia 2 which is still in alpha at the moment. As a result, I began downgrading things to the latest Aurelia 1. This is where I’m hitting a bit of a wall.

The core problem that I’m hitting is bootstrapping aurelia so I can start developing modules, view, etc.
Let me start by showing what my package.json looks like:

    {
      "name": "app-name",
      "productName": "product-name",
      "version": "1.0.0",
      "description": "n/a",
      "main": ".webpack/main",
      "license": "",
      "scripts": {
        "start": "electron-forge start",
        "package": "electron-forge package",
        "make": "electron-forge make",
        "publish": "electron-forge publish",
        "lint": "eslint --ext .ts .",
        "test": "jest"
      },
      "keywords": [],
      "author": {
        "name": "Mat Pataki",
        "email": "asd@asd.com"
      },
      "config": {
        "forge": {
          "packagerConfig": {
            "icon": "./build/icon"
          },
          "makers": [
            {
              "name": "@electron-forge/maker-squirrel",
              "config": {
                "name": "aurelia_electron",
                "setupIcon": "./build/icon.ico"
              }
            },
            {
              "name": "@electron-forge/maker-zip",
              "platforms": [
                "darwin"
              ]
            },
            {
              "name": "@electron-forge/maker-deb",
              "config": {}
            },
            {
              "name": "@electron-forge/maker-rpm",
              "config": {}
            }
          ],
          "plugins": [
            [
              "@electron-forge/plugin-webpack",
              {
                "mainConfig": "./build/webpack.main.config.js",
                "renderer": {
                  "config": "./build/webpack.renderer.config.js",
                  "entryPoints": [
                    {
                      "html": "./src/renderer/index.html",
                      "js": "./src/renderer/index.ts",
                      "name": "main_window",
                      "preload": {
                        "js": "./src/main/preload.ts"
                      }
                    }
                  ]
                }
              }
            ]
          ]
        }
      },
      "devDependencies": {
        "@aurelia/webpack-loader": "dev",
        "@electron-forge/cli": "6.0.0-beta.54",
        "@electron-forge/maker-deb": "6.0.0-beta.54",
        "@electron-forge/maker-rpm": "6.0.0-beta.54",
        "@electron-forge/maker-squirrel": "6.0.0-beta.54",
        "@electron-forge/maker-zip": "6.0.0-beta.54",
        "@electron-forge/plugin-webpack": "6.0.0-beta.54",
        "@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
        "@types/jest": "^26.0.23",
        "@types/kafkajs": "^1.9.0",
        "@types/node": "^12.19.7",
        "@types/stompjs": "^2.3.4",
        "@types/wav": "^1.0.0",
        "@types/ws": "^7.4.4",
        "@typescript-eslint/eslint-plugin": "^4.8.2",
        "@typescript-eslint/parser": "^4.8.2",
        "aurelia-cli": "^2.0.3",
        "aurelia-loader-nodejs": "^1.1.0",
        "aurelia-pal-nodejs": "^2.0.0",
        "aurelia-testing": "^1.0.0",
        "aurelia-webpack-plugin": "^4.0.0",
        "css-loader": "^5.0.1",
        "electron": "11.0.3",
        "eslint": "^7.14.0",
        "eslint-plugin-import": "^2.22.1",
        "fork-ts-checker-webpack-plugin": "^6.0.4",
        "jest": "^26.6.3",
        "node-loader": "^1.0.2",
        "style-loader": "^2.0.0",
        "testcontainers": "^7.11.0",
        "ts-jest": "^26.5.6",
        "ts-loader": "^8.0.11",
        "typescript": "^4.1.2"
      },
      "dependencies": {
        "aurelia-animator-css": "^1.0.4",
        "aurelia-bootstrapper": "^2.3.3",
        "aurelia-fetch-client": "^1.8.2",
        "bulma": "^0.9.2",
        "electron-squirrel-startup": "^1.0.0",
        "jsonfile": "^6.1.0",
        "kafkajs": "1.15.0",
        "nano": "9.0.3",
        "stompjs": "2.3.3",
        "wav": "1.0.2",
        "ws": "7.4.4"
      }
    }

The template from timfish has the webpack config split between a few files, I believe to support both electron’s main and renderer threads. Here’s the renderer webpack config:

    const rules = require("./webpack.rules");
    const plugins = require("./webpack.plugins");

    rules.push(
      { test: /\.css$/i, use: ["style-loader", "css-loader"] },
      {
        test: /\.ts$/i,
        use: ["ts-loader", "@aurelia/webpack-loader"],
        exclude: /node_modules/,
      },
      {
        test: /\.html$/i,
        use: "@aurelia/webpack-loader",
        exclude: /node_modules/,
      }
    );

    module.exports = {
      module: {
        rules,
      },
      plugins: plugins,
      resolve: {
        extensions: [".js", ".ts", ".css", ".json"],
      },
    };

And here’s the webpack rules that are imported above:

    module.exports = [
      // Add support for native node modules
      {
        test: /\.node$/,
        use: 'node-loader',
      },
      {
        test: /\.(m?js|node)$/,
        parser: { amd: false },
        use: {
          loader: '@marshallofsound/webpack-asset-relocator-loader',
          options: {
            outputAssetBase: 'native_modules',
          },
        },
      },
      {
        test: /\.tsx?$/,
        exclude: /(node_modules|\.webpack)/,
        use: {
          loader: 'ts-loader',
          options: {
            transpileOnly: true
          }
        }
      },
    ];

I’ve been trying both the declarative manual approach. Here’s my index.html now:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>App</title>
      </head>

      <body aurelia-app="main"></body>
    </html>

This is where the first issue arises at runtime. Based on the docs and test projects I’ve worked through, I’d expect src/renderer/main.ts to be called. This module contains the configure(aurelia: Aurelia) ... function which I would use to configure and start up aurelia, and from there, load an app module which would setup routes, etc. None of this code is running. I suspect a webpack configuration issue but I’m not sure.

What does run is the src/renderer/index.ts file. Failing the previous, preferred approach, I have tried to manually bootstrap aurelia like this:

import { bootstrap } from 'aurelia-bootstrapper';
import { Aurelia } from 'aurelia-framework';
import { App } from './app';

bootstrap(async (aurelia: Aurelia) => {
    console.log("bootstrapping aurelia manually...");
    aurelia.use.standardConfiguration();

    await aurelia.start();
    return aurelia.setRoot(App, document.body);
});

The first line, where I’m importing bootstrap throws an exception bootstrap:789 Uncaught (in promise) TypeError: Cannot read property 'call' of undefined. I’m not sure what to do with this just yet.

Again, I suspect my issue lies somewhere within my webpack blindspot, but having been grinding on it for some hours, I’d be very appreciative if anyone else’s keen eye and spot my mistake and point me in the right direction.

Thanks in advance!
Mat

We’ve got a closed source Aurelia v1 Electron app and I remember it being tricky to get working but it was a long time ago. We have it manually bootstrapped and the following in the Webpack config:

      new AureliaPlugin({
        aureliaApp: undefined,
        noWebpackLoader: true,
      }),

If this doesn’t work and you share a repository I’ll be happy to take a look!

1 Like

Thank-you @timfish! I’ll report back