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