Clemens Dinkel
Clemens Dinkel

Reputation: 344

How do I make webpack also load preload.js when starting a dev server using electron-forge

Problem

For my Electron app created with npx create-electron-app <appname> --template=typescript-webpack the user needs to be able to open a new BrowserWindow instance (not the one you create with window.open()) on click of a button.

Since the initiative to open a new Window is coming from the frontend/renderer of the app, I have to use the ipcRenderer in order send a message to the main process in which then I can listen for the message in order to open a new BrowserWindow.

However I fail at telling webpack to also bundle the the required preload.js along with index.js, when starting the app via yarn electron-forge start. The .webpack folder structure should look like this:

main
  index.js (main)
  preload.js
renderer
  main_window
    index.html
    index.js (renderer)
  ...

But the preload.js is missing which leads to an error in the console and the button not working.

When I manually copy the preload.js to the correct place (.webpack/main) after starting the devserver everything works which is nice to see, however it's not a solution. Pretty sure something is wrong in my webpack configurations.

Setup

The original index.ts and preload.js sit next to each other in the src folder

I'm a complete newbie when it comes to webpack or other comparable services so I have no idea what's wrong in my automatically generated webpack configurations. This is how they look like:

webpack.main.config.js

module.exports = {
  entry: "./src/index.ts",
  module: {
    rules: require("./webpack.rules"),
  },
  resolve: {
    extensions: [".js", ".ts", ".jsx", ".tsx", ".css", ".json"],
  },
};

webpack.renderer.config.js

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

rules.push({
  test: /\.css$/,
  use: [
    { loader: "style-loader" },
    { loader: "css-loader" },
    { loader: "postcss-loader" },
  ],
});

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

webpack.plugins.js

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = [new ForkTsCheckerWebpackPlugin()];

webpack.rules.js

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

If needed I can provide the source code for index.ts and preload.js and the file calling the method from the renderer process. I'm pretty sure though they're not the issue, since everything works, when I manually inject the preload.js into .webpack/main after starting.

Upvotes: 0

Views: 3552

Answers (2)

testing
testing

Reputation: 11

For future reference, in total, it looks like you might need to do two things in order to get the preload script to work:

  1. Use global variables in the index.ts file, just as Anirudh suggested:
// stuff...

// specifically for typescript: 
// the first declare should have been automatically generated
declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string; // add this

// other stuff...

const createWindow = (): void => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    height: 600,
    width: 800,
    webPreferences: {
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, // change this
    },
  });
  // and all the other things in index.ts.
}
  1. After that, you might also need to change your package.json, just as Clemens suggested. This took a little bit more research, but the documentation for the webpack plugin can be found here, wherein all the variables can be manipulated via the package.json entry for config > forge > plugins. Thus, the critical part there should look something like this:
        [
          "@electron-forge/plugin-webpack",
          {
            "mainConfig": "./webpack.main.config.js",
            "renderer": {
              "config": "./webpack.renderer.config.js",
              "entryPoints": [
                {
                  "html": "./src/index.html",
                  "js": "./src/renderer.ts",
                  "name": "main_window",

                  // -------------- change starts here --------------
                  "preload": {
                    "js": "./src/preload.ts" // or wherever your preload script is written
                  }
                  // --------------  change ends here  --------------
                }
              ]
            }
          }
        ]

I'm also a beginner at javascript, so I'm not entirely sure if it's correct. Hope it helps!

Upvotes: 1

Anirudh santhosh
Anirudh santhosh

Reputation: 461

you can use the magic global variables which webpack and electron forge provides read more about this at magic global variables

hope below code help you:

for creating a browser window
and the preload : MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY property will help to bundle preload.js to pack with other render scripts const mainWindow = new BrowserWindow({ width: 1000, height: 900, webPreferences:{ preload : MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, } });

for loading the index.html of the app.

mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);

Upvotes: 1

Related Questions