【问题标题】:Can't use static files in electron forge不能在电子锻造中使用静态文件
【发布时间】:2020-07-05 10:54:35
【问题描述】:

我无法始终如一地在 Electron 中加载图像。我正在使用 Electron Forge 和 webpack 模板 https://www.electronforge.io/templates/webpack-template

我的 src 目录如下所示:

├── images
│   └── black.png
├── index.css
├── index.html
├── index.js
├── main.js
└── renderer.js

我的 HTML 代码如下所示:

<img src="images/black.png">

我正在使用copy-webpack-plugin 复制images 目录。

在开发中运行时 (npm run start),开发服务器的根目录是 .webpack/renderer,因此图像会加载。在生产环境 (npm run package) 中运行时,HTML 文件正在从文件系统打开,因此图像标签试图访问 .webpack/renderer/main_window/images,这是错误的位置并且它不会加载。

我已经通过以下方式让它在开发和生产中工作:

<img src="../images/black.png">

这是一种 hacky 方式,并且与文件存储在 src 目录中的方式不正确。这应该很简单,但我花了好几个小时试图弄清楚,但还没有真正的解决方案。

我已经在这些链接中看到了一个解决方案,但是如果不将“../”放在路径前面,我无法让它在开发和生产中工作。

https://github.com/electron-userland/electron-forge/issues/1196

https://github.com/electron-userland/electron-forge/issues/941

我能想出几个办法来解决这个问题:

  1. webpack 配置需要通过某种环境变量或标志知道它是在开发还是生产中运行,并更改 copy-webpack-plugin 的“to”路径。
  2. 将开发服务器更改为运行,使其根为.webpack/renderer/main_window

我看到了将图像导入renderer.js 的建议,但我有几千张图像。我应该这样做吗?

import './images/1.png';
import './images/2.png';
import './images/3.png';
// ...
import './images/1000.png';

有没有办法以编程方式导入?比如:

let imageMap = {};
for (let i of Iter.range(1, 1001)) {
  let image = import(`./images/${i}.png`);
  imageMap[i] = image;
}

那我该如何在 HTML 中引用它呢?不用DOM编辑代码也能做到吗?

我不想将我的图像导入我的 JavaScript 文件并通过 webpack 加载器运行它们。我只想以一种在开发和生产中都可以使用的方式从我的 HTML 代码中引用静态文件。

我还有一个 5MB 的 JSON 文件,我需要使用 fetch() 访问它。我尝试通过加载器导入它,但构建过程花费了 5 分钟以上,我将其杀死。

加载静态文件是制作网页的基本部分,应该是项目模板的一部分,除非我遗漏了一些非常明显的东西。

【问题讨论】:

  • 我遇到了类似的问题......并且刚刚放弃了 webpack。这解决了很多问题,就我而言,我不需要其中的 webpack 部分。只会引起问题。对于前端,可能会使用 React 或 Angular 等单页技术,然后根据他们的平台工具对它们进行 webpack。 Webpack + Node.js 似乎总是解决难以解决的大问题。
  • Webpack 不是问题的原因。之所以会出现这个问题,是因为制作 electron forge 的人在开发模式下设置了 webpack 开发服务器,而在生产模式下根本没有服务器,只有静态文件。 electron forge 本身提供的配置是错误的。

标签: webpack electron-forge


【解决方案1】:

我能够通过在生产环境中运行一个为renderer 目录提供服务的静态 Express 服务器来解决这个问题。我对图像标签使用绝对路径 (/images/foo.png),并且可以访问我的静态文件。

webpack.renderer.config.js

const path = require('path');
const rules = require('./webpack.rules');
const CopyWebpackPlugin = require('copy-webpack-plugin');

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

module.exports = {
  module: {
    rules: [
      ...rules,
    ],
  },
  plugins: [
    ...copyPlugins,
  ]
};

main.js

import { app, BrowserWindow } from 'electron';
import path from 'path';
import express from 'express';

function isDebug() {
  return process.env.npm_lifecycle_event === 'start';
}

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
  app.quit();
}

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 740,
  });

  if (isDebug()) {
    // Create the browser window.
    mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
    mainWindow.webContents.openDevTools();
  } else {
    const exApp = express();
    exApp.use(express.static(path.resolve(__dirname, '..', 'renderer')));
    const server = exApp.listen(0, () => {
      console.log(`port is ${server.address().port}`);
      mainWindow.loadURL(`http://localhost:${server.address().port}/main_window/`);
    });
  }
};

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

【讨论】:

    【解决方案2】:

    我也有在生产中加载静态文件的问题,但我想我找到了解决它的方法。我们可以使用electron-is-dev 包来检查应用程序是否在生产环境中运行,然后我们可以为我们的文件指定不同的路径。就我而言,我在加载应用程序图标时遇到问题,这是解决问题的方法:

    import isDev from "electron-is-dev";
    
    const createWindow = () => {
      // Create the browser window.
      const mainWindow = new BrowserWindow({
        height: 1000,
        width: 1000,
        webPreferences: {
          nodeIntegration: true,
        },
      });
    
      mainWindow.setIcon(
        isDev
          ? path.join(__dirname, "../../src/assets/app.ico")
          : path.join(__dirname, "./assets/app.ico")
      );
    };
    

    【讨论】:

      【解决方案3】:

      我找到了一个 hacky 方法...
      我使用 webpack url-loader,这是我的 webpack.renderer.config.js 的一部分

      {
        module: {
          rules: [
            {
              test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
              use: {
                loader: 'url-loader',
                options: {
                  limit: 20 * 1024, // 20Kb
                  outputPath: 'imgs',
                  publicPath: '../imgs',
                  name: '[name]-[hash:6].[ext]',
                  esModule: false
                }
              }
            }
          ]
        }
      }
      

      我只是将outputPath 的父路径放在publicPath 中,它可以在我的应用程序中使用!

      【讨论】:

        猜你喜欢
        • 2020-03-13
        • 2019-02-20
        • 2018-02-06
        • 2019-07-15
        • 2020-04-08
        • 1970-01-01
        • 2021-08-09
        • 2021-06-28
        • 2017-12-27
        相关资源
        最近更新 更多