Home > OS >  Loading images dynamically after packaging in Electron-React-Typescipt-Webpack
Loading images dynamically after packaging in Electron-React-Typescipt-Webpack

Time:12-29

Description

I'm creating a replica of the "Jeopardy" game for my college project and chose Electron React Webpack in typescript for it. The game is going to need a scenario (made it in .json) to play and the scenario usually involves some images. Obviously, it's better to load the scenarios dynamically so that I don't need to rebuild whole app for every scenario. Therefore I need to load images dynamically as well.

Actual behaviour

I made everything work in the dev env so that I put the images in a folder and then load them by name via require.context. But after the app is packaged, I find that all of the images were moved to resources\app\.webpack\renderer\ and their names were changed like that: f9cbb866db6c9b73d628c76a72d55bc7.jpg. So, I believe, all of my code was just optimized away so that the images are static now.

Expected behaviour

Images after packaging should stay in some folder with old names so that I can change both the images and references in the scenario.

Code

This is for loading:

function importAll(r: any) {
    let images = {};
    // @ts-ignore
    r.keys().map((item: string, index: any) => { images[item.replace('./', '')] = r(item); });
    return images;
}

// @ts-ignore
const images = importAll(require.context("../assets", false, /\.(png|jpe?g|svg)$/));

This is for representing:

<img src={images[this._question.imagePath].default}></img>

CodePudding user response:

I managed to solve it using some official documentation:

First of all, I changed the way the program loads the images: now there is a button to pick a directory and a button to pick the scenario file. After this is done, the program evaluates content of picked directory:

That is how you pick a directory:

// @ts-ignore
this.assetsDIR = await window.showDirectoryPicker();

This is the evaluation:

// @ts-ignore
for await (const entry of this.props.assetsDIR.values()) {
   entry.getFile().then((val: any) => { 
      this._assets.set(val.name, URL.createObjectURL(val));
   });
}

Now I have all the images' URLs in the map with their names as the keys. After this is done I can just use the name of the image to get it from the map:

<img src={this._assets.get(this._question.imagePath)} />

This seemed perfect, but I ran into a problem with the security policy which didn't let me load the image, so I added this line in the forge.config.ts file:

devContentSecurityPolicy: `default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;`,

The line is from the answer to issue on GitHub: https://github.com/electron/forge/issues/2331 and should be placed like that:

const config: ForgeConfig = {
  packagerConfig: {},
  rebuildConfig: {},
  makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})],
  plugins: [
    new WebpackPlugin({
      devContentSecurityPolicy: `default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;`,
      mainConfig,
      renderer: {
        config: rendererConfig,
        entryPoints: [
          {
            html: './src/index.html',
            js: './src/renderer.ts',
            name: 'main_window',
            preload: {
              js: './src/preload.ts',
            },
          },
        ],
      },
    }),
  ],
};

Also I move assets folder from the workspace folder in User's documents so that the compiler and builder don't see them and don't optimize them. Thanks to @Alexander Leithner for the help

  • Related