我正在尝试使用React创建一个单页应用程序,并将该应用程序打包以用于电子生产。 该页面是关于创建“交货单”的,交货单应该能够打印并保存为Pdf文档。
值得庆幸的是,我已经通过React-Pdf库完成并管理了该任务。
但是我在创建的React-App的生产构建以及将应用包装为电子产品方面遇到一些问题。
我已经进行了一些研究,找到了一些文档,该文档介绍了如何使用Electron打包React-App,发现打包带有JS库的App与打包不使用JS库的App有点不同。
因此,我已经完成了文档中提到的操作,并修改了package.json,在公共目录中创建了一个名为electron.js的新文件。
package.json现在看起来像这样:
{
"name": "uebung_eins",
"version": "0.1.0",
"description": "Creating first Electron App",
"private": true,
"author": {
"name": "Max Mustermann",
"email": "max.mustermann@gmx.at",
"url": "https://maxmustermann.com"
},
"homepage": "./",
"build": {
"appId": "com.my-website.my-app",
"productName": "Hoch - und Tiefbau GmbH",
"copyright": "Copyright � 2019 ${author}",
"mac": {
"category": "public.app-category.utilities"
},
"files": [
"build/**/*",
"node_modules/**/*"
],
"directories": {
"buildResources": "assets"
}
},
"dependencies": {
"@react-pdf/renderer": "^1.6.8",
"bootstrap": "^4.4.1",
"cross-env": "^6.0.3",
"electron-is-dev": "^1.1.0",
"mdbreact": "^4.23.0",
"react": "^16.12.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.2.0"
},
"main": "public/electron.js",
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"electron-dev": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"",
"postinstall": "electron-builder install-app-deps",
"preelectron-pack": "yarn build",
"electron-pack": "electron-builder -w"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@rescripts/cli": "^0.0.13",
"@rescripts/rescript-env": "^0.0.11",
"concurrently": "^5.0.2",
"electron": "^7.1.7",
"electron-builder": "^21.2.0",
"typescript": "^3.7.4",
"wait-on": "^3.3.0"
}
}
electron.js看起来像这样:
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const startUrl = path.resolve('index.html');
const isDev = require('electron-is-dev');
let mainWindow;
function createWindow() {
console.log(startUrl);
mainWindow = new BrowserWindow({ width: 900, height: 680 });
mainWindow.loadURL(
isDev
? 'http://localhost:3000'
: `file://${path.join(__dirname, '../build/index.html')}`
);
if (isDev) {
// Open the DevTools.
//BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
mainWindow.webContents.openDevTools();
}
mainWindow.webContents.openDevTools();
mainWindow.on('closed', () => (mainWindow = null));
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
当我在localhost:3000上以纱线电子开发方式在开发模式下启动应用程序时,一切都很好。
但是,不幸的是,当我试图用纱线电子包装包装该应用程序时,它无法正常工作。
创建了dist文件夹,该文件夹具有.exe安装程序和可移植执行文件,但是当我执行可移植文件时,在开发控制台中会出现以下错误:
Invalid asm.js: Unexpected 2.7d1c33f4.chunk.js:1 token
此外,欢迎页面正确显示了导航栏,但是找不到组件(我认为是),当我尝试浏览导航栏时,仅出现白屏,并且开发控制台是空的。在欢迎页面上没有找到404(我已将其指定为const),如果路径错误,则会显示404。 这可能是工艺路线和正确的生产组合相结合的问题吗?
我已经尝试过像在引用路径时在electron.js文件中使用url.format()或在文件数组的package.json中添加electron.js一样,这在其他文章中已经提到。我认为electronic正在打包正确的文件,我认为App的生产版本存在问题,因为当我打开构建文件夹并打开index.html-file时,也会遇到同样的问题。 (在开发控制台中出现相同的错误,只用nav-bar呈现了欢迎页面,但没有正确的内容,仅找不到404)(也许我也只是在以一种不正确的方式思考,我实际上并不完全知道问题出在哪里)
如何解决此问题?
这也是我的App.js(指定了路由):
import React from 'react';
import Artikels from './pages/products/products';
import Consumers from './pages/consumers/consumers';
import contact from './pages/contact/contact';
import welcome from './pages/welcome/welcome';
import Invoices from './pages/invoices/invoices';
import 'bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Header from './components/header';
import './app.css';
const NotFound = () => <div>404 not found</div>;
// const soon = () => (
// <div>
// <p>Soon™</p>
// </div>
// );
const main = props => {
return (
<BrowserRouter>
<React.Fragment>
<Header />
<main>
<Switch>
<Route exact path="/" component={welcome} />
<Route exact path="/products" component={Artikels} />
<Route exact path="/customers" component={Consumers} />
<Route exact path="/invoices" component={Invoices} />
<Route exact path="/contact" component={contact} />
<Route path="*" component={NotFound} />
</Switch>
</main>
</React.Fragment>
</BrowserRouter>
);
};
export default main;
还有在构建后创建的index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="https://image.flaticon.com/icons/svg/305/305991.svg" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="logo192.png" />
<link rel="manifest" href="./manifest.json" />
<title>Hoch- und Tiefbau GmbH</title>
<link href="./static/css/2.86aa6515.chunk.css" rel="stylesheet">
<link href="./static/css/main.86a966e6.chunk.css" rel="stylesheet">
</head>
<body><noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script>!function (f) { function e(e) { for (var r, t, n = e[0], o = e[1], u = e[2], i = 0, l = []; i < n.length; i++)t = n[i], Object.prototype.hasOwnProperty.call(p, t) && p[t] && l.push(p[t][0]), p[t] = 0; for (r in o) Object.prototype.hasOwnProperty.call(o, r) && (f[r] = o[r]); for (s && s(e); l.length;)l.shift()(); return c.push.apply(c, u || []), a() } function a() { for (var e, r = 0; r < c.length; r++) { for (var t = c[r], n = !0, o = 1; o < t.length; o++) { var u = t[o]; 0 !== p[u] && (n = !1) } n && (c.splice(r--, 1), e = i(i.s = t[0])) } return e } var t = {}, p = { 1: 0 }, c = []; function i(e) { if (t[e]) return t[e].exports; var r = t[e] = { i: e, l: !1, exports: {} }; return f[e].call(r.exports, r, r.exports, i), r.l = !0, r.exports } i.m = f, i.c = t, i.d = function (e, r, t) { i.o(e, r) || Object.defineProperty(e, r, { enumerable: !0, get: t }) }, i.r = function (e) { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 }) }, i.t = function (r, e) { if (1 & e && (r = i(r)), 8 & e) return r; if (4 & e && "object" == typeof r && r && r.__esModule) return r; var t = Object.create(null); if (i.r(t), Object.defineProperty(t, "default", { enumerable: !0, value: r }), 2 & e && "string" != typeof r) for (var n in r) i.d(t, n, function (e) { return r[e] }.bind(null, n)); return t }, i.n = function (e) { var r = e && e.__esModule ? function () { return e.default } : function () { return e }; return i.d(r, "a", r), r }, i.o = function (e, r) { return Object.prototype.hasOwnProperty.call(e, r) }, i.p = "./"; var r = this.webpackJsonpuebung_eins = this.webpackJsonpuebung_eins || [], n = r.push.bind(r); r.push = e, r = r.slice(); for (var o = 0; o < r.length; o++)e(r[o]); var s = n; a() }([])</script>
<script src="./static/js/2.7d1c33f4.chunk.js"></script>
<script src="./static/js/main.d927dd98.chunk.js"></script>
</body>
</html>