Meteor/React Lazy Loading

I’m struggling to implement React lazy loading.

I get the following error:

modules.js?hash=1366dc073b25c0d88856bae23f6e79534ab11087:7168 Uncaught (in promise) TypeError: Cannot convert object to primitive value
    at modules.js?hash=1366dc073b25c0d88856bae23f6e79534ab11087:7168
    at Array.map (<anonymous>)
    at printWarning (modules.js?hash=1366dc073b25c0d88856bae23f6e79534ab11087:7167)
    at error (modules.js?hash=1366dc073b25c0d88856bae23f6e79534ab11087:7147)
    at modules.js?hash=1366dc073b25c0d88856bae23f6e79534ab11087:8527
    at meteor.js?hash=857dafb4b9dff17e29ed8498a22ea5b1a3d6b41d:1234

A quick Google search suggests that this is caused by an out-of-date JQuery version. That seemed logical as I am using jquery@1.11.0 (because of package constraints).

I tried to install jquery@3.4.1 using the --allow-incompatible-update flag but Meteor says error: no such version jquery@3.4.1. Same for 3.5.1. Same error when using !. Highest version I can install is 3.0.0. This did not fix the error though.

I installed 3.4.1 with NPM instead. This also did not work. I’m not even 100% sure if this is a JQuery problem but the only solutions I can find are related to JQuery.

I’m importing with:

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

My render looks like this (I’ve removed a lot of code - included what I think is relevant):

<Router>
    <Suspense fallback={<div>Lazy Loading...</div>}>
        <Switch>
             <Route exact path="/" component={Home}/>
        </Switch>
    </Suspense>
</Router>

I’ve also tried having the component wrap around but no luck. This is within a functional component that renders my Routes.

I can provide extra info if needed.

Hi @alelor01 I use for lazy loading the npm package called @loadable/component. What I do in the App.js file is something like this:

import React from "react";
import loadable from "@loadable/component";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
const Home = loadable(() => import("/imports/ui/home"));

export default App = () => (
	<Router>
		<Switch>
			<Route path='/' exact component={Home} />
		</Switch>
	</Router>
);

You can lazy load each view component and it works perfectly.

2 Likes

Thanks @juanpmd, I’ll give it a try.

What’s the difference with @loadable/component vs React’s built in Lazy Loading? Do you have to use the @loadable/component package instead?

I ended up getting React’s Lazy Loading to work. I don’t use SSR (at the moment) so I stuck with React’s Lazy once I figured out the issue.

Your code example made me realise that I needed to use default exports, not named exports.

Thanks for the help!

2 Likes

@juanpmd up till now I have been using React.lazy in a similar way as you demonstrate with @loadable/component. However, dynamic imports cause an issue with the Content Security Policy. I have to allow unsafe-eval to make it work. Do you have similar experiences with @loadable/component?

It is my pleasure @alelor01

They both work in a simillar way. I tried React Lazy Loading a while ago and I remember choosing loadable/component for 2 reasons:

  1. React Lazy had some strange white flickering which I though was not optimal for users.
  2. @loadable/component has a wonderful preload feature. For example you can lazy load a modal on a view, if you hover a button (without clicking) this will preload the Modal and when you click it is already there.
1 Like

Hey, I don’t use any library besides React and Meteor to enable dynamic modules in my apps.

Do you want a post about that (is that helpful enough to be shared) or are you using @loadable because you like it?

3 Likes

A post would be wonderful, thank you @filipenevola . I tried using the Meteor dynamic import system with React but I was never able to make it work (with Blaze it was extremelly easy). After that I used react-loadable which was deprecated and jumped into @loadable/component.

1 Like

I would very much appreciate a post about this subject @filipenevola. As I mentioned in my previous comment, I trying to figure out how dynamic imports relate to Content Security Policy settings. It seems that dynamic imports on the client require certain settings (i.e. allowing unsafe-eval) that are not favorable.

@juanpmd I do use react-loadable and it doesn’t seem to be deprecated.

1 Like

So I am playing around with this. My bundle size is ~ 5MB and 95% is node_modules rather than my actual react layouts, components and pages etc…

If I have a massive node package only used on one page, and lazy loaded that page - does that also include the node_module for that?

@cstrat Yes, this will exclude that package from your initial bundle too.

Check the bundle visualizer to confirm; if you still see that package in the bundle, find out where else it is referenced from. Consider using madge in non-trivial cases:

Madge is a developer tool for generating a visual graph of your module dependencies, finding circular dependencies, and give you other useful info. Joel Kemp’s awesome dependency-tree is used for extracting the dependency tree.

  • Works for JavaScript (AMD, CommonJS, and ES6 modules)
  • Also works for CSS preprocessors (Sass, Stylus, and Less)
  • NPM installed dependencies are excluded by default (can be enabled)
  • All core Node.js modules (assert, path, fs, etc) are excluded
  • Will traverse child dependencies automatically

Awesome thanks! Yeah I wasn’t sure and didn’t want to test 10 different permutations of builds since they take so long :smiley:

Edit: issue with the CSP was due to the way I used a React Suspense component.

I had started this post before I realized this was already being discussed. I must have missed this thread while searching for a solution…

hi, @loadable/component ssr will be enabled because there is no way to configure webpack in meteor, so there is no way to enable ssr any options

I just replied here how I use React.lazy and dynamic imports with Meteor.

What else should I write in a full post about it?

What are the other questions?

1 Like

npdev:react-loadable should still work, even with code splitting and SSR (unlike React.lazy).

I’m happy to fix anything about that that people are having trouble with, or with configuration (it’s a little tricky).

2 Likes