Electron app images in build assets directory giving 404, even after base href ./?

Discussão em 'Angular' iniciado por Shatoria Giles, Julho 8, 2025.

  1. I am working on a production app so I can't reveal too much.

    I am turning an angular 19 app into an electron app. It was going fine until the images gave a 404 error when the electron app was finished building

    In the build folder there are many html files and images that load smoothly.

    The issue comes from the images in build/assets folder. They are not loading. For some reason they map to something like this file:///C:/assets/images/homepage/folder-disabled.svg instead of the needed result file:///C:/desktop/project/project/assets/images/homepage/folder-disabled.svg.

    My manager has made the build folder for production named this due to there being multiple projects in a single repository (monorepo).

    project structure

    Divs that are in the asset folder don't work and give 404 while mapping to this.

    file:///C:/assets/images/homepage/folder-disabled.svg

    I have tried many things:

    1. electron protocols that look kind of like this:

    app.whenReady().then(() => {
    protocol.handle('my-protocol', async (request) => {
    const filePath = request.url.replace(`my-protocol://`, 'file://');
    return net.fetch(filePath);
    });
    createWindow();
    });

    1. base hrefs. The app only works if the href is at ./

    index.html: <base href="/">

    3.I have tried asset blobs

    {
    "glob": "**/*",
    "input": "public"
    },
    {
    "glob": "**/*",
    "input": "src/assets",
    "output": "/assets"
    }


    4.I have tried web security protocols webPreferences: { webSecurity: false }

    Minimal reproduceable example

    electron.js

    const { app, BrowserWindow, protocol } = require('electron')
    const url = require('url');
    const path = require('path');

    let mainWindow;


    function createWindow() {
    mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
    nodeIntegration: true // Enable Node.js integration in the renderer process
    }
    });

    // Load the Angular application's index.html
    // dist/actianone-ui-console/index.html
    mainWindow.loadURL(
    url.format({
    pathname: path.join(__dirname, `./dist-avprod/index.html`), // Adjust path to your Angular build output
    protocol: 'file:',
    slashes: true
    })
    );

    // Open DevTools (optional)
    // mainWindow.webContents.openDevTools();

    mainWindow.on('closed', () => {
    mainWindow = null;
    });
    }

    // app.on('ready', createWindow).then(showNotification);
    app.whenReady()
    app.whenReady().then(() => {
    protocol.interceptFileProtocol('file', (req, callback) => {
    const url = req.url.substr(7); // strip 'file://'
    let normalizedPath = url;

    if (url.startsWith('/assets')) {
    normalizedPath = path.join(__dirname, 'dist-avprod', url);
    }

    callback({ path: normalizedPath });
    });

    createWindow();
    });


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

    app.on('activate', () => {
    if (mainWindow === null) {
    createWindow();
    }
    });



    Angular.json

    "architect": {
    "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
    "baseHref": "./",
    "outputPath": "dist/actianone-ui-console",
    "index": "src/index.html",
    "main": "src/main.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "src/tsconfig.app.json",
    "assets": [
    "src/favicon.ico",
    "./src/assets/images",
    "src/assets/actian",
    "src/assets/config"
    ],
    }
    }
    }

    Continue reading...

Compartilhe esta Página