Cannot read property ‘replace’ of undefined whit Invalid JSON

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Webpack exit abruptly when a JSON is not formatted correctly when a server is running.

I’m using webpack 4.6.0, I run a local server using serve from ‘browser-sync’
I DON’T use json-loader in webpack-config as it is my understanding that it handles it by default now.

I run a local server, do a change to a JSON file that makes the JSON invalid, at this point webpack exit abruptly with the following error:

/code/program/node_modules/webpack/lib/JsonGenerator.js:10
    JSON.stringify(data).replace(
                        ^

TypeError: Cannot read property 'replace' of undefined
    at stringifySafe (/code/program/node_modules/webpack/lib/JsonGenerator.js:10:22)
    at JsonGenerator.generate (/code/program/node_modules/webpack/lib/JsonGenerator.js:36:53)
    at NormalModule.source (/code/program/node_modules/webpack/lib/NormalModule.js:413:33)
    at ModuleTemplate.render (/code/program/node_modules/webpack/lib/ModuleTemplate.js:43:31)
    at modules.map.module (/code/program/node_modules/webpack/lib/Template.js:157:28)
    at Array.map (<anonymous>)
    at Function.renderChunkModules (/code/program/node_modules/webpack/lib/Template.js:154:28)
    at HotUpdateChunkTemplate.render (/code/program/node_modules/webpack/lib/HotUpdateChunkTemplate.js:48:34)
    at compilation.hooks.additionalChunkAssets.tap (/code/program/node_modules/webpack/lib/HotModuleReplacementPlugin.js:165:48)
    at SyncHook.eval (eval at create (/code/program/node_modules/tapable/lib/HookCodeFactory.js:17:12), <anonymous>:7:1)
    at SyncHook.lazyCompileHook [as _call] (/code/program/node_modules/tapable/lib/Hook.js:35:21)
    at hooks.optimizeTree.callAsync.err (/code/program/node_modules/webpack/lib/Compilation.js:944:37)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/code/program/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/code/program/node_modules/tapable/lib/Hook.js:35:21)
    at Compilation.seal (/code/program/node_modules/webpack/lib/Compilation.js:890:27)
    at hooks.make.callAsync.err (/code/program/node_modules/webpack/lib/Compiler.js:481:17)
    at _done (eval at create (/code/program/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:9:1)
    at _err1 (eval at create (/code/program/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:32:22)
    at _addModuleChain (/code/program/node_modules/webpack/lib/Compilation.js:758:12)
    at processModuleDependencies.err (/code/program/node_modules/webpack/lib/Compilation.js:697:9)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickDomainCallback (internal/process/next_tick.js:218:9)

If the current behavior is a bug, please provide the steps to reproduce.
Clone the repo: https://github.com/Tonio31/Webpack4-Bug-with-JSON.git

  • npm install
  • npm start
  • Modify Json file in client/app/mockBackEndResponse/

What is the expected behavior?
Webpack shows an error in the console because the JSON is not formatted correctly but don’t exit, when the JSON is fixed, webpack automatically compile without errors

If this is a feature request, what is motivation or use case for changing the behavior?

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.
Webpack: 4.6.0
browser-sync: 2.23.6
StackOverflow question:

Overview of webpack config:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackNotifierPlugin = require('webpack-notifier');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  devtool: 'source-map',
  entry: {},
  resolve: {
    modules: [
      path.resolve(__dirname),
      path.resolve(__dirname, 'node_modules')
    ],
    extensions: [ '.js' ],
    alias: {
      app: 'client/app',
      common: 'client/app/common',
      components: 'client/app/components'
    }
  },

  output: {
    filename: '[name].bundle.js',
    chunkFilename: '[name].bundle.js',
    publicPath: '/',
    path: path.resolve(__dirname, 'client')
  },

  mode: 'development';

  module: {

    rules : [
      {
        test: /\.js$/,
        exclude: [ /app\/lib/, /node_modules/],
        enforce: 'pre',
        use: [
          {
            loader: 'eslint-loader',
            options: {
              failOnWarning: false,
              failOnError: true
            }
          },
        ],
      },
      {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        'postcss-loader',
      ]
      },
      {
        test: /\.(scss|sass)/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true
            }
          },
          {
            loader: 'sass-loader',
            options: {
              includePaths: [ path.resolve(__dirname, './client/app') ],
              sourceMap: true
            }
          },
        ]
      },
      {
        test: /\.html$/,
        use: [
          {
            loader: 'raw-loader',
            options: {
              minimize: false
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: [ /app\/lib/, /node_modules/],
        use: [
          {
            loader: 'ng-annotate-loader?add=true&single_quotes=true'
          },
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.svg/,
        use: [
          {
            loader: 'svg-url-loader'
          }
        ]
      },
      {
        test: /\.(png|jpg)$/,
        use: [
          {
            loader: 'url-loader?limit=1024'
          }
        ]
      },
      {
        test: /\.woff$/,
        use: [
          {
            loader: 'url-loader?limit=65000&mimetype=application/font-woff&name=public/fonts/[name].[ext]'
          }
        ]
      },
      {
        test: /\.woff2$/,
        use: [
          {
            loader: 'url-loader?limit=65000&mimetype=application/font-woff2&name=public/fonts/[name].[ext]'
          }
        ]
      },
      {
        test: /\.[ot]tf$/,
        use: [
          {
            loader: 'url-loader?limit=65000&mimetype=application/octet-stream&name=public/fonts/[name].[ext]'
          }
        ]
      },
      {
        test: /\.eot$/,
        use: [
          {
            loader: 'url-loader?limit=65000&mimetype=application/vnd.ms-fontobject&name=public/fonts/[name].[ext]'
          }
        ]
      }
    ],

    noParse: [
      '/node_modules/d3-cloud/build/d3.layout.cloud.js',
    ]
  },
  plugins: [

    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require("./package.json").version)
    }),

    new webpack.ProvidePlugin({
      c3: 'c3',
      Bugsnag: 'bugsnag-js'
    }),

    // This is used to have a banner shown to the user to "Add to home screen"
    // It works with the service-worker called in app.js
    new CopyWebpackPlugin([
      {
        from: './config',
        to: path.resolve(__dirname, 'dist/')
      },
      {
        from: './assets/**/*',
        to: path.resolve(__dirname, 'dist/')
      },
    ]),

    // Injects bundles in your index.html instead of wiring all manually.
    // It also adds hash to all injected assets so we don't have problems
    // with cache purging during deployment.
    new HtmlWebpackPlugin({
      template: 'client/indexMockBackEnd.html',
      //template: 'client/index.html',
      inject: 'body',
      hash: true,
      favicon: 'client/app/common/favicon/favicon.ico'
    }),


    new webpack.DefinePlugin({
      ENVIRONMENT: JSON.stringify('development'),
      BROCHURE_HOME_URL: JSON.stringify(`https://pl.dev`)
    }),

    // Adds webpack HMR support. It act's like livereload,
    // reloading page after webpack rebuilt modules.
    // It also updates stylesheets and inline assets without page reloading.
    new webpack.HotModuleReplacementPlugin(),

    // displays desktop notifications on MacOS
    new WebpackNotifierPlugin(),
  ],

  optimization: {
    namedModules: true, // NamedModulesPlugin()
    splitChunks: {
      chunks: "all"
    },
    runtimeChunk: true,
    concatenateModules: true //ModuleConcatenationPlugin
  }
};

