首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的电子应用程序没有导入contextBridge?

为什么我的电子应用程序没有导入contextBridge?
EN

Stack Overflow用户
提问于 2021-01-29 22:28:32
回答 1查看 1.1K关注 0票数 2

我正在用Webpack、Babel和ESLint编写一个带有React和类型记录的电子应用程序,但我在设置时遇到了困难:

代码语言:javascript
运行
复制
  mainWindow = new BrowserWindow({
    title: "Biomech",
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      enableRemoteModule: false,
      sandbox: true,
      preload: path.join(__dirname, "./preload.js"),
      nativeWindowOpen: true,
    },
  });

作为一种安全措施。

原因是,如果我像上面所指定的那样设置webPreferences,我需要使用contextBridge和一个预加载脚本来将使用IPC的函数绑定到window。问题是contextBridge没有正确导入到我的preload.ts中。

代码语言:javascript
运行
复制
import { contextBridge, ipcRenderer } from "electron";
import { readFileSync } from 'fs';
import { History } from 'history';
import { LIST_DRIVE_FILES_CHANNEL, LOAD_PREV_TEST_RESULTS_CHANNEL, OAUTH2_ACCESS_TOKEN_REQUEST_CHANNEL } from "../src/constants/ipcChannels";
import { VISUALIZE_RESULTS_PATH } from "../src/constants/urls";


// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        exchangeCodeForAccessToken: (code: string) => {
            ipcRenderer.invoke(OAUTH2_ACCESS_TOKEN_REQUEST_CHANNEL, code);
        },
        listDriveFiles: (accessToken: string) => {
            ipcRenderer.invoke(LIST_DRIVE_FILES_CHANNEL, accessToken);
        },
        openDirectoryDialog: (history: History) => {
            ipcRenderer.invoke(LOAD_PREV_TEST_RESULTS_CHANNEL).then((dialog: any) => {
                if (dialog.canceled) {  // canceled with one l is correct
                    return;
                } else {
                    const selectedDirectory = dialog.filePaths[0];
                    console.log(readFileSync(selectedDirectory + "/README.md", 'utf-8'));
                    history.push(VISUALIZE_RESULTS_PATH);
                }
            })
        }
    }
);

在我看来,它被正确地使用了,就像我在这里看到的例子,或者电子文档中的例子。但是,当我运行我的主进程脚本:npm run dev:electron时,它在我的package.json中指定:

代码语言:javascript
运行
复制
{
  "name": "electron-react-ts-app",
  "version": "1.0.0",
  "description": "Electron + React + Typescript",
  "main": "./dist/main.js",
  "preload": "./dist/preload.js",
  "scripts": {
    "dev": "concurrently --success first \"npm run dev:electron\" \"npm run dev:react\" -k",
    "dev:electron": "NODE_ENV=development webpack --config webpack.electron.config.js --mode development && electron .",
    "dev:react": "NODE_ENV=development webpack serve --config webpack.react.config.js --mode development",
    "build:electron": "NODE_ENV=production webpack --config webpack.electron.config.js --mode production",
    "build:react": "NODE_ENV=production webpack --config webpack.react.config.js --mode production",
    "build": "npm run build:electron && npm run build:react",
    "pack": "electron-builder --dir",
    "dist": "electron-builder",
    "lint": "eslint .",
    "format": "prettier --write \"**/*.+(js|jsx|json|yml|yaml|css|md|vue)\""
  },
  "keywords": [],
  "license": "MIT",
  "build": {
    "files": [
      "dist/",
      "node_modules/",
      "package.json"
    ],
    "productName": "Example",
    "appId": "com.example.app",
    "directories": {
      "output": "dist"
    }
  },
  "devDependencies": {
    "@babel/preset-env": "^7.9.5",
    "@babel/preset-react": "^7.9.4",
    "@babel/preset-typescript": "^7.9.0",
    "@types/electron-devtools-installer": "^2.2.0",
    "@types/react-router-dom": "^5.1.7",
    "@types/regenerator-runtime": "^0.13.0",
    "dpdm": "^3.6.0",
    "electron": "^11.2.1",
    "electron-builder": "^22.7.0",
    "electron-devtools-installer": "^3.1.1",
    "eslint": "^7.18.0",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^4.5.1",
    "husky": "^4.3.8",
    "lint-staged": "^10.5.3",
    "prettier": "^2.2.1",
    "react-router-dom": "^5.2.0",
    "webpack": "^5.11.1",
    "webpack-cli": "^4.3.1",
    "webpack-dev-server": "^3.11.1"
  },
  "dependencies": {
    "@babel/core": "^7.12.10",
    "@popperjs/core": "^2.6.0",
    "@types/node": "^14.14.22",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "axios": "^0.21.1",
    "babel-loader": "^8.2.2",
    "bootstrap": "^4.5.3",
    "chokidar": "^3.5.1",
    "core-js": "^3.8.3",
    "css-loader": "^5.0.1",
    "electron-fetch": "^1.7.3",
    "fsevents": "^2.3.1",
    "ini": "^2.0.0",
    "jquery": "^3.5.1",
    "react": "^17.0.1",
    "react-bootstrap": "^1.4.0",
    "react-dom": "^17.0.1",
    "react-google-login": "^5.2.2",
    "style-loader": "^2.0.0"
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint && npm run format"
    }
  },
  "lint-staged": {
    "*.+(js|jsx)": "eslint --fix",
    "*.+(json|css|md)": "prettier --write"
  }
}

