Skip to content

webpack-dev-server goes into infinite compile loop after making the smallest change to the source code #4362

Closed

Description

@OleksiL

Hi Guys.

I have an issue when webpack-dev-server goes into infinite compile loop after any change to the source code.
The same code works without this issue for my colleague. And it doesn't go into infinite loop every time: sometimes it will compile only once and stop (so works as it should), but sometimes it goes into frenzy mode.
In the the verbose log attached on the first change it compiled only once and stopped, but after I did another change it went into infinite loop.
webpack-dev-server.log

I've added my package.json, package-lock.json, and webpack folder to the zip file
webpack-dev-server-infinite-loop.zip

    "webpack-cli": "4.9.2",
    "webpack-dev-server": "3.11.2",
    "webpack-merge": "5.8.0",
    "webpack-notifier": "1.15.0",
    "workbox-webpack-plugin": "6.5.1"

Symptoms:
When I make a change to the component - webpack-dev-server recompiles it, but doesn't stop after the first cycle and keeps doing it:
code-change-example-causing-it
browser-console
intellij-console

I've tried to play with webpack related libraries versions, npm and node versions, clearing all caches for gradle, maven, intellij. Modified webpack configuration files to exclude things from watched. Removed and cloned the repository. Generated a new appliation with JHipster and compared generated webpack configs with mine, tried to make different changes. Nothing helps.

