Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
OleksiL opened this issue Apr 1, 2022 · 23 comments · May be fixed by #4424
Closed

Comments

@OleksiL
Copy link

OleksiL commented Apr 1, 2022

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.

@alexander-akait
Copy link
Member

Please firstly update webpack-dev-server to v4

@OleksiL
Copy link
Author

OleksiL commented Apr 1, 2022

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?

@alexander-akait
Copy link
Member

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

@OleksiL
Copy link
Author

OleksiL commented Apr 4, 2022

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

@alexander-akait
Copy link
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)

@OleksiL
Copy link
Author

OleksiL commented Apr 20, 2022

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.

@alexander-akait
Copy link
Member

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

@OleksiL
Copy link
Author

OleksiL commented Apr 21, 2022

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?

@alexander-akait
Copy link
Member

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

@snitin315
Copy link
Member

Yes. I will look into this.

@snitin315
Copy link
Member

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

@snitin315
Copy link
Member

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

@alexander-akait
Copy link
Member

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

@marekdedic
Copy link

marekdedic commented Feb 9, 2023

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

The repo is skaut/shared-drive-mover

@bogdan-panteleev
Copy link

bogdan-panteleev commented May 9, 2023

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

@samir-kamble
Copy link

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?

@samir-kamble
Copy link

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

Where do we need to add it?

@vbansal2
Copy link

vbansal2 commented Nov 1, 2023

is there any update on this issue?

@OZZlE
Copy link

OZZlE commented Jan 11, 2024

watchpack

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

@alexander-akait
Copy link
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

@OZZlE
Copy link

OZZlE commented Jan 12, 2024

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

@alexander-akait
Copy link
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

@alexander-akait
Copy link
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
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants