Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Loading static assets using electron-forge v6 and the webpack plugin

I spent a few hours chasing down just how to get my static assets (css, fonts, images) to load in an Electron app built using electron-forge v6 (https://www.electronforge.io/) and its webpack plugin (https://www.electronforge.io/config/plugins/webpack) while in development mode. There really isn't any documentation available online, either in the electron-forge documentation or in places like blogs or gists or stackoverflow. So I thought I'd put it down here.

Step 1

Load CopyWebpackPlugin npm i -D copy-webpack-plugin


Step 2

Use the plugin to move your directories into place.

It's important that they be at bare minimum in .webpack/renderer, since that is the root used for localhost

webpack.renderer.config.js

const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const assets = [ 'img', 'css', 'fonts' ]; // asset directories

module.exports = {
  // Put your normal webpack config below here
  module: {
    rules: require('./webpack.rules'),
  },
  plugins: assets.map(asset => {
    return new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, 'src', asset),
        to: path.resolve(__dirname, '.webpack/renderer', asset)
      }
    ]);
  })
};

Step 3

IMPORTANT: Access files with absolute paths

Files without absolute paths do not appear to work, even when everything is relatively placed.

index.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" href="/css/main.css">
  </head>
  <body>
    <img src="/img/img_src.png" />
    <p style="font-family: MyFancyFont, sans-serif;">👆 that's an image!</p>
  </body>
</html>
@sanathks

This comment has been minimized.

Copy link

@sanathks sanathks commented Jun 18, 2019

Thanks for sharing 👍

@pearson1933

This comment has been minimized.

Copy link

@pearson1933 pearson1933 commented Dec 4, 2019

Any advice on how to import static assets in react components?

@Kvisaz

This comment has been minimized.

Copy link

@Kvisaz Kvisaz commented Apr 2, 2020

Thank you.

2020-04-20 - I test relative path for assets in Electron 6.0.0 (Windows 8 x64) - it is working

2020-04-02_131610

@dxinteractive

This comment has been minimized.

Copy link

@dxinteractive dxinteractive commented May 9, 2020

Hi @bbudd, thanks for posting this. Electron forge webpack docs pretty much don't exist for anything deeper than just webpacking some js files. Using version 6.0.0-beta.51

Your approach almost worked for me, but using absolute paths didn't quite work once I run make on OSX. Say if I had an image loaded at /image.png, running start is fine and the image would load from localhost:3000/image.png... but the file produced by make would attempt to load the image from file:///image.png and then fail to find anything. I assume that something in the make process would need to know the file location that corresponds to requests to /, but I can't work out where that happens, or how to intercept requests.

Not sure if you'll reply, but did you have any issues like this?

EDIT: found a lead, I might be right from here on in electron-userland/electron-forge#1592

@dougleville

This comment has been minimized.

Copy link

@dougleville dougleville commented Jun 2, 2020

Thanks for this, I was banging my head on this for a few hours and your post helped me out.

@paragbaxi

This comment has been minimized.

@vasani-arpit

This comment has been minimized.

Copy link

@vasani-arpit vasani-arpit commented Sep 28, 2020

I resolved this without using CopyWebpackPlugin in my case I had issue with FontAwesome. I tried to take solutions from https://stackoverflow.com/questions/33649761/how-do-i-load-font-awesome-using-scss-sass-in-webpack-using-relative-paths but none of them worked.

so, I imported/set the fonts and sass like this in app.scss file

$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "~@fortawesome/fontawesome-free/scss/solid";
@import "~@fortawesome/fontawesome-free/scss/brands";
@import "~@fortawesome/fontawesome-free/scss/fontawesome";

but this wasn't enough for icon to show up the icon was coming up as □ in the web page.

then I found out from the docs that I need to write extra class for it. so I added the following in app.scss

.product {
    @extend %fa-icon;
    @extend .fas;

    &:before {
        content: fa-content($fa-var-store);
    }
}

and it worked !!!

This might be trivial for most of you but I am new to scss and webpack so I thought I should share because others might need it.

@anontyro

This comment has been minimized.

Copy link

@anontyro anontyro commented Nov 9, 2020

This is awesome it worked wonders for me, the only issue I had was using a newer version of copy-webpack-plugin so I had to use a slightly different way to wrap it:

const copyPlugins = assets.map((asset) => {
  return new CopyWebpackPlugin({
    patterns: [{ from: path.resolve(__dirname, 'src', asset), to: asset }],
  });
});

it requires the patterns wrapping now and then it works this was very helpful

@johannesgiani

This comment has been minimized.

Copy link

@johannesgiani johannesgiani commented Apr 6, 2021

Another way could be to use webpack file-loader. I use it to import icons in the main process but that should work for a renderer as well.

Given a /src/renderer.ts/js and /assets/icon.png:

import icon from '../assets/icon.png';

add a rule in webpack.rules.js:

//...
  {
    test: /\.png$/,
    use: {
      loader: 'file-loader',
    }
  }
//...
@nkallen

This comment has been minimized.

Copy link

@nkallen nkallen commented Apr 9, 2021

I've got this working in both dev and prod using file-loader. Here's what I've done:

webpack.renderer.config

rules.push({
    test: /\.(png|jpg|svg|jpeg|gif)$/i,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'img/[name].[ext]',
                publicPath: '../.'
            }
        },
    ],
});

I needed to set publicPath because in prod files are relative to your entryPoints.name (which is "main_window" by default with electron-forge) but the asset files are copied into render not render/main_window

In a random js/ts file:

import porcelain from './img/matcap-porcelain-white.jpg';

And my file is located in '/src/img/matcap-porcelain-white.jpg

@jin-yee

This comment has been minimized.

Copy link

@jin-yee jin-yee commented Apr 20, 2021

Thanks for the help!

It works fine, for npm 7 and later please downgrade the npm to 6 and copyWebpackPlugin please use the following configuration:

 plugins: assets.map(asset => {
    return new CopyWebpackPlugin(
      {
        patterns: [
          {
            from: path.resolve(__dirname, asset),
            to: path.resolve(__dirname, '.webpack/renderer', asset)
          }
        ]
      }
    );
  })
@DK013

This comment has been minimized.

Copy link

@DK013 DK013 commented Jun 19, 2021

I've got this working in both dev and prod using file-loader. Here's what I've done:

webpack.renderer.config

rules.push({
    test: /\.(png|jpg|svg|jpeg|gif)$/i,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'img/[name].[ext]',
                publicPath: '../.'
            }
        },
    ],
});

I needed to set publicPath because in prod files are relative to your entryPoints.name (which is "main_window" by default with electron-forge) but the asset files are copied into render not render/main_window

In a random js/ts file:

import porcelain from './img/matcap-porcelain-white.jpg';

And my file is located in '/src/img/matcap-porcelain-white.jpg

This really did wonders. Thanks Mate !!

@anztrax

This comment has been minimized.

Copy link

@anztrax anztrax commented Aug 20, 2021

This is awesome it worked wonders for me, the only issue I had was using a newer version of copy-webpack-plugin so I had to use a slightly different way to wrap it:

const copyPlugins = assets.map((asset) => {
  return new CopyWebpackPlugin({
    patterns: [{ from: path.resolve(__dirname, 'src', asset), to: asset }],
  });
});

it requires the patterns wrapping now and then it works this was very helpful

thanks bro this works for me 👍

@AlexPasharin

This comment has been minimized.

Copy link

@AlexPasharin AlexPasharin commented Oct 8, 2021

Thanks, you are live saver!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment