导入“事件”时,Electron Forge 与 Webpack 收到“require 未定义”错误
我最近用 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)
休息了一会儿后,我意识到解决方案很简单:
我只需要将以下内容添加到我的渲染器配置中:
target: 'web'
解决方案是使用
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!");
使用 electron forge webpack 模板时我也遇到了同样的错误。我发现原因是 webpack 配置中的
@vercel/webpack-asset-relocator-loader
。删除此加载器进行渲染后,一切正常。看来
@vercel/webpack-asset-relocator-loader
只能在节点环境中使用。