【问题标题】:preload script not loaded in packaged app未在打包的应用程序中加载预加载脚本
【发布时间】:2018-09-27 05:57:01
【问题描述】:

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

当我使用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",
}

我的项目结构:

- 节点模块

- main.js

- preload.js

- package.json

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

【问题讨论】:

  • 您可以尝试将path.join(__dirname, 'preload.js') 替换为'./preload.js'
  • 已经试过了!尝试了很多路径,似乎不是问题... ^^'
  • 首先,您在运行打包的应用程序时是否遇到特定错误?其次,你的应用有 webview 吗?如果是这样,不要将预加载脚本传递给 BrowserWindow 构造函数,而是尝试向webview 标签添加一个属性:preload="preload.js"(假设该文件与您在窗口中加载的页面相邻)

标签: javascript electron electron-packager


【解决方案1】:

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

  1. package.json 文件中添加preload 键:
{
  "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 正确输入:

为什么要分开 fie ?不确定是否需要,但我不想在渲染器进程中从包含主进程代码(如 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);

学分:

另见:

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 它在开发中对我有用,因为我知道路径但在生产中不起作用,因为那里没有 preload.js,因为我使用 electron-forge,它使用 webpack,它将所有文件捆绑到一个单个文件。我该怎么做?我写了更多关于我的用例here on a Github issue
    猜你喜欢
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 2021-03-19
    • 2020-12-29
    相关资源
    最近更新 更多