Flow Router + Meteor@1.5 = per route dynamic import

Flow Router is works nice with react components and much more flexible, convenient and advanced than the React Router, with React Router you will have to reinvent the wheels and re-do the simple things that the Flow Router provides out of the box
For example, with RR you have to tinker with url/hash parameters, url-based paginations, absolute/relative paths, etc…
prepare to strain the brain :grinning:
I think that ReactRouter starred by people who did not know about Iron/Flow Routers

1 Like

Hello @orloff ,

Thank you for info :slight_smile:
I know you have been using FR-Extra for a while, I’m curious if you got a chance to try it with dynamic imports?

Hi!
I’m just exploring this technology :slight_smile:
before dynamic import i prevented excessive loading by this:

const route = window.location.pathname;
if (route.indexOf('/admin')> -1) {
    import '../imports/startup/client/routes/admin.js';
    import '../imports/ui/admin/layout.js';
   .....other admin only staff....
  } else
if (route=='/' || route.indexOf('/catalog')> -1 .............. )
  {
    import '../imports/ui/css/custom.css';
    import '../imports/ui/css/theme.css';
    import '../imports/ui/css/themify-icons.css';
    import '../imports/ui/catalog/layout.html';
........only for clients.......

and I’m studying whether it’s worth changing to dynamic?
pros and cons ?

Some pros/cons and research at this post

Thank you @dr.dimitru.

1 Like

Nice! Looks like vanilla FlowRouter also works ok with dynamic imports out of the box. Like this:

FlowRouter.route('/page/:_id', {
  name: 'page',
  action() {
    import('../../ui/pages/Page/Page.js').then(() => {
      BlazeLayout.render('layout', { main: 'Page' });
    });
  },
});
6 Likes

in fact it doesn’t seems to build different bundles… any idea
The app still works but only one js file generated in production.
4 routes of 6 are using dynamics import and they have specific code inside so i expected to get at least 5 bundles

Eh…I didn’t check a count of bundles. But I used bundle visualizer and noticed that bundle size reduced. I have page importing Chart.js lib, which is huge. So I load this page dynamically and when I open the main page there is no Chart.js in the bundle. And when I go to the page with this lib it works well.

Bundle always is only one. All dynamic code is loaded dynamically over the WebSockets or XHR. The server decides what should be returned upon request.

1 Like

You can open “Network” tab in the browser’s Dev Tools, and then select “websocket” and then “Frames” tab, there you will be able to observe what and when actually loaded dynamically.

Ok, for instance i didn’t see anything over network…

Should look like (purge IndexedDB before you go, in case modules is already loaded):

What if you have multip template options per route?

Using your example:

FlowRouter.route('/page/:_id', {
  name: 'page',
  action() {
    import('../../ui/pages/Page/Page.js').then(() => {
      BlazeLayout.render('layout', { main: 'Page', SideBars: 'Sidebar' });
    });
  },
});

How would you dynamically import both Page and Sidebar in this case?

I use Promise.all([]).then()

2 Likes

Promise.all? Sorry, I’m not familiar with Promise syntax, will you help with a code snippet @rmuratov?

FlowRouter.route('/page/:_id', {
  name: 'page',
  action() {
    Promise.all([
      import('../../ui/pages/Page/Page.js',
      import('../../ui/pages/Sidebar/Sidebar.js'
    ]).then(() => {
      BlazeLayout.render('layout', { main: 'Page', SideBars: 'Sidebar' });
    });
  },
});
3 Likes

Thanks @robfallows!

Just curious, why isn’t the original example wrapped in a promise? Is the import statement a wrapper on a promise?

FlowRouter.route('/page/:_id', {
  name: 'page',
  action() {
    import('../../ui/pages/Page/Page.js').then(() => {
      BlazeLayout.render('layout', { main: 'Page', SideBars: 'Sidebar' });
    });
  },
});

Yes - it returns a Promise.

You could also use async/await:

FlowRouter.route('/page/:_id', {
  name: 'page',
  async action() {
    await import('../../ui/pages/Page/Page.js');
    await import('../../ui/pages/Sidebar/Sidebar.js');
    BlazeLayout.render('layout', { main: 'Page', SideBars: 'Sidebar' });
  },
});

Although that could be slower, since it waits each time, whereas Promise.all runs them concurrently.

5 Likes

Very good. Thank you @robfallows!

1 Like

Or:

FlowRouter.route('/page/:_id', {
  name: 'page',
  async action() {
    await Promise.all([
      import('../../ui/pages/Page/Page.js'),
      import('../../ui/pages/Sidebar/Sidebar.js')
    ]);
    BlazeLayout.render('layout', { main: 'Page', SideBars: 'Sidebar' });
  },
});

source: http://2ality.com/2017/01/import-operator.html#async-functions-and-import

3 Likes