不能在电子锻造中使用静态文件
Can't use static files in electron forge
我无法始终如一地在 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
目录。
当 运行ning 处于开发阶段 (npm run start
) 时,开发服务器的根目录是 .webpack/renderer
,因此图像会加载。当 运行ning 在生产 (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
我可以想出几种方法来解决这个问题:
- webpack 配置需要通过某种环境变量或标志知道它是 运行ning 在开发还是生产中,并更改 copy-webpack-plugin 的 "to" 路径。
- 将开发服务器更改为 运行 所以它的根是
.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 多分钟,我将其终止。
加载静态文件是制作网页的基本部分,应该是项目模板的一部分,除非我遗漏了一些非常明显的东西。
我能够通过 运行 生产中服务于 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);
我在生产中也遇到了加载静态文件的问题,但我想我找到了解决它的方法。我们可以使用 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")
);
};
我找到了一个 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
中,它在我的应用程序中有效!
我无法始终如一地在 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
目录。
当 运行ning 处于开发阶段 (npm run start
) 时,开发服务器的根目录是 .webpack/renderer
,因此图像会加载。当 运行ning 在生产 (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
我可以想出几种方法来解决这个问题:
- webpack 配置需要通过某种环境变量或标志知道它是 运行ning 在开发还是生产中,并更改 copy-webpack-plugin 的 "to" 路径。
- 将开发服务器更改为 运行 所以它的根是
.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 多分钟,我将其终止。
加载静态文件是制作网页的基本部分,应该是项目模板的一部分,除非我遗漏了一些非常明显的东西。
我能够通过 运行 生产中服务于 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);
我在生产中也遇到了加载静态文件的问题,但我想我找到了解决它的方法。我们可以使用 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")
);
};
我找到了一个 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
中,它在我的应用程序中有效!