diff --git a/desktop/.erb/configs/webpack.config.renderer.prod.ts b/desktop/.erb/configs/webpack.config.renderer.prod.ts index 8e6c5d1a..ed826db2 100644 --- a/desktop/.erb/configs/webpack.config.renderer.prod.ts +++ b/desktop/.erb/configs/webpack.config.renderer.prod.ts @@ -17,7 +17,7 @@ const configuration: Configuration = { mode: 'production', output: { path: webpackPaths.distRendererPath, - publicPath: './', + publicPath: '/', filename: '[name].[contenthash].js', library: { type: 'umd', diff --git a/desktop/package.json b/desktop/package.json index a8ee749a..45df20e5 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -47,6 +47,7 @@ "start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only .", "start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts", "start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts", + "http-server": "ts-node src/main/lib/http.ts", "test": "jest" }, "lint-staged": { @@ -115,6 +116,8 @@ "electron-serve": "^1.1.0", "electron-updater": "^5.0.1", "electron-window-state": "^5.0.3", + "express": "^4.18.1", + "get-port": "5.1.1", "react": "^18.1.0", "react-dom": "^18.1.0", "react-router-dom": "^6.3.0" diff --git a/desktop/src/main/lib/serve.ts b/desktop/src/main/lib/electron-serve.ts similarity index 100% rename from desktop/src/main/lib/serve.ts rename to desktop/src/main/lib/electron-serve.ts diff --git a/desktop/src/main/lib/http.ts b/desktop/src/main/lib/http.ts new file mode 100644 index 00000000..06a192a9 --- /dev/null +++ b/desktop/src/main/lib/http.ts @@ -0,0 +1,29 @@ +import express from 'express'; +import path from 'path'; + +/** + * 启动一个本地服务器 + */ +export function startLocalServer( + staticPath: string, + port: number +): Promise { + return new Promise((resolve) => { + const app = express(); + + const staticDir = path.resolve(__dirname, staticPath); + console.log('Static File:', staticDir); + + app.use(express.static(staticDir)); + + // Fallback + app.use('/**', function (_, res) { + res.sendFile(staticPath + '/index.html', { maxAge: 0 }); + }); + + app.listen(port, () => { + console.log('Static file server is listen at:', port); + resolve(); + }); + }); +} diff --git a/desktop/src/main/main.ts b/desktop/src/main/main.ts index 3a895b0b..f0523556 100644 --- a/desktop/src/main/main.ts +++ b/desktop/src/main/main.ts @@ -13,7 +13,7 @@ import { app, BrowserWindow, shell, ipcMain } from 'electron'; import { autoUpdater } from 'electron-updater'; import log from 'electron-log'; import MenuBuilder from './menu'; -import { resolveHtmlPath } from './util'; +import { getMainWindowUrl, resolveHtmlPath } from './util'; import windowStateKeeper from 'electron-window-state'; import is from 'electron-is'; @@ -108,8 +108,15 @@ const createWindow = async () => { }, }); - const url = resolveHtmlPath('index.html'); - log.info('loadUrl:', url); + // 方案一: 通过文件协议加载界面 + // const url = resolveHtmlPath('index.html'); + // log.info('loadUrl:', url); + // mainWindow.loadURL(url); + + // 方案二: 通过本地起一个http服务,然后electron访问http服务 + log.info('Starting Local Http Server'); + const url = await getMainWindowUrl(); + log.info('Local Server started, entry:', url); mainWindow.loadURL(url); mainWindow.on('ready-to-show', () => { diff --git a/desktop/src/main/util.ts b/desktop/src/main/util.ts index 4929e751..3705cf92 100644 --- a/desktop/src/main/util.ts +++ b/desktop/src/main/util.ts @@ -1,5 +1,9 @@ import { URL } from 'url'; import path from 'path'; +import is from 'electron-is'; +import { startLocalServer } from './lib/http'; +import getPort, { makeRange } from 'get-port'; +import log from 'electron-log'; export let resolveHtmlPath: (htmlFileName: string) => string; @@ -15,3 +19,24 @@ if (process.env.NODE_ENV === 'development') { return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`; }; } + +/** + * 获取主界面的窗口地址 + */ +export async function getMainWindowUrl() { + if (is.dev()) { + const port = process.env.PORT || 1212; + return `http://localhost:${port}/index.html`; + } else { + const port = await getPort({ + port: makeRange(11000, 20000), // 使用高位端口 + }); + await startLocalServer(path.resolve(__dirname, '../renderer/'), port); + + return `http://localhost:${port}/index.html`; + } +} + +export function getDefaultLoggerPath(): string { + return log.transports.file.getFile().path; +} diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 71607707..f9aa3105 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -5381,7 +5381,7 @@ expect@^28.1.1: jest-message-util "^28.1.1" jest-util "^28.1.1" -express@^4.17.3: +express@^4.17.3, express@^4.18.1: version "4.18.1" resolved "https://registry.npmmirror.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== @@ -5722,6 +5722,11 @@ get-package-type@^0.1.0: resolved "https://registry.npmmirror.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-port@5.1.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + get-stream@^4.1.0: version "4.1.0" resolved "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"