Dynamic import not working

Hey there!

I’m trying to implement dynamic loading to split the code per page to minimise the main bundle size cause the app is slow…

I tried to check on the forum by finding relevant posts and imitate the logic. But the solution is no different than what’s done before. Is there any other thing that needs to be done other than dynamically loading all my components that are assigned to routes?

Like this:

import React, { lazy, Suspense } from 'react;
import { Switch, Router, Route } from 'react-router-dom';
const MyComponent = lazy(() => import('./MyComponent'));
...
return (
    <Router>
        <Switch>
            <Suspense fallback={<div>Loading...</div>}>
                <Route path="/" component={MyComponent} />
            </Suspense>
        </Switch>
    </Router

Thanks ahead!

What error are you getting?

Two tips:

1 - Try:

<Route path="/" component={props => <MyComponent {...props} />} />

I don’t remember why now but in some cases I had to do this in the compoment prop instead of just {MyComponent}.

2 - Export your component using default export and not named export.

This is an expensive route. This creates a new component everytime the route is rendered. Each re-render results to mount and unmount instead of just updating.

Instead, use the render props

<Route path="/" render={props => <MyComponent {...props} />} />
1 Like

Hi Filipe!
Thanks for your answer!

No error, what so ever…
And actually I have tried both of the tips. No help.

Any further ideas?

I’m using it like this. Seems to work?

import React, { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

import HomePage from './pages/HomePage';
import LoadingIndicator from './LoadingIndicator';

const Login = lazy(() => import('./pages/Login'));

const renderLoader = () => <LoadingIndicator />;

const Routing = ({ }) => {
  return (
    <Router>
      <div className="transition-container">
        <Switch>
          <Route exact path="/">
            <HomePage />
          </Route>
          <Route exact path="/login">
            <Suspense fallback={renderLoader()}>
              <Login />
            </Suspense>
          </Route>
          [...]

Thanks for sharing!

I don’t really see a difference with mine. They are identical almost.

Wonder if there’s any other trick that needs to be done for Meteor to handle this? I mean at the end client is served by the Meteor server and I would think that some configuration is necessary??

Without any error messages and knowing the structure of your app it is kinda hard to tell what ist going wrong.
One instance where those dynamic imports actually might fail is when trying to access the server on the local network without setting ROOT_URL. But then it logs all sorts of error messages:

Or could it be you are running into this problem?

1 Like

Here’s the app: GitHub - eminx/cocoso: community cooperation software

And the routes page is here: cocoso/Routes.jsx at master · eminx/cocoso · GitHub

As you see, lastly I tried @loadable but the result was same - no different…

What do you mean “no error whatsoever”, there should be plenty, e.g. that in Routes.jsx “CalendarContainer” is not even defined.
Also, I’m not sure how this should work, I’m not familiar with loadable, but I think the router doesn’t work because those container-files like ActivitiesContainer etc. are not returning React components. Sorry, I’m not using withTracker much.

Can you please confirm that lazy loading is not working?

In Chrome dev tools, press command-shift-p (Mac) or control-shift-p (Windows) to open the command menu. Select Show Coverage and click the Reload button and reload your home page, and Chrome will show you what has loaded.

Yeah, really there was no error - no difference to the state that it was before…

You’re right about the CalendarContainer - I missed it but it was still working. And I reckoned and defined it yesterday. Somehow the build system finds the component in the repo with the name of the file I think (if there is a file with the name of the component/var assigned to the route). I tested it by changing the name of the file and then it was a build error…

Actually you have a point! I have checked this before but it felt the same. Then I checked again and although it doesn’t seem like there’s a bundle per each page loading; the bundle I see is with the name of the initial page… Interesting!

I just checked my screenshot and it seems like this thing was the same before I implemented dynamic loading. And the bundle size is identical as well.

Anyhow though!

Very good. If you go to other pages, do you see the components for those pages loading at that time?

Your application structure is missing an imports folder.

It will load all files unless you put them in the imports folder.

4 Likes

Oh wow, I didn’t know the magic of the imports folder. Thanks!!

Nope, but I guess this was due to the missing imports folder

Dear @flean I wonder how the Meteor’s built-in imports folder logic coexists with React’s lazy loading?
Because according to the docs at the page you sent, it feels like React’s lazy is redundant if we do this way of Meteor…?

Perhaps React brings the code splitting feature, whereas with Meteor imports folder we optimise the bundle?

Interesting that it starts to work, except that in only few pages I get a strange error:

Uncaught ReferenceError: Buffer is not defined

The common thing in those pages are that they are with route parameters like /page/:pageId but not all pages with params have error. Some of them do work.

I couldn’t overcome it yet.

OK this was due to meteor-node-stubs package needing an update. After the update, everything is nice and smooth! :blush:

Thanks to all of you for the help! :heart_eyes: