Quantcast
Channel: User totymedli - Stack Overflow
Viewing all articles
Browse latest Browse all 54

Answer by totymedli for Electron+Webpack = Module not found: Error: Can't resolve fsevents/fs/etc in chokidar/etc

$
0
0

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

Explanation

The issue comes from 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);}

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.

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.

The canUse function is implemented this way:

const canUse = () => fsevents && FSEventsWatchers.size < 128;

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).

Solution

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$/ }),  ],};

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/67829712module.exports = undefined

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

Viewing all articles
Browse latest Browse all 54

Trending Articles