Flow Router + Meteor@1.5 = per route dynamic import


#1

Recently released meteor@1.5 brought the great performance enhancements, including dynamic import(..), we’re happy to introduce support of dynamic per route import(..) in flow-router-extra.

Our test app, was ~4MB on initial load, using dynamic import(..) weight is reduced to only ~800KB!
Try flow-router-extra now and tell me how it work for you :slight_smile:

Update:
To give more inspiration I’ve made an example:

<!--/imports/client/index.html-->
<template name="index">
  <h1>Current time is: {{time}}</h1>
</template>

/* /imports/client/index.js */
import moment          from 'moment';
import { Meteor }      from 'meteor/meteor';
import { Template }    from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './index.html';

Template.index.onCreated(function () {
  this.time  = new ReactiveVar(moment().format('LTS'));
  this.timer = null;
});

Template.index.onRendered(function () {
  this.timer = Meteor.setInterval(() => {
    this.time.set(moment().format('LTS'));
  }, 750);
});

Template.index.onDestroyed(function () {
  if (this.timer) {
    Meteor.clearInterval(this.timer);
    this.timer = null;
  }
});

Template.index.helpers({
  time() {
    return Template.instance().time.get();
  }
});

To let you see the only required changes before and after dynamic import(...) I’ve made it as diff:

/* /imports/lib/routes.js */
import { FlowRouter }  from 'meteor/ostrio:flow-router-extra';

FlowRouter.route('/', {
  name: 'index',
+ waitOn() {
+   return import('/imports/client/index.js');
+ },
  action() {
-   require('/imports/client/index.js');
    this.render('_layout', 'index');
  }
});

Iron:Router & Dynamic Imports: How?
Set route for modal in FlowRouter + Blaze?
#2

Thank you @dr.dimitru! I look forward to testing this :slight_smile:


#3

@nadeemjq thank you for interest :slight_smile:
I’ve updated my initial post with example.


#4

Thanks @dr.dimitru, you’ve made it super easy!


#5

@dirkstevens glad you found it useful and easy to implement.
Share your implementation, and how much of bandwidth you have saved on initial bundle load with dynamic import(..) ?


How large is your app?
How large is your app?
#6

Do you have implementation details for React?


#7

Hi, check this thread.
I’m not using React, so it’s better to ask there.
But my quick guess - the same way - include modules you need to render a page…


#8

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


#9

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?


#10

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 ?


#11

Some pros/cons and research at this post


#12

Thank you @dr.dimitru.


#13

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' });
    });
  },
});

I'm on Meteor 1.5, now what?
#14

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


#15

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.


#16

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.


#17

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.


#18

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


#19

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


#20

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?