title: Webpack 4: FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
body: <p>After upgrading to Webpack 4.16.3 from webpack 3.x I ran into the error below when running <code>npm run dev</code> for +/- 20 min. I get this error on a huge VueJS project. On other projects I have no errors so far. I've looked up some similar issues on Github and Stackoverflow, most of them seem related to Angular. I tried the following, but the problem seems to persist.</p>
  
  <pre><code>--max_old_space_size=4096
  </code></pre>
  
  <p>The one thing I did notice was that the error happens when saving a file with a faulty import or export statement.</p>
  
  <p>The error log:</p>
  
  <pre><code>[hardsource:d5167ca7] Using 732 MB of disk space.
  [hardsource:d5167ca7] Last compilation did not finish saving. Building new cache.
   95% emitting HtmlWebpackPlugin                                                    
  &lt;--- Last few GCs ---&gt;
  
  [6805:0x2babd20]   877537 ms: Mark-sweep 1344.1 (1396.8) -&gt; 1342.6 (1394.9) MB, 455.6 / 0.1 ms  (average mu = 0.378, current mu = 0.000) last resort GC in old space requested
  [6805:0x2babd20]   877899 ms: Mark-sweep 1342.6 (1394.9) -&gt; 1342.6 (1394.9) MB, 362.1 / 0.1 ms  (average mu = 0.250, current mu = 0.000) last resort GC in old space requested
  
  
  &lt;--- JS stacktrace ---&gt;
  
  ==== JS stack trace =========================================
  
      0: ExitFrame [pc: 0xbd4a57041bd]
  Security context: 0xeb4c809e6c9 &lt;JSObject&gt;
      1: byteLength(aka byteLength) [0x2eacaef7f969] [buffer.js:530] [bytecode=0x13d2a9725f69 offset=204](this=0x2dd8909822e1 &lt;undefined&gt;,string=0x3f1ce1e95801 &lt;Very long string[23843934]&gt;,encoding=0xeb4c80b1a99 &lt;String[4]: utf8&gt;)
      2: arguments adaptor frame: 3-&gt;2
      3: fromString(aka fromString) [0xfa9ba97d19] [buffer.js:341] [bytecode=0x13d2a9720091 offset...
  
  FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
   1: 0x8b5f80 node::Abort() [node]
   2: 0x8b5fcc  [node]
   3: 0xab730e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
   4: 0xab7528 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
   5: 0xea5152  [node]
   6: 0xeb43c6 v8::internal::Heap::AllocateRawWithRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [node]
   7: 0xe828af v8::internal::Factory::NewRawTwoByteString(int, v8::internal::PretenureFlag) [node]
   8: 0xfc792f v8::internal::String::SlowFlatten(v8::internal::Handle&lt;v8::internal::ConsString&gt;, v8::internal::PretenureFlag) [node]
   9: 0xab4a44 v8::internal::String::Flatten(v8::internal::Handle&lt;v8::internal::String&gt;, v8::internal::PretenureFlag) [node]
  10: 0xac2d8f v8::String::Utf8Length() const [node]
  11: 0x8ce702  [node]
  12: 0xb44409  [node]
  13: 0xb44f79 v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
  14: 0xbd4a57041bd 
  Aborted (core dumped)
  </code></pre>
  
  <p>My <code>webpack.base.conf.js</code></p>
  
  <pre><code>'use strict'
  const path = require('path')
  const utils = require('./utils')
  const config = require('./config')
  const vueLoaderConfig = require('./vue-loader.conf')
  const VueLoaderPlugin = require('vue-loader/lib/plugin')
  var HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
  
  function resolve (dir) {
    return path.join(__dirname, '..', dir)
  }
  
  const createLintingRule = () =&gt; ({
    test: /\.(js|vue)$/,
    loader: 'eslint-loader',
    enforce: 'pre',
    include: [resolve('resources/assets/js')],
    options: {
      formatter: require('eslint-friendly-formatter'),
      emitWarning: !config.dev.showEslintErrorsInOverlay,
    },
  })
  
  module.exports = {
    mode: (process.env.NODE_ENV === 'production')
      ? 'production'
      : 'development',
    context: path.resolve(__dirname, '../'),
    entry: {
      app: ['./resources/assets/sass/app.scss', './resources/assets/js/main.js'],
    },
    plugins: [
      new VueLoaderPlugin(),
      new HardSourceWebpackPlugin(),
      // You can optionally exclude items that may not be working with HardSource
      // or items with custom loaders while you are actively developing the
      // loader.
      new HardSourceWebpackPlugin.ExcludeModulePlugin([
        {
          // HardSource works with mini-css-extract-plugin but due to how
          // mini-css emits assets, assets are not emitted on repeated builds with
          // mini-css and hard-source together. Ignoring the mini-css loader
          // modules, but not the other css loader modules, excludes the modules
          // that mini-css needs rebuilt to output assets every time.
          test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,
        },
        {
          test: /my-loader/,
          include: path.join(__dirname, 'vendor'),
        },
      ])
    ],
    output: {
      path: config.build.assetsRoot,
      filename: '[name].js',
      publicPath:
        process.env.NODE_ENV === 'production'
          ? config.build.assetsPublicPath
          : config.dev.assetsPublicPath,
    },
    resolve: {
      modules: ['node_modules'],
      extensions: ['.js', '.vue', '.json'],
      alias: {
        clockwork: resolve('resources/assets/js'),
      },
    },
    module: {
      rules: [
        ...(config.dev.useEslint ? [createLintingRule()] : []),
        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: vueLoaderConfig,
        },
        {
          test: /\.js$/,
          loader: 'babel-loader',
          include: [
            resolve('resources/assets/js'),
            resolve('node_modules/webpack-dev-server/client')
          ],
        },
        {
          test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
          loader: 'url-loader',
          options: {
            limit: 10000,
            name: utils.assetsPath('img/[name].[hash:7].[ext]'),
          },
        },
        {
          test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
          loader: 'url-loader',
          options: {
            limit: 10000,
            name: utils.assetsPath('media/[name].[hash:7].[ext]'),
          },
        },
        {
          test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
          loader: 'url-loader',
          options: {
            limit: 10000,
            name: utils.assetsPath('fonts/[name].[hash:7].[ext]'),
          },
        },
      ],
    },
    node: {
      // prevent webpack from injecting useless setImmediate polyfill because Vue
      // source contains it (although only uses it if it's native).
      setImmediate: false,
      // prevent webpack from injecting mocks to Node native modules
      // that does not make sense for the client
      dgram: 'empty',
      fs: 'empty',
      net: 'empty',
      tls: 'empty',
      child_process: 'empty',
    },
  };
  </code></pre>
  
  <p>My <code>webpack.dev.conf.js</code></p>
  
  <pre><code>'use strict'
  const utils = require('./utils')
  const webpack = require('webpack')
  const config = require('./config')
  const merge = require('webpack-merge')
  const baseWebpackConfig = require('./webpack.base.conf')
  // const CopyWebpackPlugin = require('copy-webpack-plugin')
  const path = require('path')
  const HtmlWebpackPlugin = require('html-webpack-plugin')
  // const AutoDllPlugin = require('autodll-webpack-plugin');
  const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
  const portfinder = require('portfinder')
  
  const HOST = process.env.HOST
  const PORT = process.env.PORT &amp;&amp; Number(process.env.PORT)
  
  const devWebpackConfig = merge(baseWebpackConfig, {
    module: {
      rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
    },
    // cheap-module-eval-source-map is faster for development
    devtool: config.dev.devtool,
  
    // these devServer options should be customized in /config/index.js
    devServer: {
      clientLogLevel: 'warning',
      historyApiFallback: {
        rewrites: [
          { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
        ],
      },
      hot: true,
      contentBase: false, // since we use CopyWebpackPlugin.
      compress: true,
      host: HOST || config.dev.host,
      port: PORT || config.dev.port,
      open: config.dev.autoOpenBrowser,
      overlay: config.dev.errorOverlay
        ? { warnings: false, errors: true }
        : false,
      publicPath: config.dev.assetsPublicPath,
      proxy: config.dev.proxyTable,
      quiet: true, // necessary for FriendlyErrorsPlugin
      watchOptions: {
        poll: config.dev.poll,
      }
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env': require('./config/dev.env')
      }),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
      new webpack.NoEmitOnErrorsPlugin(),
      // https://github.com/ampedandwired/html-webpack-plugin
      new HtmlWebpackPlugin({
        filename: 'index.html',
        template: 'webpack/index.html',
        inject: true
      })
    ]
  })
  
  module.exports = new Promise((resolve, reject) =&gt; {
    portfinder.basePort = process.env.PORT || config.dev.port
    portfinder.getPort((err, port) =&gt; {
      if (err) {
        reject(err)
      } else {
        // publish the new Port, necessary for e2e tests
        process.env.PORT = port
        // add port to devServer config
        devWebpackConfig.devServer.port = port
  
        // Add FriendlyErrorsPlugin
        devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
          compilationSuccessInfo: {
            messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
          },
          onErrors: config.dev.notifyOnErrors
            ? utils.createNotifierCallback()
            : undefined
        }))
  
        resolve(devWebpackConfig)
      }
    })
  })
  </code></pre>
  
  <p>EDIT: After some digging around and with the help of the developers of Webpack we concluded that this is not an issue with Webpack. Most likely this is a memory leak caused by the sass-loader. I still haven't found a solution, but will keep this updated.</p>
  
  <p>What happens with this memory leak is that when you edit the same file multiple times the dev server begins flooding your memory in small increments every time the file is saved. Node then crashes when the memory limit is reached. </p>