开发者问题收集

导入“事件”时,Electron Forge 与 Webpack 收到“require 未定义”错误

2021-02-09
2390

我最近用 electron forge 和 webpack 模板开始了一个新项目。我正在创建一个简单的身份验证类,并希望使用 nodejs 中的事件系统。我正在使用 import 语法,但收到一条错误消息,指出 require 未定义。我不希望打开 nodeIntegration ,我认为 webpack 会自动使用 browserfy 版本的 nodejs 事件系统:

You usually do not have to install events yourself! If your code runs in Node.js, events is built in. If your code runs in the browser, bundlers like browserify or webpack also include the events module.

安装 browserify 事件模块也无法解决问题。我还尝试排除 node_modules/events 文件夹,希望 webpack 会使用其自己的事件模块,但这对我来说不起作用。这是我的代码:

import { EventEmitter } from 'events';

export default class Auth {
  constructor(socket) {
  }

  setToken(token) {
    this.token = token;
    localStorage.setItem('token', token);
    this.emit('token', token);
  }

  checkToken() {
    if(localStorage.getItem("token") !== null) {
      this.setToken(localStorage.getItem("token"));
    } else {
      this.emit('false', false);
    }
  }

  getToken() {
    return localStorage.getItem("token");
  }

  setAuth(auth) {
    this.emit('auth', auth);
    this.isAuth = auth;
  }
  
}

这是我的 webpack 渲染器配置:

const rules = require('./webpack.rules');
const webpack = require('webpack');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

rules.push({
  test: /\.css$/,
  use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
});

const assets = [ 'assets' ];
const copyPlugins = assets.map((asset) => {
  return new CopyWebpackPlugin({
    patterns: [{ from: path.resolve(__dirname, 'src/renderer/', asset), to: asset }],
  });
});

module.exports = {
  // Put your normal webpack config below here
  module: {
    rules,
  },
  plugins: [
      new webpack.ProvidePlugin({
          $: 'jquery',
      }),
      ...copyPlugins
  ],
  resolve: {
    alias: {
      'components': path.resolve(__dirname, './src/renderer/components'),
      'pages': path.resolve(__dirname, './src/renderer/pages'),
      'core': path.resolve(__dirname, './src/renderer/core'),
    },
    extensions: ['.js']
  },
};

这是我的 webpack 规则配置:

module.exports = [
  // Add support for native node modules
  {
    test: /\.node$/,
    use: 'node-loader',
  },
  {
    test: /\.(m?js|node)$/,
    parser: { amd: false },
    use: {
      loader: '@marshallofsound/webpack-asset-relocator-loader',
      options: {
        outputAssetBase: 'native_modules',
      },
    },
  },
];

这是错误:

external "events":
Uncaught ReferenceError: require is not defined
    at Object.events (external "events":1)
    at __webpack_require__ (bootstrap:832)
    at fn (bootstrap:129)
    at Module../src/renderer/core/Auth.js (Auth.js:1)
    at __webpack_require__ (bootstrap:832)
    at fn (bootstrap:129)
    at Module../src/renderer/index.js (index.js:1)
    at __webpack_require__ (bootstrap:832)
    at fn (bootstrap:129)
    at Object.0 (routes.js:40)
3个回答

休息了一会儿后,我意识到解决方案很简单:

我只需要将以下内容添加到我的渲染器配置中:

target: 'web'
Joe Jankowiak
2021-02-09

解决方案是使用 electron 中的 ContextBridge API 作为 electron-forge webpack 模板

preload.js

import { ipcRenderer, contextBridge } from "electron";

contextBridge.exposeInMainWorld("electron", {
  notificationApi: {
    sendNotification(message) {
      ipcRenderer.send("notify", message);
    },
  },
  batteryApi: {},
  fileApi: {},
});

main.js

const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      worldSafeExecuteJavaScript: true,
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
    },
 });

ipcMain.on("notify", (_, message) => {
   new Notification({ title: "Notification", body: message }).show();
});

package.json

 "plugins": [
    [
      "@electron-forge/plugin-webpack",
      {
        "mainConfig": "./webpack.main.config.js",
        "renderer": {
          "config": "./webpack.renderer.config.js",
          "entryPoints": [
            {
              "html": "./src/index.html",
              "js": "./src/renderer.js",
              "name": "main_window",
              "preload": {
                "js": "./src/preload.js"
              }
            }
          ]
        }
      }
    ]
  ]

然后使用以下代码将调用本机通知消息

electron.notificationApi.sendNotification("Finally!");
  
Sathishkumar Rakkiyasamy
2021-07-29

使用 electron forge webpack 模板时我也遇到了同样的错误。我发现原因是 webpack 配置中的 @vercel/webpack-asset-relocator-loader 。删除此加载器进行渲染后,一切正常。看来 @vercel/webpack-asset-relocator-loader 只能在节点环境中使用。

user22407961
2023-08-18