Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compile a preload script w/ webpack in Electron?

Electron 1.6.5, Webpack 2.4.1

I'm using electron-react-boilerplate with a webview component. I inject a preload script into the webview that does something like this:

const { ipcRenderer } = require('electron');
const doSomething = require('./utils/do-some-thing.js');

document.addEventListener('DOMContentLoaded', event => {
   doSomeThing()

  // tell scraper to get started
  ipcRenderer.sendToHost('THING IS DONE', [{ url: document.URL }]);
});

webview needs this script passed as a file:// path like so:

       <webview
        preload={'./some/folder/preload.js''}
        {...props}
      />

The problem is that my webpack setup doesn't transpile preload.js because it isn't explicitly called via require(). Then, when I build the app, the path ./some/folder/ doesn't exist.

I've tried setting webpack to create a second compiled script like so:

entry: [
    'babel-polyfill',
    './app/index',
    './some/folder/preload.js'
  ],

  output: {
    path: path.join(__dirname, 'app/dist'),
    publicPath: '../dist/'
  },

But this leads to a JavaScript heap out of memory error, which leads me to believe this isn't correct.

Also: wouldn't this approach duplicate electron in the ./dist folder since it's require()'d by both preload.js and index.js ?

like image 272
Brandon Avatar asked May 05 '17 04:05

Brandon


People also ask

Is Webpack necessary for electron?

It is not webpack which is used in electron. The require function is part of the node. js, which is the base for electron. But as long as webpack is also availiable as a node module (https://www.npmjs.com/package/webpack) it is also possible to use webpack with electron.


2 Answers

You could use the electron-main and electron-preload configurations of webpack:

const path = require('path');

module.exports = [
  {
    entry: './src/index.js',
    target: 'electron-main',
    output: {
      path: path.join(__dirname, 'dist'),
      filename: 'index.bundled.js'
    },
    node: {
        __dirname: false,
    }
  },
  {
    entry: './src/preload.js',
    target: 'electron-preload',
    output: {
      path: path.join(__dirname, 'dist'),
      filename: 'preload.bundled.js'
    }
  },
]

You get two bundles after building, but Electron is not in either of them, so no duplicates.

Notice the __dirname: false, which is required since otherwise webpack replaces __dirname always replaced by / by webpack, leading to an unexpected behaviour in almost all cases (see here for further information, should be false by default, but wasn't for me).

like image 153
Yannic Avatar answered Sep 22 '22 08:09

Yannic


We had a similar issue where we had several preload scripts instead of one. Our solution was to use the CopyPlugin. So for us, the config looks like this:

const CopyPlugin = require("copy-webpack-plugin");

plugins.push(new CopyPlugin([{ from: "src/container-with-scripts/", to: "preloadScripts/" }]));

module.exports = {
  module: { rules }, // imported from elsewhere
  target: "electron-renderer",
  node: { global: true },
  plugins,
  resolve: {
    extensions: [".js", ".ts", ".jsx", ".tsx", ".css", ".scss"]
  }
};

So we just take the folder containing all our scripts and copy them to the autogenerated .webpack folder.

like image 31
Gh05d Avatar answered Sep 22 '22 08:09

Gh05d