Seppo
Seppo

Reputation: 1

Electron - Unable to Load Local Resource Error for a File in Renderer Process

I'm completely new to Electron, and am currently developing an application (using Electron-Vite + React) and encountering an issue related to loading a local resource (specifically a file named video.html) into a secondary BrowserWindow. While I can load the index.html file without any problems using Electron's loadURL function, I consistently face the "Unable to load local resource" error when attempting to load video.html.

The app is working fine in development environment using npm run dev, but as soon as I preview the production with npm start the second BrowserWindow throws an error at me.

Here is my index.js main process file

//index.js

import { app, shell, BrowserWindow, ipcMain } from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'

let mainWindow, secondWindow

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 900,
    height: 670,
    show: false,
    autoHideMenuBar: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      contextIsolation: true,
      enableRemoteModule: false,
      webSecurity: true
    }
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/index.html`)
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }
}

function createSecondWindow() {
  secondWindow = new BrowserWindow({
    width: 1080,
    height: 720,
    autoHideMenuBar: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      contextIsolation: true,
      enableRemoteModule: false,
      webSecurity: true
    }
  })

  secondWindow.on("ready-to-show", () => {
    secondWindow.show();
  });

  secondWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    secondWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/video.html`)
  } else {
    secondWindow.loadFile(join(__dirname, '../renderer/video.html'));
  }
}


app.whenReady().then(() => {
  electronApp.setAppUserModelId('com.electron')

  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  createWindow()
  createSecondWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

ipcMain.on("play-video", (event, videoPath) => {
  if (secondWindow) {
    secondWindow.webContents.send("start-video", videoPath);
  }
})

Electron.vite.config.js

import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  main: {
    plugins: [externalizeDepsPlugin()]
  },
  preload: {
    plugins: [externalizeDepsPlugin()]
  },
  renderer: {
    resolve: {
      alias: {
        '@renderer': resolve('src/renderer/src')
      }
    },
    plugins: [react()]
  },
})

The structure of my application is as follows:

├── build
├── out
└─┬ src
  ├── preload
  ├─┬ main
  │ └── index.js
  ├─┬ renderer
  │ ├── index.html
  │ ├── video.html
  │ ├── public
  │ └─┬ src
  │   ├── App.jsx (React component used in main.jsx)
  │   ├── VideoApp.jsx (React component used in video.jsx)
  │   ├── main.jsx (src for index.html)
  │   └── video.jsx (src for video.html)
  ├── electron.vite.config.js
  └── package.json

Could someone guide me on how to load video.html into a BrowserWindow without encountering this "Unable to load local resource" error?

What I've Tried:

  1. Using loadFile and loadURL: I attempted loading the file directly into the window using Electron's loadFile and loadURL methods. However, both approaches resulted in the same error.

  2. Adjusting Security Settings: I ensured that my Electron security settings (webSecurity, etc.) were correctly configured but still encountered the same problem.

Upvotes: 0

Views: 617

Answers (1)

Seppo
Seppo

Reputation: 1

It appears that I had missed one part of the documentation in my search of a solution. For now, the solution seems to be just to modify my config file:

import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  main: {
    plugins: [externalizeDepsPlugin()]
  },
  preload: {
    plugins: [externalizeDepsPlugin()]
  },
  renderer: {
    //ADDED THE BUILD.ROLLUPOPTIONS.INPUT FOR BOTH RENDERER PROCESSES
    build: {
      rollupOptions: {
        input: {
          browser: resolve(__dirname, 'src/renderer/index.html'),
          webview: resolve(__dirname, 'src/renderer/video.html')
        }
      }
    },
    resolve: {
      alias: {
        '@renderer': resolve('src/renderer/src')
      }
    },
    plugins: [react()]
  },
})

With this modification I was able to get the secondWindow to work in both development and production. Now I just need to troubleshoot the ipcMain as the communication between the two windows breaks down after these changes.

Upvotes: 0

Related Questions