我得到以下错误:无法读取未定义的属性“exposeInMainWorld”

代码语言:javascript
运行
复制
webpack 5.19.0 compiled successfully in 1793 ms
App threw an error during load
TypeError: Cannot read property 'exposeInMainWorld' of undefined
    at Object../electron/preload.ts (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:24:53)
    at __webpack_require__ (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:128:41)
    at /Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:252:11
    at Object.<anonymous> (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:254:12)
    at Module._compile (internal/modules/cjs/loader.js:1152:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1173:10)
    at Module.load (internal/modules/cjs/loader.js:992:32)
    at Module._load (internal/modules/cjs/loader.js:885:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12738)
    at Module.require (internal/modules/cjs/loader.js:1032:19)

我查看了这个回购关于电子安全的信息,看起来他做的事情并没有太大的不同,至少乍一看是这样,但我显然是在搞砸一些事情。

这里是我的webpack配置(webpack.electron.config.js),以防它有用:

代码语言:javascript
运行
复制
const path = require("path");

module.exports = [
  {
    resolve: {
      extensions: [".tsx", ".ts", ".js"],
    },
    devtool: "source-map",
    entry: {
        main: {
            import: "./electron/main.ts",
            dependOn: "preload"
        },
        preload: "./electron/preload.ts"
    },
    output: {
      path: path.resolve(__dirname, "dist"),
      filename: "[name].js",
    },
    target: "electron-main",
    module: {
      rules: [
        {
          test: /\.(js|ts|tsx)$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader",
          },
        },
        {
          test: /\.css$/,
          use: ["style-loader", "css-loader"],
        },
      ],
    },
    node: {
      __dirname: false,
    },
  },
];
EN

回答 1

Stack Overflow用户

发布于 2021-08-25 22:57:48

我认为问题在于您的webpack.config文件:

代码语言:javascript
运行
复制
entry: {
    main: {
        import: "./electron/main.ts",
        dependOn: "preload"
    },
    preload: "./electron/preload.ts"
},

可能是webpack试图在编译时解决所有"preload.ts“依赖,并尝试将其与main.ts文件捆绑在一起。在这种情况下,它将永远无法访问contextBridge.。preload.js文件应该只在单独的“上下文”中运行--“孤立的世界”,因为它们是在文档中引用的。

我想尝试的是:

  1. 从您webpack配置中删除dependOn:预加载:行。
  2. preload.ts文件转换为JS (即。( CommonJS格式)-现在试着用TS来实现

您的preload.js文件应该大致如下所示:

代码语言:javascript
运行
复制
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld(
  'electron',
  {
    doThing: () => ipcRenderer.send('do-a-thing')
  }
)
  1. preload.js复制到__dirname (在我的例子中是/dist)
  2. 再次运行电子

这是我访问"contextBridge“对象的唯一方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65962555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档