[idea] Manual control of loading of entrypoints in Meteor 1.3

Perhaps we can tell Meteor 1.3’s new modules system not to load entry points (main.js files) so we can load them manually.

We can currently import any file by referencing it relative to /app inside of a module, for example

import foo from '/app/path/to/foo'

By the same token, maybe we can tell Meteor 1.3 not to load a given entry point using the same type of path relative to /app (in package.json?):

{
    "dependencies": {
        // ...
    },
    "meteor": {
        "skipLoad": [
            "/app/client/home/main.js",
            "/app/client/about/main.js"
        ]
    }
}

Then, Meteor would compile those entry points as usual with one small difference: they won’t be loaded. Additionally, we can use the same exact paths to load them manually when we desire, so, for example, we could manually put this into the <head> of our app:

<script src="/app/client/about/main.js"></script>

We could load the entry points any way we wish, manuall/programmatically.

I think that’d be a killer feature. As a side-effect, we can use existing tools to programmatically load JavaScript files, for example with SystemJS:

System.import('/app/client/about/main.js')
  .then(...)

// easy!

This would all work in harmony with Meteor 1.3’s new module system. Apps could still take advantage of build plugins to handle things like import image from './image.png', but, the entry point simply won’t be loaded.

Meteor would need to serve the URL for each file (f.e. /app/client/about/main.js) so that we can load them. There could also be an option to configure the URL prefix, so it could be /whatever/we/want/client/about/main.js or /js/client/about/main.js

@benjamn Any thoughts on this?

3 Likes

Globbing could be supported, so if we want to load all main.js files manually, we could put this in our config:

{
    "dependencies": {
        // ...
    },
    "meteor": {
        "skipLoad": [
            "/app/**/main.js"
        ]
    }
}

And then we can load any and all main.js files manually.

wouldn’t what you want to achieve also be possible by entirely disabling autoloading and adopt multiple configurable entry points. akin to have everything be lazy loaded as has been hinted would be default in the future and not just what’s in imports directories. ?

so if lazyloading would be default, using a meteor.conf embedded in package.json, having an autoLoad: [ “/app/abc/,"/app/123/” ] in the meteor: { … } nest would get you the chance to have both, with nothing by default, unless autoLoad is added by default to package.json.

just a quick thought.

Well, that depends. @benjamn What exactly do you mean when you say that modules are “lazy loaded” in your new modules implementation? Are modules lazy loaded through the network?

If so, then yeah @casperandersen, this is exactly what we need, the ability to prevent files from loading and the ability to manually load those files.

@joe I might have jumped ahead using the term lazy loading. since @benjamn have referred to lazy evaluation not lazy loading.

In this case I was only thinking in the context of the bundler at ‘bundle-time’, so maybe auto bundle would be more descriptive.

What I am currently experiencing with lazy evaluation in 1.3 is

  • everything in an imports dir is not auto-bundled and loaded on the client, only what has been imported from somewhere, starting from an entry point outside the imports directories.
  • js/jsx in the imports dirs are somehow evaluated, even if not imported anywhere, I experience this if there is a syntax error. dunno if that is intentional? could be nice if it didn’t evaluate non-imported, while developing, and also I’d be concerned it spent resources on that which unnecessarily adds to build time
  • everything not in imports directories, html, css, js, jsx, are auto-bundled.

Forward looking:
However, indeed lazy loading, of resources that are not bundled into the initial client(s), and loaded over the network is indeed desired. When people were experimenting with famous, that was in play. Now we are in the code splitting context :slight_smile: in the code splitting context when we get to that without webpack, it would indeed be nice to have lazy loading over the network on demand, so the initial client can be kept thin, and modules be added while the app is running, whether the modules were compiled at bundle time or post bundle time.

However, having everything be auto-bundled as in pre-1.3 could be an option, so the default is that only what is referenced by an import gets bundled. That would be sweet. And in this context we can have the possibility to specify multiple entry points in a package.json meteor or separate meteor.conf build section. (this part works well in webpack, and looks like it will do well with an ES2015+ based solution too).

Instead of having skipLoading, which insinuates autoLoading/Bundling by default, I’d prefer an autoLoading so we turn it on its head from magic to declarative, with magic being an option. Somewhat similar to todays usage of autopublish and insecure packages, although they are enabled by default as it is.

Heck, even having autoLoad be configured with everything by default would be sweeter, then instead of the guide being like meteor remove autopublish insecure, the guide would be like change autoLoad/Bundle from * to none or /client/main.js, /client/main.html, /client/main.css. however now that’s almost like specifying entry points, so I’m just throwing in snow balls here with thoughts on ideas :smile:

1 Like

Aaah, good catch! I missed that. I think the entire dependency tree of an es2015 entry point module gets evaluated as soon as the entry point is requested to be evaluated, so, there’s not anything really lazy in that case.

@benjamn Could you expand a little on what you mean by lazy evaluation? I thought that was a CommonJS/AMD thing, as in

setTimeout(function() {
  let foo = require('foo') // lets import this later.
}, 5000) 

I have the same problem (you can see I may have confused the terminology there). I would think those files shouldn’t be executed or even shipped to the client.

Yep, it would.

That would be nice, but I think it breaks backwards compatibility since the magic auto-bundle has to be on by default for pre-1.3 apps work.

That’d be great!