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

时间:2018-04-17 10:02:00

标签: javascript electron electron-packager

我制作了一个小型电子应用,需要加载一个preload js文件。

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

此处致电:

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

我简化的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",
}

我的项目结构:

- node_modules

- main.js

- preload.js

- package.json

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

2 个答案:

答案 0 :(得分:3)

需要将预加载脚本指定为绝对路径。因此,这与您在开发中运行它和打包为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');

答案 1 :(得分:1)

对于使用 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"
                  }
                }
              ]
            }
          }
        ]
      ]
    }
  }
}

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

  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,
    }
  });
  1. preload.ts 中写:
import {
  contextBridge,
  ipcRenderer
} from 'electron';

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

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

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

// 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);

学分:

另见: