Open kristoferjoseph opened 8 years ago
This is a good ideas. Do you have any suggestions for what this new syntax will look like?
Currently, we walk the parsed AST for required dependencies to find the the require('lasso-loader').async(...)
calls and then rewrite them. Perhaps we should look for something else? Maybe something like LOAD_ASYNC(...)
. We would still probably rewrite it to use lasso-loader
under the hood but we don't need to reveal this implementation detail.
We need some way to define those split points, request the async bundle and ensure it exists before running the code.
ES6+/201X does define System.import
for the purpose of asynchronously loading a module. We could probably use that and at least it would be somewhat standard. Webpack2 is using this for their split point.
I'm not opposed to coming up with an alternative that doesn't leak "lasso" into the code. The reason I was okay with "lasso-loader" being leaked is that lasso-loader is an actual module that can be used to load JS and CSS files asynchronously and it can be used independent of lasso.
In addition, in the case that lasso-loader
is running on the server we could make the lasso-loader
module work on the server since we control the code for lasso-loader
.
Here are some ideas:
lasso-loader
Rename lasso-loader
to something like "lazy-loader" that is more generic and does not have "lasso" in its name (assuming the name is also available on npm
)
System.import
Switch to System.import
and require that the lazy function be split into a separate module:
Old:
client.js:
require('lasso-loader').async(function() {
var foo = require('./foo');
var bar = require('./bar');
// ...
});
New:
client.js:
System.import('./lazy')
.then(function(lazy) {
lazy(); // Invoke the lazy function when ready
})
.catch(function() {
// ...
});
lazy.js:
// NOTE: We export a function that is invoked when the dependencies are fully loaded
module.exports = function lazy() {
var foo = require('./foo');
var bar = require('./bar');
// ...
});
It would be a challenge to make System.import
work on the server since it would require System
polyfill. If System
is a true global then it would not have access to the local require
syntax. Here are some ideas on how to make System.import
work on the server:
System.import(require.resolve('./lazy'))
.then(function(lazy) {
lazy(); // Invoke the lazy function when ready
})
.catch(function() {
// ...
});
System
variable in every loaded modulePersonally, I like the System.import
solution. We can continue to support lasso-loader
for backwards compatibility, but I think it is reasonable for lasso
to transform the System.import
code such that it works in the browser. Through some hacks we could probably make System.import
work on the server, but hopefully that would be temporary until System.import
is natively supported.
Thoughts?
Looks like simply import(path) : Promise
has been proposed: https://github.com/tc39/proposal-dynamic-import
Was thinking a lot about this while implementing my own lasso middleware and if you are already rewriting the lasso-require
calls is it too far of a stretch to instead look for require('modle-name')
since lasso already needs users to define what modules are being asynchronously loaded?
@kristoferjoseph FYI, we still want to implement this, but we have been focused on the Marko v4 release that just went out recently. I'm going to reopen this :)
I think what is most desirable is to help push the following spec forward: https://github.com/tc39/proposal-dynamic-import
Doing so will force the hand of Node to make some concrete decisions Re: ES6 Modules Interop.
Next step is to get the tests defined for implementations. I've opened an issue for that in the Compat Table here: https://github.com/kangax/compat-table/issues/1052
Please note some Node-goers seem vehemently opposed to dynamic imports. But despite how they feel the Web needs them to help drive ES modules forward.
As a stop gap you may find some value in Fetch Inject, which implements Fetch Injection and will work alongside Service Workers for offline support in PWAs.
I'm interested in understanding how HTTP/2 multiplexing will play into all of this, as mentioned in the comments section of Rich Harris' bundler post on Medium this week.
Is there currently a way to asynchronously load a module without having to have lasso leak into app source?