Electron+Webpack = 找不到模块:错误:无法解析 chokidar/etc 中的 fsevents/fs/etc [英] Electron+Webpack = Module not found: Error: Can't resolve fsevents/fs/etc in chokidar/etc

查看:106
本文介绍了Electron+Webpack = 找不到模块:错误:无法解析 chokidar/etc 中的 fsevents/fs/etc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个 Electron 应用程序,但许多节点库导致 Module not found 错误,即使对于 electron-main 目标也是如此.

I'm trying to create an Electron app, but many node-libs causes the Module not found error, even for the electron-main target.

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 期间产生错误:

This produces the error during 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' } 没有帮助.

PS: Adding node: { fsevents: 'empty' } doesn't help.

推荐答案

tl;dr

通过IgnorePlugin告诉Webpack忽略require:

tl;dr

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 requires 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 ],
};

替代方案

我们可以创建一个模拟模块,它会返回一个虚假的默认值(同时添加一些注释来解释这种情况):

Alternative Solution

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://stackoverflow.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,
    },
  },
};

这篇关于Electron+Webpack = 找不到模块:错误:无法解析 chokidar/etc 中的 fsevents/fs/etc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