Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.lazy not working in production mode

I have a react app running, and I wanted to add route based code-splitting using React.lazy to it.

Currently my code is,

import { PureComponent, cloneElement, Suspense, lazy } from 'react';
...
export const CartPage = lazy(() => import(/* webpackMode: "lazy", webpackPrefetch: true */ 'Route/CartPage'));
...
<Suspense fallback={ this.renderFallbackPage() }>
    <NoMatchHandler>
       <Switch>
          ...
             <Route path="/cart" exact component={ CartPage } />
          ...
       </Switch>
    </NoMatchHandler>
</Suspense>

Only mentioned the relevant parts here to make it compact.

Now the problem is, in webpack-dev-server, it runs perfectly, but when I run npm run build, and go to /cart the code breaks. After following the link mentioned for the error, this is the message

Element type is invalid. Received a promise that resolves to: function i(e){var r;return
r=t.call(this,e)||this,T()(y?!e.wrapperProps[d]:!e[d],"Passing redux store in props has
been removed and does not do anything.
"+P),r.selectDerivedProps=n(),r.selectChildElement=function(){var t,e,n,r;return
function(i,o,a){return(o!==t||a!==e||r!==i)&&(t=o,e=a,r=i,n=m.a.createElement(i,Object(O.a)
({},o,{ref:a}))),n}}
(),r.indirectRenderWrappedComponent=r.indirectRenderWrappedComponent.bind(function(t)
{if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been 
called");return t}(r)),r}. Lazy element type must resolve to a class or function.

A couple of common troubleshooting which I already did

  1. In the CartPage component, I have done export default connect(mapStateToProps, mapDispatchToProps)(CartPage);
  2. React version is 16.13.1

And the weird part is, Received a promise that resolves to: function.... It is a function! But then it complains Lazy element type must resolve to a class or function. It doesn't make any sense to me.

What could be wrong?

EDIT

The Route/CartPage/index.js has the following

import { PureComponent } from 'react';

export default class CartPage extends PureComponent {
     render() {
         return <h1>Test</h1>;
     }
}

I deliberately made it as simple as possible. But still the same error came. But with different parameters. Now the error is this

Element type is invalid. Received a promise that resolves to: function
t(){return c()(this,t),r.apply(this,arguments)}. Lazy element type 
must resolve to a class or function.

EDIT 2

I removed the following lines from my webpack.config.js. And it started to work! Still no idea why though

const MinifyPlugin = require('babel-minify-webpack-plugin');
...    
plugins: [
    ...,
    new MinifyPlugin({
        removeConsole: false,
        removeDebugger: false
    }, {
        comments: false
    })
]
...
like image 968
Jay Ghosh Avatar asked May 30 '20 16:05

Jay Ghosh


People also ask

Is lazy loading available in React?

React Lazy Load is an easy-to-use React component which helps you defer loading content in predictable way. It's fast, You can also use component inside scrolling container, such as div with scrollbar. It will be found automatically.

Does React lazy help with performance?

Lazy loading is a great technique for optimizing the performance of your React app. It focuses on loading a component only when it is needed. It enables you to speed up the render time of your app significantly.

Can we use React lazy in react native?

Yes, It's in React-Native. You can use it for better performance. I hope it will help you to understand!

What is lazy () in React?

The React. lazy() function allows you to render a dynamic import as a normal component. It makes it simple to construct components that are loaded dynamically yet rendered as regular components.


1 Answers

Like I mentioned in the question, the babel-minify-webpack-plugin was causing the issue for some reason. My guess is, they were saving function definitions as strings to save space, and using eval somewhere inside its logic. But that's just my guess.

Anyway, the Github page for babel-minify-webpack-plugin says that it is deprecated, so I ended up removing that from my project, and using the terser-webpack-plugin instead. Everything seems to work now, and the build time is also significantly reduced. My advice is, avoid using the babel-minify-webpack-plugin and use some other minification plugin instead

like image 149
Jay Ghosh Avatar answered Oct 26 '22 19:10

Jay Ghosh