paulmillr / chokidar

Minimal and efficient cross-platform file watching library
https://paulmillr.com
MIT License
10.73k stars 574 forks source link

Unhandled Promise Rejection Warnings with Webpack 5 and browser-sync 2.26.14 on Node v14.16.0 #1090

Closed chatelp closed 3 years ago

chatelp commented 3 years ago

Describe the bug

Getting thousands of UnhandledPromiseRejectionWarning errors coming from chokidar when launching webpack --watch --config resources/assets/build/webpack.config.js

Versions (please complete the following information):

Additional context

// from package.json
"scripts": {

    "start": "webpack --watch --config resources/assets/build/webpack.config.js",

  },
//webpack.config.js
'use strict'; // eslint-disable-line

const path = require('path');
const webpack = require('webpack');
const { merge, mergeWithCustomize, customizeArray } = require('webpack-merge');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');

const desire = require('./util/desire');
const config = require('./config');

const assetsFilenames = (config.enabled.cacheBusting) ? config.cacheBusting : '[name]';

let webpackConfig = {
  context: config.paths.assets,
  entry: config.entry,
  devtool: (config.enabled.sourceMaps ? 'source-map' : undefined),
  output: {
    path: config.paths.dist,
    publicPath: config.publicPath,
    filename: `scripts/${assetsFilenames}.js`,
  },
  stats: {
    hash: false,
    version: false,
    timings: false,
    children: true,
    errors: true,
    errorDetails: true,
    warnings: true,
    chunks: false,
    modules: false,
    reasons: false,
    source: false,
    publicPath: false,
  },
  performance: {
    maxEntrypointSize: 512000,
    maxAssetSize:        512000,
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.(js|s?[ca]ss)$/,
        include: config.paths.assets,
        loader: 'import-glob',
      },
      {
        test: /\.js$/,
        exclude: [/node_modules(?![/|\\](bootstrap|foundation-sites))/],
        use: [
          { loader: 'buble-loader', options: { objectAssign: 'Object.assign' } },
        ],
      },
      {
        test: /\.css$/,
        include: config.paths.assets,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { sourceMap: config.enabled.sourceMaps } },
          {
            loader: 'postcss-loader', options: {
              postcssOptions: {
                config: path.join( __dirname, 'postcss.config.js' ),
                ctx: config,
              },
                sourceMap: config.enabled.sourceMaps,
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { sourceMap: config.enabled.sourceMaps } },
          {
            loader: 'postcss-loader', options: {
              postcssOptions: {
                config: path.join( __dirname, 'postcss.config.js' ),
                ctx: config,
              },
              sourceMap: config.enabled.sourceMaps,
            },
          },
          { loader: 'resolve-url-loader', options: { sourceMap: config.enabled.sourceMaps } },
          {
            loader: 'sass-loader', options: {
              sassOptions: {
                sourceComments: true,
              },
              sourceMap: true, //config.enabled.sourceMaps, // false causes a resolve issue
            },
          },
        ],
      },
      {
        test: /\.(ttf|otf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
        include: config.paths.assets,
        loader: 'url-loader',
        options: {
          limit: 4096,
          name: `[path]${assetsFilenames}.[ext]`,
        },
      },
      {
        test: /\.(ttf|otf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
        include: /node_modules/,
        loader: 'url-loader',
        options: {
          limit: 4096,
          outputPath: 'vendor/',
          name: `[path]${assetsFilenames}.[ext]`,
        },
      },
    ],
  },
  resolve: {
    modules: [
      config.paths.assets,
      'node_modules',
    ],
    enforceExtension: false,
  },
  externals: {
    jquery: 'jQuery',
  },
  plugins: [
    new ESLintPlugin({
      failOnWarning: false,
      failOnError:   true,
    }),
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: [config.paths.dist],
      verbose: false,
    }),
    new CopyPlugin({
      patterns: [
        {
          from: config.copy,
          noErrorOnMissing: true,
          to: `[path]${assetsFilenames}[ext]`, // Note: since 8.0.0 no dot in placeholder needed
        },
      ],
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
      Popper: 'popper.js/dist/umd/popper.js',
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: config.enabled.optimize,
      debug: config.enabled.watcher,
      stats: { colors: true },
    }),
    new webpack.LoaderOptionsPlugin({
      test: /\.s?css$/,
      options: {
        output: { path: config.paths.dist },
        context: config.paths.assets,
      },
    }),
    new MiniCssExtractPlugin({
      filename: `styles/${assetsFilenames}.css`,
    }),
    new StyleLintPlugin({
      failOnError: !config.enabled.watcher,
      syntax: 'scss',
    }),
  ],
};

/* eslint-disable global-require */ /** Let's only load dependencies as needed */

if (config.enabled.optimize) {
  webpackConfig = merge(webpackConfig, require('./webpack.config.optimize'));
}

if (config.enabled.cacheBusting) {
  const WebpackAssetsManifest = require('webpack-assets-manifest');

  webpackConfig.plugins.push(
    new WebpackAssetsManifest({
      output: 'assets.json',
      space: 2,
      writeToDisk: false,
      assets: config.manifest,
      replacer: require('./util/assetManifestsFormatter'),
      contextRelativeKeys: true,
    })
  );
}

if (config.enabled.watcher) {
  webpackConfig.entry = require('./util/addHotMiddleware')(webpackConfig.entry);
  webpackConfig = merge(webpackConfig, require('./webpack.config.watch'));
}

/**
 * During installation via sage-installer (i.e. composer create-project) some
 * presets may generate a preset specific config (webpack.config.preset.js) to
 * override some of the default options set here. We use webpack-merge to merge
 * them in. If you need to modify Sage's default webpack config, we recommend
 * that you modify this file directly, instead of creating your own preset
 * file, as there are limitations to using webpack-merge which can hinder your
 * ability to change certain options.
 */

module.exports = mergeWithCustomize({
  customizeArray: customizeArray({
    'module.rules': 'replace',
  }),
})(webpackConfig, desire(`${__dirname}/webpack.config.preset`) ? desire(`${__dirname}/webpack.config.preset`) : {} )
//webpack.config.watch.js
const url = require('url');
const webpack = require('webpack');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')

const config = require('./config');

const target = process.env.DEVURL || config.devUrl;
const proxyUrlObj = url.parse(config.proxyUrl);

module.exports = {
  // Ajout du polling pour webpack (ne marche pas dans homestead sinon)
  devServer: {
    watchOptions: {
        poll: true,
    },
  },
  output: {
    pathinfo: true,
    publicPath: config.proxyUrl + config.publicPath,
  },
  devtool: 'cheap-module-source-map',
  stats: false,
  plugins: [
    new BrowserSyncPlugin({
      host:  proxyUrlObj.hostname,
      port:  proxyUrlObj.port,

      proxy: target,
      https: (url.parse(target).protocol === 'https:'),

      files: [
        '**/*.php',
        '**/*.css',
        {
           match: '**/*.js',
           options:{
              ignored: 'dist/**/*.js',
           },
        },
     ],

      watch: config.watch,
      open:  config.open,
      reloadDelay: 500,
    },{
      reload: false,
      injectChanges: false,
    }),

    new webpack.HotModuleReplacementPlugin(),
  ],
};
paulmillr commented 3 years ago

we don't support "webpack", we support chokidar. if you want a bugfix, provide a proper isolated bug

chatelp commented 3 years ago

I'm not the developper of webpack, nor browser-sync. I just saw that the error is created by chokidar, when called through webpack->browser-sync->chokidar.

paulmillr commented 3 years ago

so report this to webpack or browser-sync. chokidar is a low-level library.

paulmillr commented 3 years ago

^ we need a more low-level reproduction

chatelp commented 3 years ago

Yes, I already reported it to browser-sync. Just wanted to notify you at the same time. In any case, found a "solution" to the ENOSPC problem: increasing the inotify limit https://unix.stackexchange.com/questions/13751/kernel-inotify-watch-limit-reached. So it's not exactly a bug in Chokidar, but you should probably handle the promise rejection in this particular case.

Cheers.

paulmillr commented 3 years ago

thanks