Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncaught TypeError: Cannot read property 'call' of undefined at __webpack_require__

I am using React.lazy to load some React classes on runtime so that they are not all loaded at once. My code works for production, but crashes when I am in development mode. (UPDATE: My code no longer works in production - see below).

The particular error message is very cryptic so hard to know exactly what the issue is:

Uncaught TypeError: Cannot read property 'call' of undefined at __webpack_require__ (main.js:64)

The above error occurred in one of your React components:
    in Unknown
    in Suspense
    in div (created by Main)
    in Main (created by Route)
    in Route (created by App)
    in Switch (created by App)
    in div (created by App)
    in Router (created by BrowserRouter)
    in BrowserRouter (created by App)
    in App

Consider adding an error boundary to your tree to customize error handling behavior.

Uncaught (in promise) TypeError: Cannot read property 'call' of undefined at __webpack_require__ (main.js:64)

Line 64 gives the following code:

modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

I have other React classes that are not having any issues.

The particular class file that I created is called Categories.js. As far as I know I am not loading the class any differently than any of the ones that are working. I have even tried renaming the class/file and have I have also removed most of my data out of it in case something in the file was causing the issue.

Here are the pertinent lines from my code:

import React, {Suspense} from 'react';
....
const Categories = React.lazy(()=> import('./Categories'))
....
return (
    <Suspense fallback={<div>Loading...</div>}>
        <Categories class_select={class_select} />
    </Suspense>
 )

If it helps here is my webpack.config.js file:

const HtmlWebPackPlugin = require("html-webpack-plugin");
const CopyPlugin = require('copy-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = (env, argv) => {

  const isProduction = (argv.mode === "production")
  return {

          module: {
            rules: [
              {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                  loader: "babel-loader",
                  options: {
                    plugins: [
                        "@babel/plugin-syntax-dynamic-import"
                    ]
                  }
                }
              },
              {
                test: /\.html$/,
                use: [
                  {
                    loader: "html-loader"
                  }
                ]
              }
            ]
          },
          ...(isProduction && {
                  optimization: {
                   // minimize: true,
                    minimizer: [
                        new TerserPlugin({
                                terserOptions: {
                                        extractComments: 'all',
                                        compress: {
                                                drop_console: true
                                        },

                                }
                        })
                    ],
                  }
          }),
          devtool: !isProduction && 'eval-source-map',
          plugins: [
            new HtmlWebPackPlugin({
              template: "./src/index.html",
              filename: "./index.html"
            }),
            new CopyPlugin([
              { from: 'src/css', to: 'css' }
            ])
          ]
     };
};

Questions

1) What is causing this error? 2) Why is it only being caused in dev mode but not production mode?

Update

My code no longer works in production either. I am getting the following error:

Uncaught (in promise) TypeError: Cannot read property 'call' of undefined at o (main.js:2). 

In fact it is even worse in production than dev. In production none of the React lazy classes are working. In dev it is only one of them that isn't working.

like image 416
kojow7 Avatar asked Sep 24 '19 05:09

kojow7


1 Answers

Process

In order to find a potential solution to this issue, I had to tinker with the optimization module, which was indeed the issue here, even when not enabled surprisingly. My best guess is that some parameters are set to default in production mode and not in dev mode and this causes the issues of imports and undefined properties.

I decided to try replicating the deployment environment and check if I could at least "break" the development as well and investigate the issue from here. These are the parameters that are different between production and development and that were suspect in causing the issue at hand (you can try yourself by switching to the opposite value to put your deployment like the development environment for example).

On the link I provided in the comment, the user was explaining that the issue was at deployment level and that the way the vendors chunk were built, were colliding with the main chunks and cuts the entry to one another. One of the solution was to use concatenateModules: false apparently, but to no avail, it didn't solve my issue. So I tried with the others and found the issue bellow.

Potential solution

in module.exports, the optimization object should be edited

optimization: {
    minimize: true,
    namedModules: true,
    namedChunks: true,
    removeAvailableModules: true,
    flagIncludedChunks: true,
    occurrenceOrder: false,
    usedExports: true,
    concatenateModules: true,
    sideEffects: false, // <----- in prod defaults to true if left blank
}

Edit: all of these parameters are set to their opposite between production and development, tweak them at your own leisure, some issues stems from them

Explanation

After switching all the parameters I found that the sideEffects one is the one that breaks things and I see why:

The sideEffects flag will break down imports into separate ones as follow, as per the documentation on sideEffects:

import { a, b } from "big-module-with-flag"

is rewritten to

import { a } from "big-module-with-flag/a";
import { b } from "big-module-with-flag/b";

And will try to optimize imports accordingly across the modules, which can cause issues in production. Normally this should help optimizing the size of the package by reducing the bundles, at the cost of removing some imports but can break things at import.

I hope the explanation was somewhat clear, if somebody has deeper knowledge on WebPack optimization, any documentation and enhancement would be welcome.

like image 166
Pierre Chevallier Avatar answered Sep 19 '22 02:09

Pierre Chevallier