Code Splitting an Packages

Granted I am still wrapping my head around the new 1.5.x feature to split code/ie. load code on demand, I am somewhat at a loss how to accomplish it when modularizing your app with packages. How do I use code splitting with packages?

Thanks for any hint/example.

2 Likes

I wrote a blog post about my experience here, maybe it would help you.

It references a link as to how to make packages load lazily:

api.mainModule("main.js", "client", { lazy: true })

When it comes to dynamic import, if you know import/export well then it should be easy to use. The main difference is, when you use an import your code, Meteor will automatically import it. With dynamic import, that import would only happen once the function runs. There’s a bit of magic going, but its quite nice once you get the hang of it.

I also have a sample repo here to demo it. Notice that the import statement only runs when the function is triggered (in this case, by a click).

6 Likes

Thank you for replying and posting your blog post. Do you happen to know about a package that implements lazy? Just trying to get the structure right. My main confusion is if packages honor the import directory.

My app is using mrt:accounts-admin-ui-bootstrap-3 but I don’t want to load any of it unless the /admin/user URL is hit. I already cloned the package because I wanted to add columns to the standard UI.

PS: do you know if code splitting works with Iron Router? Or is it finally time to switch :slight_smile:

1 Like

Ah, yeah, it would work the same as any package. When you do import/export, you are defining the main module with api.mainModule("main.js"), and to prevent Meteor from loading it, you just use api.mainModule("main.js", "client", { lazy: true }) instead.

IIRC Iron Router does not have support for lazy loading, however, the import statement can probably be stuffed somewhere in the route callback.

PS: Meteor Candy 2 is going to be up soon, with a good number of new features and dynamic imports. Maybe its another option here :smiley:

1 Like

Great article, but I’m a bit worried about what you’re eating :wink:.

@msavin will you explain the hightlighted sencence in detail please? For example, is your definition of microservices?

@aadams one thing I’ve seen is companies build separate apps for administration purposes that connect to to the same databases. With dynamic imports, that’s no longer necessary, as far as keeping the client lean. Therefore, you can leverage the current login session for administration and save money on hosting and maintaining another service.

1 Like

Thanks @msavin.

In my case I split my admin add from my “users” app for the following reasons:

  1. Optional performance: Users app needs much more scale than my admin app, I can load up a bunch of my client’s admin apps on one slower server (saves $), while I can throw each of THEIR clients onto a performant box (more $$) – or put both the admin and client on one box (same out of pocket $) – flexabilty/options/performance.

  2. Awkward admin “log in as” user features: When I add both admin and user apps are one, the out of the box Meteor “impersonation” feature was not as robust as I would have liked. Sometimes I would ramdomly get kicked out, and if the page was refreshed of course they are kicked out. With two apps, this is very stable.

  3. Views/Routes and Roles: There is now a clean separation of not just views on the client, but more importantly, the codebase and routes. Before I would have to check both views and routes agains the role – that’s no longer the case when you separate the application.

  4. Public folder: I have assets in the public folder that I only need on the admin side. As far as I know, we can’t yet dynamicly import from that folder.

  5. Client size: This reason is kinda mute now that 1.5 has dynamic imports, which was that I had to load all the views and client side code only used by the admin add, also with the user app.

  6. Mobile: The “users” app can now be broken out and use for mobile, whereas the admin app will not be deployed to mobile for various reasons.


Also, what’s your definition of microservices?

For example I’m now thinking of breaking out a portion of my application into a “service”, could be call “microservice”, that is responsible for long running workers. This is a server side only service, and therefore dynamic imports has impact on it.

I think we’re on the same page for service/microservice. I called it microservice because Josh had the described the method in that way in his blog post.

To give you my version of it:

I don’t think admin functionality requires much resources because its not like you would be dealing with 1000 requests per second. Plus, your deployment should be good at distributing the load across servers. In contrast, you wouldn’t want two apps competing for resources on the same server.

Not sure, I’ve never seen that. In my experience user impersonation works reliably.

[quote]3) Views/Routes and Roles: There is now a clean separation of not just views on the client, but more importantly, the codebase and routes. Before I would have to check both views and routes agains the role – that’s no longer the case when you separate the application.

  1. Client size: This reason is kinda mute now that 1.5 has dynamic imports, which was that I had to load all the views and client side code only used by the admin add, also with the user app.

  2. Mobile: The “users” app can now be broken out and use for mobile, whereas the admin app will not be deployed to mobile for various reasons.
    [/quote]

Here, I think all of these can be addressed by making your admin panel a package that is dynamically imported.

I believe Meteor requests things from that folder when they are necessary - this is actually a behavior of the web browser and not Meteor. Meteor only loads an HTML, CSS and JS file, and then those request static assets as necessary.


In the end, developing your admin panel as a dynamically imported package is not much different than building it as a separate app, and having it all bundled into one piece is cheaper and (IMO) easier.

It was the other way around, I want the ability to have my “users” app on a HA server properly scaled – yet throw my admin app on a low profile server (heck throw a few of the admin apps, from different clients, on a low profile server) is a great idea and savings. I actually like the flexability to throw multip apps on a server or break one off on its own where appropriate – to each his own.

Heck, I even like the fact that my admin and user code is not “mixed” anymore – just reduces congnative overhead of a very large project. Again, everyone has a different taste.

But I will absolutly now implement dynamic imports for both my admin and my user app – 100% on board with doing this. I even upgraded from 1.3 directly to 1.5, just to get this feature.

@aadams
Nice man. let me know if you want a preview of Meteor Candy 2, it might save you some time in doing this yourself. Plus, I know you run your own business, so it would be great to get your perspective on it from that POV.

1 Like

Hi,

I’m trying to do that but also try to split my code into multiple .JS files in meteor.
My goal is mostly to make smaller Hot Code Push to my Cordova users using mobile phones.

Our app.js file has grown to 6,5mb and our mobile users are complaining their actions don’t get saved when the websocket is too slow, which usually happens when:
-We’ve pushed new versions and their 4G network is congested or in rural area

I could not find articles on how to split app.js in multiple files.

We’re using meteor 1.5.4

Regards,
Burni

Would you please open a new post for this? You usually dont want to split your app.js but rather reduce the initial bundle size. Let’s talk in an own post about this.

1 Like

Hi Jkuester,

Thanks for your reply and invitation to open a new topic to discuss the idea.

It’s here in the mobile forum :

Thanks a lot!

Burni