Creating multiple Preload files in electron (One for each page)

Viewed 756

I am creating my first Electron app and I got the first page of the form done. Now this app is not a SPA, so I have about 3-4 different pages, and page leads to another.

To allow proper code organization I want to keep a separate Preload file for each client facing page, unfortunately I am not able to get this right.

I've tried setting the Preload file again on the BrowserWindow object (Yes, I want to use only one instance of the BrowserWindow and load all my files there), but that doesn't work. I still get the functions from the old preload only.

There's a method called setPreloads on the session object of the WebContents, but that doesn't seem to work either as my ContextBridge doesn't have the new functions even then.

What is a good solution to this?

1 Answers

I finally made, what I think is an elegant solution with a little tip from @pushkin. location.href can be used to detect the file that is being loaded in the browser.

My goals were

  1. Properly organize the preload code, so that the codes for different frontend files do not overlap with each other.
  2. Only expose the preload code that's required to run the current frontend file in the main world.

I don't know if the system I implemented is perfect, but here's how it goes.

Create a separate preload.js file for each front-end page. Ex: index_preload.js

    const { contextBridge, ipcMain, ipcRenderer } = require('electron')
    const nodemon = require('nodemon')
    const fs = require('fs');
    const path = require('path')
    const open = require('open')
    
    
    indexBridge = {
        openSecret: () => {
            open('https://adplify.in/user/secret')
        },
        loadPages: () => {
            ipcRenderer.send('loadPages', "pagelist");
        }
    }

module.exports = indexBridge;

I am exporting the entire functionality of the preload file in an object.

Then in the main preload file

const indexBridge = require("./viewscripts/home/index_preload");
const pagesBridge = require("./viewscripts/home/pageslist_preload");
const { contextBridge, ipcMain, ipcRenderer } = require('electron')
const nodemon = require('nodemon')

console.log(`Location: ${location.href}`);

if (location.href.endsWith("index.html"))
  Bridge = indexBridge;
else if (location.href.endsWith("pageslist.html"))
  Bridge = pagesBridge;

contextBridge.exposeInMainWorld("Bridge", Bridge);

Only one Bridge object is exposed for every page, and what the Bridge holds depends on which page the user is on. I can happily put the Preload code for every page in a separate file.

Overall, this does what I wanted very nicely.

Thanks @pushkin

Related