更新时间:2022-02-21 09:56:29
通过IgnorePlugin
告诉Webpack忽略require
:
Tell Webpack to ignore that require
via 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,
],
};
问题来自这一行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(偶尔?)有这个问题.
My guess is that since it is a require
, Webpack tries to resolve it, even tho on Linux it doesn't exists. That's why it is in a try...catch
block, because it will fail when running on Linux and they handle it that way. Sadly Webpack (occasionally?) has problems with this.
如果我们检查整个 fsevents-handler.js
模块在主要 index.js
文件,我们可以看到它们通过FsEventsHandler.canUse()
,保存到opts.useFsEvents
,然后每次他们想使用该模块他们检查该选项.
If we check how this whole fsevents-handler.js
module is used in the main index.js
file, we can see that they check if they can use this module via FsEventsHandler.canUse()
, save it to opts.useFsEvents
, then every time they want to use that module they check that option.
canUse
函数是 以这种方式实现:
const canUse = () => fsevents && FSEventsWatchers.size < 128;
因此,如果我们有一个模块返回了一些错误的值,那么通过 fsevents
变量,整个事情都将被禁用(在 Linux 上应该是默认的).
So if we had a module that returned something falsy, then through the fsevents
variable the whole thing would be disabled (as it should be by default on Linux).
在我创建了以下章节中描述的(现在替代)解决方案后,vinceau 提出了一个更简单的解决方案:您可以告诉 Webpack 基于正则表达式槽 IgnorePlugin
.这样你就不必模拟模块,所以 lib 中的 require
会像作者最初预期的那样工作(失败).所以只需添加插件:
After I created the (now alternative) solution described in the chapter below, vinceau came up with a simpler solution: you can tell Webpack to ignore require
s based on a regex trough IgnorePlugin
. This way you don't have to mock the module so the require
in the lib will work (fail) as the authors originally expected it. So just add the plugin:
module.exports = {
plugins: [
new IgnorePlugin({ resourceRegExp: /^fsevents$/ }),
],
};
这将忽略每个操作系统上的 require
,但这不应该在 OSX 下发生,因此***检查平台并仅添加可选:
This will ignore the require
on every OS, but that shouldn't happen under OSX so it is better to check the platform and only add it optionally:
const optionalPlugins = [];
if (process.platform !== "darwin") { // don't ignore on OSX
optionalPlugins.push(new IgnorePlugin({ resourceRegExp: /^fsevents$/ }));
}
module.exports = {
plugins: [ ...optionalPlugins ],
};
我们可以创建一个模拟模块,它会返回一个虚假的默认值(同时添加一些注释来解释这种情况):
We can create a mock module that will return a falsy default (also add some comments to explain the situation):
// 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://***.com/a/67829712
module.exports = undefined
让我们将其保存到名为 fsevent.js
的项目根目录(您可以随意调用/放置它),然后配置 Webpack,以便当它尝试解析 fsevents
它将返回这个模拟模块.在 Webpack 5 中,这可以通过解析别名来完成.我们还添加了一个条件,因此我们不会在 fsevents
可用的 OSX 上执行此操作:
Lets save this to the project root named fsevent.js
(you can call/place it however you like), then configure Webpack, so when it tries to resolve fsevents
it will return this mock module. In Webpack 5 this can be done trough resolve aliases. We also add a condition so we don't do this on OSX where fsevents
is available:
const optionalAliases = {};
if (process.platform !== "darwin") {
optionalAliases['fsevents$'] = path.resolve(__dirname, `fsevents.js`);
}
module.exports = {
resolve: {
alias: {
...optionalAliases,
},
},
};