You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron-React-Typescript-Webpack打包后动态加载图片异常求助

问题描述

我用Electron + React + Webpack + TypeScript做大学项目,复刻Jeopardy游戏。游戏依赖JSON格式的场景文件运行,场景中包含图片资源,为了避免每次修改场景都重新构建应用,需要实现图片和场景的动态加载。

实际表现
开发环境下,把图片放在指定文件夹,通过require.context按文件名加载完全正常。但应用打包后,所有图片被转移到resources\app\.webpack\renderer\目录,文件名被替换成哈希值(例如f9cbb866db6c9b73d628c76a72d55bc7.jpg),导致原来的动态加载代码失效,图片无法正常显示。

预期表现
打包后的图片保留原文件名,存放在指定的独立文件夹中,这样修改图片或场景中的引用时,无需重新构建应用。

代码示例
加载图片的代码:

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)$/));

渲染图片的代码:

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

1. 修改Webpack配置,保留图片原文件名

调整Webpack中处理图片资源的规则,关闭哈希命名并指定输出目录:

module.exports = {
  // 其他Webpack配置...
  module: {
    rules: [
      // 其他loader规则...
      {
        test: /\.(png|jpe?g|svg)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'assets/[name][ext]' // 保留原文件名,输出到assets子目录
        }
      }
    ]
  }
};

如果使用的是旧版Webpack的file-loader,配置如下:

{
  test: /\.(png|jpe?g|svg)$/i,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: 'assets/[name][ext]',
        outputPath: 'assets/'
      }
    }
  ]
}

2. 配置Electron打包工具(electron-builder)

在项目的package.json中添加build字段,将assets文件夹标记为额外资源,确保打包时直接复制到应用根目录:

{
  "build": {
    "extraResources": [
      {
        "from": "src/assets/",
        "to": "assets/"
      }
    ]
  }
}

这样打包后,图片会被放在应用根目录的assets文件夹下,而非Webpack编译后的内部目录。

3. 调整图片加载逻辑

不再依赖require.context,改为通过Electron的路径API获取资源目录,动态加载图片:

主进程配置

import { app, BrowserWindow, ipcMain } from 'electron';
import { join } from 'path';

let mainWindow: BrowserWindow | null;

app.on('ready', () => {
  mainWindow = new BrowserWindow({
    // 窗口配置...
    webPreferences: {
      nodeIntegration: true, // 若Electron版本低于12,需开启;高版本建议用contextBridge
      contextIsolation: false
    }
  });

  // 向渲染进程发送assets目录路径
  const assetsPath = join(app.getAppPath(), 'assets');
  mainWindow.webContents.send('assets-path', assetsPath);
});

渲染进程代码

import { ipcRenderer } from 'electron';

let assetsPath: string;

// 接收主进程发送的assets路径
ipcRenderer.on('assets-path', (_, path) => {
  assetsPath = path;
});

// 渲染图片时使用本地文件路径
<img src={`file://${assetsPath}/${this._question.imagePath}`} alt="" />

如果是高版本Electron,建议使用contextBridge暴露路径,避免开启nodeIntegration:

// 主进程preload脚本
import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('electronAPI', {
  getAssetsPath: () => ipcRenderer.invoke('get-assets-path')
});

// 主进程
ipcMain.handle('get-assets-path', () => join(app.getAppPath(), 'assets'));

// 渲染进程
const assetsPath = await window.electronAPI.getAssetsPath();
<img src={`file://${assetsPath}/${this._question.imagePath}`} alt="" />

4. 验证动态修改效果

打包完成后,直接替换assets文件夹中的图片或修改JSON场景文件,重启游戏即可生效,无需重新构建应用。

内容的提问来源于stack exchange,提问作者esperor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:50:53