Meteor 1.5 and lazy loading react components

That’s right - for backwards compatibility all files outside of /imports are loaded right away, so there’s no way to load them later since they are already loaded :]

Thanks. Will this change in Meteor 1.5 as @gusto suggested?

Here’s the discussion on that, please join in!

I think we need to make sure to do it in a way that current Meteor users are not affected, but I personally like it as a default for new apps started with 1.5.

1 Like

Been using this solution for a little while, but occasionally seeing it doesn’t actually import and then mount the proper component – just gets stuck with my initial Loading. It’s really inconsistent, and more often than not happens in a background tab. No errors seem to be thrown in console or server logs. Anyone seen anything similar?

I’ve got my imports in an /imports folder, and router.js in the root directory.

Flash forward 1.5 months and this method still often fails to fetch the file on initial page load, and I have to manually re-trigger the route using FlowRouter.reload() (or let the user manually trigger it from the component if they open up the website and the route doesn’t import properly).

Here’s an example – note that my and components live outside the imports folder so that they are served as part of the initial meteor JS bundle without requiring import.

FlowRouter.route('/', {
    name: 'home',
    action: function(params, queryParams) {
        mount(Layout, {
            content: <Loader />,
        });
        import('/imports/client/feed').then(({ default: Feed }) => {
            mount(Layout, {
                content: <Feed tab='home' page={queryParams.page} />
            });
        });
    }
})

Anyone else seen anything like this?

have you tried to do a log or breakpoint before the second mount ? Does the import promise resolve in this situation?

Thanks for the tip – that’s a little beyond me in the FlowRouter context. Could I bother you for an example or a tip on where and how to do that?

I think he means something like this:

FlowRouter.route('/', {
    name: 'home',
    action: function(params, queryParams) {
        console.log('action init');
        mount(Layout, {
            content: <Loader />,
        });
        console.log('post first-mount');
        import('/imports/client/feed').then(({ default: Feed }) => {
            console.log('promise resolved');
            mount(Layout, {
                content: <Feed tab='home' page={queryParams.page} />
            });
            console.log('post second mount');
        });
    }
});

Also, not to necessarily dissuade you from the .then syntax, but I’ve been testing 1.5 successfully using async await:

MainRoutes.route('/', {
  name: 'dashboard',
  async action() {
    // const inTime = Date.now()
    await import('/imports/ui/modules/main/index');
    // console.log('load time:', Date.now() - inTime);
    BlazeLayout.render('global', {
      layout: 'basicLayout',
      pageContent: 'dashboard',
    });
  },
});

Thanks for the tip re: where to put the logs in. I’ve been able to replicate the issue with the logs in place, and indeed – the promise does resolve and all console.logs are fired.

I like your async / await idea. I’ve changed it to use that as it seems clearer, but alas… same issue. It gets stuck on my first mount of , and doesn’t resolve the second mount until I fire FlowRouter.reload(). Weird.

Perhaps I should just keep it to one solitary mount… the only issue is whether I should be showing a while that promise resolves or not. It’s quite quick…

I honestly don’t know React + FlowRouter well enough to help you there. I can say that I’m experimenting with the same ideas though, which is why I’m time stamping the import times. It’s tricky because your client only pays the initial import price one time, and subsequent loads are pulled from cache.

It seems like a lot of overhead right now, but thinking long term, a state-managed solution to import resolution seems like a win for me. Then things could be handled at the template level.