React.lazy not working in production mode
Asked Answered
B

1

7

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
    })
]
...
Blubber answered 30/5, 2020 at 16:34 Comment(15)
did you find any solutions? I have the same problemOctennial
No. And the weird thing is, I installed a fresh React, and React.lazy works fine there. Not sure what I did wrong in my projectBlubber
please show us Route/CartPage codeKezer
you should use default export in this fileKezer
Can you share the code of CartPage file?Dupuy
@Dupuy I edited the question. Please have a lookBlubber
@Kezer I did export default. I edited the question now. Please have a lookBlubber
What happen if you render the CartPage component without router?Dupuy
@Dupuy you mean <CartPage /> instead of <Route path="/cart" exact component={ CartPage } />?Blubber
Yeah it is interesting if this is a issue with routeDupuy
@Dupuy I tried that and it still gives the same error. I don't even know how to debug it. Because in the error itself, it's saying that it is a function. But then says it expects a functionBlubber
Can u create a repo with a reproduction code?Dupuy
Let us continue this discussion in chat.Blubber
One possible reasoning could be that you haven't imported React in your component. Maybe try import React, { PureComponent } from 'react';Fonz
@ShubhamKhatri That is not it. I used the ProvidePlugin of webpack to make React globally point to reactBlubber
B
4

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

Blubber answered 6/6, 2020 at 16:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.