Dynamic Import a Meteor package


#1

Is it possible to dynamic import a Meteor package?

I’m currently using the awesome job collection meteor package (vsivsi:job-collection) and I was able to separate a lot of long running tasks triggered by user actions to background jobs. But, less than 5% of user actions result to background jobs.

Given this, the package is in the top 5 of the network resources being downloaded by my users. Is it possible to dynamically import this package?


#2

#3

Doing this seems not to work. The initial bundle still includes the meteor package. Am I doing something wrong?

const { JobCollection, Job } = await import('meteor/vsivsi:job-collection');

#4

Where do you put that statement?

const { JobCollection, Job } = await import('meteor/vsivsi:job-collection');

It should only be called within a function that is only called when the user needs it.


#5

Yep, inside a function

async function createJob(type, inputs, priority, options) {
    const { JobCollection, Job } = await import('meteor/vsivsi:job-collection');
...
...
...

#6

As long as createJob is not called, the package should not load.

How do you verify it is in the initial bundle? You see the package loading in the network tab of inspector?


#7

Yes. From the network tab of chrome’s inspector. I actually commented all calls to createJob() but it was still loading on initial call after clearing the cache. So I assumed either there was a special way of dynamically importing meteor packages as compared to normal modules OR meteor packages are always included in the bundle


#8

You could use dynamic import with Meteor packages, but the packages must be configured for that use case with es6 modules. I took a look at vsivsi:job-collection and it does not look like it supports that use case.


#9

Thanks. I’ll check with the package owner


#10

For more information on this, check this issue:


#11

Thanks @robfallows

I’ll see if just changing the package.js will do as indicated here:

If it does work, then I’ll do a PR for that package but I’m not sure about backwards compatibility to Meteor lower than 1.5


#12

As long as you bump the version and set api.versionsFrom to 1.5, the Meteor build process will use the older version for pre-1.5 and the newer for 1.5+. The most important thing you need to confirm is that for 1.5+ code, you ensure that it works not only for dynamic imports, but also if used “traditionally” - which is not quite the same as pre-1.5 backwards compatibility.


#13

So. I’ve done some playing around with one of my packages and while it’s easy to get dynamic imports working - they just do - I haven’t got “traditional” use working with a dynamically loaded package. Which is kinda obvious. That means either the entire codebase (including internal, Meteor packages if necessary) have to use dynamic imports, or you need (an) additional package(s) to dynamically load and make the export(s) available to the global scope. In Meteor package terms, this could be a weak dependency: if present you get the traditional, eager loading. If not, you get dynamic loading.

My (limited experimentation) conclusion is that a straight one-for-one replacement offering dynamic loading and “traditional” loading based on your code style is not possible. But, I’d love to be proven wrong!


#14

Ohh. Too bad. Then I think I have no choice but to fork it and maintain it. I’ve confirmed from the author that he is no longer actively maintaining it but not deprecating as it is still being used by many meteor developers