预加载脚本未加载到打包的应用程序中

Ser*_*gio 8 javascript electron electron-packager

我制作了一个需要加载预加载 js 文件的小型 Electron 应用程序。

当我用 启动应用程序时electron .,它会找到该文件,但是当应用程序被打包时,它却找不到。

调用是在这里进行的:

mainWindow = new BrowserWindow({
   width: 800,
   height: 600,
   webPreferences: {
     nodeIntegration: false, 
     nativeWindowOpen: true,
     webSecurity: false,
     preload: path.join(__dirname, 'preload.js')  
  }
})
Run Code Online (Sandbox Code Playgroud)

我的简化 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",
}
Run Code Online (Sandbox Code Playgroud)

我的项目结构:

- 节点模块

- main.js

- 预加载.js

- 包.json

我已经检查了结果,path.join在这两种情况下,路径都是正确的,并且文件在那里。

Amb*_*ier 8

对于使用 Electron Forge webpack typescript 样板的人们:

  1. preload在文件中添加密钥package.json
{
  "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"
                  }
                }
              ]
            }
          }
        ]
      ]
    }
  }
}

Run Code Online (Sandbox Code Playgroud)

预加载脚本可以是打字稿文件。

  1. 添加MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY常量作为 的值preload
// 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,
    }
  });
Run Code Online (Sandbox Code Playgroud)
  1. preload.ts写:
import {
  contextBridge,
  ipcRenderer
} from 'electron';

contextBridge.exposeInMainWorld(
  'electron',
  {
    doThing: () => ipcRenderer.send('do-a-thing')
  }
)
Run Code Online (Sandbox Code Playgroud)
  1. 添加index.d.ts文件,写入:
declare global {
  interface Window {
    electron: {
      doThing(): void;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 启动您的应用程序,您可以在开发控制台中键入electron并查看它的定义。

  2. 奖励:为 contextBridge 公开的 API 正确输入:

为什么要分开打?不确定是否需要,但我不想从渲染器进程中包含主进程代码(如 preload.ts)的文件中导入接口。

// exposed-main-api.model.ts

export interface ExposedMainAPI {
  doThat(data: string): Promise<number>;
}
Run Code Online (Sandbox Code Playgroud)
// index.d.ts

declare global {
  interface Window {
    electron: ExposedMainAPI
  }
}
Run Code Online (Sandbox Code Playgroud)
// 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);
Run Code Online (Sandbox Code Playgroud)

学分:

也可以看看:


Avr*_*dor 6

预加载脚本需要指定为绝对路径。因此,它与在开发中运行它的时间和打包为 asar 文件运行它的时间有所不同。

const getSourceDirectory = () => isDev()
    ? path.join(process.cwd(), 'build', 'src') // or wherever your local build is compiled
    : path.join(process.resourcesPath, 'app', 'src'); // asar location

const preload = path.resolve(getSourceDirectory(), 'preload.js');
Run Code Online (Sandbox Code Playgroud)

  • 它在开发中对我有用,因为我知道路径,但在生产中不起作用,因为那里没有“preload.js”,因为我使用“electron-forge”,它使用“webpack”将所有文件捆绑到一个文件中。我该怎么做?我已经写了更多关于我的用例的文章[在 Github 问题上](https://github.com/electron-userland/electron-forge/issues/1590) (2认同)