Help needed pls - dynamic imports don't seem to be working

Hi, I thought I was using dynamic imports to help reduce the size of the initial bundle.

I moved some imports/requires to either inside functions like onCreated or onRendered… or even when an event fires.

For one if these when I check the bundle-visualizer and I still see datatables.net datatables.net - npm show up in the visualizer.

I also see codemirrorcodemirror - npm which I understand is a dependency of EasyMD easy-markdown-editor/package.json at master · Ionaru/easy-markdown-editor · GitHub

For example, here’s code where I import easymde - npm , which I think imports codemirror . I thought as this is inside the onRendered the import/require would be dynamic

Template.someTemplate.onRendered(function() {
  const self = this;
  const template = this;
  import 'easymde/dist/easymde.min.css';
  const EasyMDE = require('easymde');

Any help appreciated

I can’t speak to the rest of the issues - but dynamic imports are functions:

import('easymde/dist/easymde.min.css')

I also don’t think you can combine require with dynamic imports (meaningfully), nor - as far as I know will dynamically importing the CSS have the affect of applying the styles (not 100% on this one).

import() returns a promise - so if you’re going to try to use in your render function you’d probably want something like:

 Template.someTemplate.onRendered(async function() {
await import('easymde');
...
})
2 Likes

I think what happens with dynamically imported css is that it is injected into a new <style> tag, which triggers a browser re-paint. So that part should work fine.
(Tested by dynamically importing a JS file which statically imports a css file. ie. as a child dependency)

I’m also pretty sure require can be swapped out for import( just fine

1 Like

@znewsham @coagmano thanks… I think I got that working. Both require and import seem to work, dependent on the specifics of the module.

I was also trying to get dynamic-import | Meteor API Docs working.

it seems like when I do something like

if (false) {
  import './somefile';
}

it gets imported regardless and shows up in the bundle-visualizer

I did try this in an index file I was importing…

Meteor.startup(async function() {
  await import('./somefile');

That seems to have the opposite effect and is never imported/does not show up in bundle-visualizer

Anyone had any luck with that?

ps I did notice this thread Dynamic Imports File Names - #17 by vigorwebsolutions

UPDATE: kinda works some of he time. I tried it with huge chunks of files in index files and it reduces bundle size significantly… but sometimes there are issues with things not being defined… so not 100% sure how the load order works?

2 Likes

I did not know this, but just verified that is the case - this makes a lot of sense.

In general, import statements are supposed to be top level (non dynamic imports that is). There was some discussion a while back about whether this requirement made sense, particularly in meteor’s isomorphic setup where you could very likely want if (Meteor.isServer) import....

Dynamically imported files should never show up in the bundle visualiser, since they are never part of the served bundle (even after they are dynamically loaded by the client) - so that part makes sense.

There should almost never be issues with things not being defined - if you’re waiting for the import correctly. I’ve never tried playing with dynamic imports from packages that use Meteor’s package level globals, nor meteor’s specific export syntax at the package level - no idea how this would work, but in general, stay away from both of these things for es6 style exports, and no globals at all.

We’ll probably need an example of something that isn’t defined to help further.

1 Like

This is a static import, so the imported code will be included in the bundle, but never executed.
Note that the docs say to use the dynamic import function here, which prepares the target for dynamic importing, but doesn’t include it in the initial bundle.
Also note the docs say this is only ever required when you want to use dynamic imports without static strings eg:

const module = await import(`/libs/${path}.js`);

Because the target module can’t be analysed at build time, the bundler doesn’t know which files to include in the bundle. That’s why the solution is to create a whitelist in a dead code branch,
ie. if (false)

Can you provide an example?
I’ve never had issues with things not being defined after they’re imported. I can think of a couple of ways this could be caused, but would need to see to know if you’re running into one of them

I can answer this part, since I’ve played with it before in various attempts to bundle split old packages.
If you’re using a package with globals or exports, it’s pretty much always included in the bundle, even if you dynamically import it.
You can get them to lazy-load, but requires extra configuration in the package and it’s consumption.