Activity

  1. alexander-akait commented on Apr 1, 2022

    @alexander-akait
    Member

    Please firstly update webpack-dev-server to v4

  2. OleksiL commented on Apr 1, 2022

    @OleksiL
    Author

    Please firstly update webpack-dev-server to v4

    This was, actually, how I noticed the issue: I was in the process of updating front-end libraries and migrated webpack-dev-server from v3 to v4. Later when testing it I found that it goes into infinite loop. At first I thought that something was wrong with my webpack configs and I modified them many times. Couldn't resolve it and after few days switched back to the previous version. But then I noticed that the issue still exists. After that I checked out few months old code from master branch, cleared all caches, removed all libraries, let npm and gradle to re-download all dependencies and even downgraded intellij version. It didn't help. The same source code works without issue for my colleague :(
    I start thinking that it is not webpack related, but something on my pc intervenes and modifies the files and in this way triggers recompiling. Like antivirus, but I don't have any... Any ides what it can be?

  3. alexander-akait commented on Apr 1, 2022

    @alexander-akait
    Member

    What is os? Please use the issue template in future, there are minimum questions which we need

  4. OleksiL commented on Apr 4, 2022

    @OleksiL
    Author

    Windows 10. I scanned issue template, but maybe not thoroughly enough.

  5. alexander-akait commented on Apr 4, 2022

    @alexander-akait
    Member

    Can you remove webpack.HotModuleReplacementPlugin, when you set hot: true, webpack-dev-server automatically apply this plugin, anyway can you provide example with code (no need to copy all code, only for showing the problem)

  6. OleksiL commented on Apr 20, 2022

    @OleksiL
    Author

    I've solved it by changing ending of one word: ignore -> ignored :

          watchOptions: {  
            ignored: ['**/node_modules', utils.root('src/test')]
          },
    

    I don't know how could it work correctly for everyone else with just ignore because docs tell to use ignored. I also had to change regexp values in the array because it started complaining about them after I'd made a change. Maybe there are two different ways to ignore files and only one of them worked in my case.

  7. alexander-akait commented on Apr 20, 2022

    @alexander-akait
    Member

    Do you change this options in dev server options? Because we have validation, so you should get an error...

  8. OleksiL commented on Apr 21, 2022

    @OleksiL
    Author

    Yes, in devServer options. I am using these versions of libraries:

        "webpack": "5.39.0",
        "webpack-cli": "4.7.2",
        "webpack-dev-server": "3.11.2",
    

    Now it looks like this:

    devServer: {
          stats: options.stats,
          hot: true,
          contentBase: './build/resources/main/static/',
          port: 9060,
          proxy: [
            {
              context: ['/api', '/services', '/management', '/swagger-resources', '/v2/api-docs', '/v3/api-docs'],
              target: `http${options.tls ? 's' : ''}://localhost:8080`,
              secure: false,
              changeOrigin: options.tls
            }
          ],
          watchOptions: {
            ignored: ['**/node_modules', utils.root('src/test')]
          },
          https: options.tls,
          historyApiFallback: true
        }
    

    I didn't have any validation errors neither now nor then. But I had to change regexps after switching from ignore to ignored. Should I have validation errors before the change or after it?

  9. alexander-akait commented on Apr 21, 2022

    @alexander-akait
    Member

    Yes, it should be validation error, @snitin315 can you look at this?

  10. snitin315 commented on Apr 21, 2022

    @snitin315
    Contributor

    Yes. I will look into this.

  11. snitin315 commented on Apr 23, 2022

    @snitin315
    Contributor

    So, this config is for v3, in which we had watchOptions property with type: object only, hence there was no error.

    "watchOptions": {
    "type": "object"
    },
    "writeToDisk": {

    In v4 we moved this to static.watch which also has type: object only, we have not defined specific property because options are from chokidar which can change anytime and we will have to change them again in our schema.

    "watch": {
    "anyOf": [
    {
    "type": "boolean",
    "cli": {
    "negatedDescription": "Does not watch for files in static content directory."
    }
    },
    {
    "type": "object",
    "description": "Options for watch.",
    "link": "https://github.com/paulmillr/chokidar#api"
    }
    ],
    "description": "Watches for files in static content directory.",
    "link": "https://webpack.js.org/configuration/dev-server/#watch"
    }
    }
    },

  12. snitin315 commented on Apr 23, 2022

    @snitin315
    Contributor

    Similar is the case with other options as well which uses external API like historyAPIFallback, bonjour etc

  13. alexander-akait commented on Apr 24, 2022

    @alexander-akait
    Member

    We need to add additionalProperties: false, let's do it

  14. marekdedic commented on Feb 9, 2023

    @marekdedic

    Hi,
    I'm getting this problem without having the devServer key in my config at all...

    The repo is skaut/shared-drive-mover

  15. bogdan-panteleev commented on May 9, 2023

    @bogdan-panteleev

    Same for me. Just configured webpack as follows. And if I run webpack --watch, then I have webpack recompiling the project endlessly.

    Eventually I just switched to ESBuild.

    package.json

    {
      "name": "grokking_algorithms",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "binary_search": "cd src && tsc binary-search.ts && node binary-search.js",
        "start": "webpack --watch"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@types/node": "^20.1.1",
        "prettier": "^2.8.8",
        "ts-loader": "^9.4.2",
        "ts-node": "^10.9.1",
        "tsconfig-paths": "^4.2.0",
        "typescript": "^5.0.4",
        "webpack": "^5.82.0",
        "webpack-cli": "^5.1.0"
      }
    }

    webpack.config.js

    const webpack = require('webpack');
    const path = require('path');
    
    module.exports = {
      entry: './src/main.ts',
      mode: 'development',
      target: 'node',
      module: {
        rules: [
          {
            test: /\.ts$/,
            loader: 'ts-loader',
            exclude: [/test/, /\.spec\.ts$/, /\.e2e-spec\.ts$/],
          },
        ],
      },
      resolve: {
        extensions: ['.ts', '.json', '.js'],
      },
      plugins: [],
      output: {
        path: path.join(__dirname, 'dist'),
        filename: 'main.js',
        library: {
          name: 'handler',
          type: 'umd',
        },
      },
      externals: [],
      optimization: {
        minimize: false,
      },
    };
  16. samir-kamble commented on Jul 17, 2023

    @samir-kamble

    Same for me. Just configured webpack as follows. And if I run webpack --watch, then I have webpack recompiling the project endlessly.

    Eventually I just switched to ESBuild.

    package.json

    {
      "name": "grokking_algorithms",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "binary_search": "cd src && tsc binary-search.ts && node binary-search.js",
        "start": "webpack --watch"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@types/node": "^20.1.1",
        "prettier": "^2.8.8",
        "ts-loader": "^9.4.2",
        "ts-node": "^10.9.1",
        "tsconfig-paths": "^4.2.0",
        "typescript": "^5.0.4",
        "webpack": "^5.82.0",
        "webpack-cli": "^5.1.0"
      }
    }

    webpack.config.js

    const webpack = require('webpack');
    const path = require('path');
    
    module.exports = {
      entry: './src/main.ts',
      mode: 'development',
      target: 'node',
      module: {
        rules: [
          {
            test: /\.ts$/,
            loader: 'ts-loader',
            exclude: [/test/, /\.spec\.ts$/, /\.e2e-spec\.ts$/],
          },
        ],
      },
      resolve: {
        extensions: ['.ts', '.json', '.js'],
      },
      plugins: [],
      output: {
        path: path.join(__dirname, 'dist'),
        filename: 'main.js',
        library: {
          name: 'handler',
          type: 'umd',
        },
      },
      externals: [],
      optimization: {
        minimize: false,
      },
    };

    Did this stopped infinite loop problem ? Also, I did not see webpack.config.js file. I have webpack.custom.js file.

    Do I need to create a file with that name?

  17. samir-kamble commented on Jul 17, 2023

    @samir-kamble

    We need to add additionalProperties: false, let's do it

    Where do we need to add it?

  18. vbansal2 commented on Nov 1, 2023

    @vbansal2

    is there any update on this issue?

  19. OZZlE commented on Jan 11, 2024

    @OZZlE

    watchpack

    I tried even setting watch to false and it still does it

  20. alexander-akait commented on Jan 11, 2024

    @alexander-akait
    Member

    There are a lot of different problems here, please provide reproducible test repo before ask a help, without it we can't help you

  21. OZZlE commented on Jan 12, 2024

    @OZZlE

    package.json

    "scripts": {
        "webpack-dev-server": "webpack-dev-server --env=epidev --config webpack.config.dev.js",
    },
    "devDependencies": {
      "@babel/core": "^7.20.5",
      "@babel/plugin-proposal-class-properties": "^7.18.6",
      "@babel/plugin-transform-runtime": "^7.19.6",
      "@babel/preset-env": "^7.20.2",
      "@babel/preset-react": "^7.18.6",
      "@frctl/fractal": "^1.5.14",
      "@frctl/nunjucks": "^1.0.3",
      "@testing-library/jest-dom": "^5.16.5",
      "@testing-library/react": "^13.4.0",
      "autoprefixer": "^10.4.13",
      "babel-eslint": "^10.1.0",
      "babel-loader": "^9.1.0",
      "cpx": "^1.5.0",
      "css-loader": "^6.7.2",
      "css-mediaquery": "^0.1.2",
      "cssnano": "^5.1.14",
      "eslint": "^7.32.0",
      "eslint-config-airbnb-base": "^15.0.0",
      "eslint-loader": "^4.0.2",
      "eslint-plugin-import": "^2.26.0",
      "eslint-plugin-react": "^7.31.11",
      "file-loader": "^6.2.0",
      "husky": "^8.0.2",
      "jest": "^29.3.1",
      "jest-environment-jsdom": "^29.3.1",
      "lint-staged": "^13.1.0",
      "mini-css-extract-plugin": "^2.7.2",
      "npm-run-all": "^4.1.5",
      "postcss": "^8.4.20",
      "postcss-cli": "^10.1.0",
      "postcss-flexbugs-fixes": "^5.0.2",
      "postcss-focus": "^5.0.1",
      "postcss-loader": "^7.0.2",
      "prettier": "^2.8.1",
      "script-loader": "^0.7.2",
      "style-loader": "^3.3.1",
      "stylelint": "^14.16.0",
      "stylelint-config-recommended-scss": "^8.0.0",
      "stylelint-scss": "^4.3.0",
      "stylelint-webpack-plugin": "^3.3.0",
      "svg-sprite-loader": "^6.0.11",
      "svgo": "^3.0.2",
      "svgo-loader": "^3.0.3",
      "webpack": "^5.75.0",
      "webpack-bundle-analyzer": "^4.7.0",
      "webpack-cli": "^5.0.1",
      "webpack-dev-server": "^4.11.1",
      "webpack-merge": "^5.8.0"
    },
    "engines": {
      "node": ">=16"
    },
    "dependencies": {
      "@babel/plugin-proposal-decorators": "^7.20.5",
      "animate.css": "^4.1.1",
      "babel-polyfill": "^6.26.0",
      "body-scroll-lock": "^4.0.0-beta.0",
      "focus-trap": "^7.2.0",
      "foundation-sites": "^6.7.5",
      "iframe-resizer": "^4.3.2",
      "ion-rangeslider": "^2.3.1",
      "jquery": "^3.6.2",
      "jquery-modal": "^0.9.2",
      "jquery.scrollto": "^2.1.3",
      "js-cookie": "^3.0.1",
      "mobx": "^6.7.0",
      "mobx-react": "^7.6.0",
      "picturefill": "^3.0.3",
      "rangeslider.js": "^2.3.3",
      "react": "^18.2.0",
      "react-dom": "^18.2.0",
      "react-modal": "^3.16.1",
      "react-responsive": "^9.0.2",
      "sanitize.css": "^13.0.0",
      "sass": "^1.69.5",
      "sass-loader": "^13.3.2",
      "scrollprogress": "^3.0.2",
      "slick-carousel": "^1.8.1",
      "stickyfilljs": "^2.1.0",
      "svgxuse": "^1.2.6",
      "universal-cookie": "^4.0.4",
      "whatwg-fetch": "^3.6.2"
    }
    

    webpack.config.dev.js

    const path = require('path');
    const webpack = require('webpack');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
    const StyleLintPlugin = require('stylelint-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    /*eslint-disable */
    var dirname = __dirname;
    /*eslint-enable */
    
    const resolve = {
      modules: [
        // path.resolve(dirname, 'components/atoms/'),
        // path.resolve(dirname, 'components/molecules/'),
        // path.resolve(dirname, 'components/organisms/'),
        // path.resolve(dirname, 'static/scripts'),
        // path.resolve(dirname, 'static/styles'),
        // path.resolve(dirname, 'static'),
        // path.resolve(dirname, 'node_modules/foundation-sites/scss'),
        'node_modules',
      ],
      extensions: ['.js', '.jsx'],
    };
    const eslintRule = {
      enforce: 'pre',
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'eslint-loader',
      options: {
        configFile: '.eslintrc.js',
      },
    };
    const getScssRule = (env) => {
      return {
        test: /\.scss$/,
        use: [
          {
            loader: 'style-loader',
          },
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  /* eslint-disable global-require */
                  require('postcss-focus')(),
                  require('autoprefixer')({ grid: true }),
                  require('cssnano')(),
                  /* eslint-enable global-require */
                ],
              },
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sassOptions: {
                includePaths: ['node_modules'],
              }
            },
          },
        ],
      }
    };
    const fileRule = {
      test: /\.(svg|png|jpe?g|gif|woff|woff2|eot|ttf|otf)$/,
      // exclude: [
      //   path.resolve('./static/icons/**/*'),
      //   path.resolve('./static/fonts/icons.svg'),
      // ],
      exclude: path.resolve('./static/icons'),
      use: [
        {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'static/fonts/',
          },
        },
      ],
    };
    const svgSpriteRule = {
      test: /\.svg$/,
      include: path.resolve('./static/icons'),
      use: [
        {
          loader: 'svg-sprite-loader',
          options: {
            extract: true,
            spriteFilename: 'static/images/icons.svg',
            esModule: false,
          },
        },
        'svgo-loader',
      ],
    };
    
    const moduleConfig = (origEnv) => {
      var apiEnvTarget = 'production';
      var env = 'development';
    
      return {
        mode: 'development',
        // devtool: origEnv.epi ? 'source-map' : '',
        resolve,
        entry: {
          main: [
            path.resolve(dirname, 'static/styles/main.scss')
          ],
          react: [
    
            // was main
            path.resolve(dirname, 'static/scripts/main.js'),
            // path.resolve(dirname, 'static/styles/main.scss'),
    
            path.resolve(dirname, 'static/scripts/react-bundle.js')
          ],
        },
        output: {
          path: path.resolve(dirname, 'dist'),
          publicPath: '/',
          filename: './static/scripts/[name].module.js',
          clean: false,
        },
        module: {
          rules: [
            eslintRule,
            {
              test: /\.(js|jsx)$/,
              exclude: /node_modules\/(?![foundation-sites])/,
              loader: 'babel-loader',
              options: { 
                "presets": [
                  [
                    "@babel/preset-env",
                    {
                      "targets": { "esmodules": true },
                    }
                  ],
                  "@babel/preset-react"
                ],
              }
            },
            getScssRule(env),
            fileRule,
            svgSpriteRule,
          ],
        },
        plugins: [
          new StyleLintPlugin({
            configFile: './.stylelintrc',
          }),
          new MiniCssExtractPlugin({
            filename: './static/styles/[name].css',
          }),
          new SpriteLoaderPlugin(),
          new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            foundation: 'Foundation'
          }),
          // this is used to import environment specific modules like api request etc, ie api will be mocked in development
          new webpack.NormalModuleReplacementPlugin(/(.*)-ENVIRONMENT_TARGET(\.*)/, function(resource) {
            resource.request = resource.request.replace(/-ENVIRONMENT_TARGET/, `-${apiEnvTarget}`);
          }),
          new HtmlWebpackPlugin({
            title: 'Development',
          })      
        ],
        devServer: {
          watchFiles: [
            /components\//,
            /static\/[^/]*\/*.js/,
            /static\/[^/]*\/*.scss/,
          ],
          static: {
            watch: {
              usePolling: false,
              ignored: [
                /dist\//, 
                /docs\//, 
                /node_modules\//,
                /public\//, 
                /static\/icons\//, 
                /static\/fonts\//, 
              ],
            },
          },      
          devMiddleware: {
            index: true,
            mimeTypes: { phtml: 'text/html' },
            publicPath: path.join(dirname, 'public'),
            // publicPath: '/',
            serverSideRender: false,
            writeToDisk: true,
          },
        },
        optimization: {
          splitChunks: {
            cacheGroups: {
              styles: {
                name: 'styles',
                test: /\.css$/,
                chunks: 'all',
                enforce: true,
              },
            },
          },
        },
        watch: false,
        watchOptions: {
          ignored: [
            'dist/**/*', 
            'docs/**/*', 
            'node_modules/**/*',
            'public/**/*', 
            'static/icons/**/*', 
          ],
        },    
        stats: {warnings:false},
      };
    }
    module.exports = function config(env, argv = {}) {
      return moduleConfig({
        ...env,
        epi: true,
        epidev: true,
      }, argv);
    };
    
  22. alexander-akait commented on Feb 5, 2024

    @alexander-akait
    Member

    @OZZlE What are steps to reproduce the problem? I see you have writeToDisk: true and

    watchFiles: [
            /components\//,
            /static\/[^/]*\/*.js/,
            /static\/[^/]*\/*.scss/,
          ],
    

    please make sure you ignore generated webpack file, otherwise you can have a loop of reloading

  23. alexander-akait commented on Feb 8, 2024

    @alexander-akait
    Member

    The original problem was resolved. Anyway feel free to feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions