問題描述
我制作了一個需要加載預加載 js 文件的小型 Electron 應用程序.
I've made a small Electron app which needs to load a preload js file.
當我用 electron .
啟動應用程序時,它會找到該文件,但是當應用程序被打包時,它不會.
When I start the app with electron .
, it finds the file, but when the app is packaged, it doesn't.
在此處撥打電話:
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
nativeWindowOpen: true,
webSecurity: false,
preload: path.join(__dirname, 'preload.js')
}
})
我的簡化 package.json:
My simplified package.json:
"name": "app",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-packager . --platform=win32 --arch=x64 --overwrite"
}
"devDependencies": {
"electron": "^1.8.4",
"electron-packager": "^12.0.1",
}
我的項目結構:
- 節點模塊
- main.js
- preload.js
- preload.js
- package.json
- package.json
我檢查了 path.join
的結果,在這兩種情況下,路徑都是正確的,并且文件在那里.
I've checked the result of the path.join
and in both cases, the path is correct, and the file is there.
推薦答案
對于使用 Electron Forge webpack typescript 樣板的人們:
For peoples using Electron Forge webpack typescript boilerplate :
- 在
package.json
文件中添加preload
鍵:
- Add the
preload
key inpackage.json
file:
{
"config": {
"forge": {
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.tsx",
"name": "main_window",
"preload": {
"js": "./src/preload.ts"
}
}
]
}
}
]
]
}
}
}
預加載腳本可以是打字稿文件.
Preload script can be a typescript file.
- 添加
MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY
常量作為preload
的值:
- Add
MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY
constant as value forpreload
:
// Tell typescript about this magic constant
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: any;
// [...]
const mainWindow = new BrowserWindow({
height: 1000,
width: 1500,
webPreferences: {
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
}
});
- 在
preload.ts
中寫:
import {
contextBridge,
ipcRenderer
} from 'electron';
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
- 添加
index.d.ts
文件,寫入:
- Add
index.d.ts
file, write :
declare global {
interface Window {
electron: {
doThing(): void;
}
}
}
啟動您的應用程序,在您的開發控制臺中您可以輸入
electron
并查看它的定義.
獎勵:為 contextBridge 公開的 API 正確輸入:
BONUS: getting the typing right for the contextBridge exposed API:
為什么要分開 fie ?不確定是否需要,但我不希望在渲染器進程中從包含主進程代碼(如 preload.ts)的文件中導入接口.
Why a separated fie ? Not sure if needed, but I prefer not having to import an interface from a file that contain main process code (like preload.ts) in renderer process.
// exposed-main-api.model.ts
export interface ExposedMainAPI {
doThat(data: string): Promise<number>;
}
// index.d.ts
declare global {
interface Window {
electron: ExposedMainAPI
}
}
// preload.ts
import {
contextBridge,
ipcRenderer
} from 'electron';
const exposedAPI: ExposedAPI = {
// You are free to omit parameters typing and return type if you feel so.
// TS know the function type thanks to exposedAPI typing.
doThat: (data) => ipcRenderer.invoke('do-that-and-return-promise', data)
};
// note: this assume you have a `ipcMain.handle('do-thing-and-return-promise', ...)`
// somewhere that return a number.
contextBridge.exposeInMainWorld('electron', exposedAPI);
學分:
- @deadcoder0904 在 評論 對于以前的答案,這是他鏈接的 github 問題:https://github.com/electron-userland/electron-forge/issues/1590
index.d.ts
輸入和contextBridge
的小示例用法:https://github.com/electron/electron/issues/9920#issuecomment-743803249
- @deadcoder0904 that gave us the solution in an comment to a previous answer, here is the github issue he link : https://github.com/electron-userland/electron-forge/issues/1590
index.d.ts
typing and small example usage ofcontextBridge
: https://github.com/electron/electron/issues/9920#issuecomment-743803249
另見:
- 關于安全性的說明以及使用 IPC 的示例:https://github.com/electron/electron/issues/9920#issuecomment-575839738
這篇關于未在打包的應用程序中加載預加載腳本的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!