我正在尝试创建一个 Electron 应用程序,但许多节点库导致 Module not found
错误,即使是 electron-main
目标。
webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
target: `electron-main`,
entry: {main: `./src/main.js`},
resolve: {
extensions: ['.js'],
modules: ['node_modules', path.join(__dirname, 'src')],
},
output: {
path: path.resolve(__dirname, `dist`),
filename: '[name].bundle.js',
},
}
src/main.js
const watcher = require('chokidar').watch('./dist')
watcher.on('change', function() {
console.log('change', arguments)
})
package.json
{
"name": "test",
"version": "1.0.0",
"author": "I",
"private": true,
"main": "dist/main.bundle.js",
"scripts": {
"build": "webpack"
},
"devDependencies": {
"@types/chokidar": "^1.7.5",
"chokidar": "^2.0.4",
"electron": "^2.0.8",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0"
}
}
这会在
build
期间产生错误:WARNING in ./node_modules/chokidar/lib/fsevents-handler.js
Module not found: Error: Can't resolve 'fsevents' in '.\node_modules\chokidar\lib'
@ ./node_modules/chokidar/lib/fsevents-handler.js
@ ./node_modules/chokidar/index.js
@ ./src/main.js
我究竟做错了什么?
PS:添加
node: { fsevents: 'empty' }
没有帮助。
最佳答案
tl;博士
告诉 Webpack 忽略 require
通过 IgnorePlugin
:
const { IgnorePlugin } = require('webpack');
const optionalPlugins = [];
if (process.platform !== "darwin") { // don't ignore on OSX
optionalPlugins.push(new IgnorePlugin({ resourceRegExp: /^fsevents$/ }));
}
module.exports = {
// other webpack config options here...
plugins: [
...optionalPlugins,
],
};
解释问题来自 this line in
lib/fsevents-handler.js
:try {
fsevents = require('fsevents'); // this module doesn't exists on Linux
} catch (error) {
if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error);
}
我的猜测是,因为它是 require
,Webpack 尝试解决它,即使在 Linux 上它也不存在。这就是为什么它在 try...catch
中的原因阻止,因为它在 Linux 上运行时会失败并且他们会以这种方式处理它。可悲的是,Webpack(偶尔?)在这方面有问题。如果我们检查这整个
fsevents-handler.js
模块用于主 index.js
文件,我们可以看到他们check if they can use this module通过 FsEventsHandler.canUse()
, save it to opts.useFsEvents
,然后每次他们想使用该模块 they check that option .canUse
功能是 implemented this way :const canUse = () => fsevents && FSEventsWatchers.size < 128;
因此,如果我们有一个模块返回假值,那么通过 fsevents
变量整个事情将被禁用(因为它应该在 Linux 上默认)。解决方案
在我创建了以下章节中描述的(现在是替代的)解决方案后,vinceau想出了一个更简单的解决方案:你可以告诉 Webpack 忽略
require
s 基于正则表达式低谷 IgnorePlugin
.这样你就不必模拟模块,所以 require
在 lib 中将像作者最初预期的那样工作(失败)。所以只需添加插件:module.exports = {
plugins: [
new IgnorePlugin({ resourceRegExp: /^fsevents$/ }),
],
};
这将忽略 require
在每个操作系统上,但在 OSX 下不应该发生这种情况,因此最好检查平台并仅选择性地添加它:const optionalPlugins = [];
if (process.platform !== "darwin") { // don't ignore on OSX
optionalPlugins.push(new IgnorePlugin({ resourceRegExp: /^fsevents$/ }));
}
module.exports = {
plugins: [ ...optionalPlugins ],
};
替代方案我们可以创建一个模拟模块,它将返回一个虚假的默认值(还添加一些注释来解释这种情况):
// mock module to prevent Webpack from throwing an error when
// it tries to resolve the `fsevents` module under Linux that
// doesn't have this module.
// see: https://stackoverflow.com/a/67829712
module.exports = undefined
让我们将其保存到名为 fsevent.js
的项目根目录中(你可以随意调用/放置它),然后配置 Webpack,以便当它尝试解析 fsevents
时它将返回这个模拟模块。在 Webpack 5 中,这可以通过 resolve aliases 完成.我们还添加了一个条件,因此我们不在 OSX 上执行此操作,其中 fsevents
可用:const optionalAliases = {};
if (process.platform !== "darwin") {
optionalAliases['fsevents$'] = path.resolve(__dirname, `fsevents.js`);
}
module.exports = {
resolve: {
alias: {
...optionalAliases,
},
},
};
关于webpack - Electron+Webpack = 找不到模块 : Error: Can't resolve fsevents/fs/etc in chokidar/etc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52125641/