Author: Fantashit

4 thoughts on “Cannot read property ‘replace’ of undefined whit Invalid JSON

  1. as @badpunman points out above, there seems to be no way to require() files with .json extension that are not valid JSON in webpack – even with raw-loader! or forcing the loader in config to be raw does not help, although it fails in a different place;

        at doBuild.err (..webpack/lib/NormalModule.js:375:32)
        at runLoaders (..webpack/lib/NormalModule.js:272:12)
        at ..loader-runner/lib/LoaderRunner.js:370:3
        at iterateNormalLoaders (..loader-runner/lib/LoaderRunner.js:211:10)
        at iterateNormalLoaders (..loader-runner/lib/LoaderRunner.js:218:10)
        at ..loader-runner/lib/LoaderRunner.js:233:3
        at runSyncOrAsync (..loader-runner/lib/LoaderRunner.js:130:11)
        at iterateNormalLoaders (..loader-runner/lib/LoaderRunner.js:229:2)
    

    The only workaround I’ve discovered so far is using another extension than .json. This might be a separate issue, though?

  2. The only workaround I’ve discovered so far is using another extension than .json.

    add type: "javascript/auto" to the rule.

  3. Could this be due to the json file encoding? I have run into this same error due to my json being encoded with BOM. Changing to just utf-8 solved it for me.

Comments are closed.