Closed RGBboy closed 8 years ago
@RGBboy the reflective API to import modules via loader is not intended to be statically analyzable, in fact, it is very hard to do any analysis on an imperative form IMO, e.g.: "test.js"
could be produced by a function call, and there is nothing you can do to guess what value that expression will output.
@caridy but you could achieve such by allowing an API to declare this. E.g.
Loader.importNamed(['x'], 'test.js').then(...)
Then each hook has this information to do optimizations if they wish.
I was just under the impression that Loader would one day be the lower level API behind the module syntax. The end game would be to enable the browser/engine to do this optimization, and if they end up using Loader they would need this via this API no? Otherwise they would need to implement their own loading system without Loader.
Another alternative would be to specify it in the load string, which would allow hooks to see it:
Loader.import('test.js?x').then(...)
Then each hook has this information to do optimizations if they wish.
What if some other code (later) depends on having the entire namespace. If you've already tree-shaken away part of the module then what? Maybe I am misunderstanding your request.
Perhaps tree shaking is the wrong term. I am under the assumption that it would be loaded. Say for example I make two imports for different named exports:
Loader.importNamed(['x'], 'test.js').then('...') // like import { x } from 'test.js';
// ... later
Loader.importNamed(['y'], 'test.js').then('...') // like import { y } from 'test.js';
x
and y
would be gradually resolved when they are needed. You would load the whole of test.js
but you would not resolve all of its imports as you only need x
in the first case. Later y
would be resolved as it is requested.
I was under the impression this is how Loader would need to work and that the Registry be incrementally resolved as the tree of dependencies are imported.
no, that's not the intent, and that's not the way modules are implemented in 262. modules are evaluated to completion by the engine, which doesn't take into consideration who consume the module, and how it is consumed. any sort of optimization, and tree shaking, should happen before delivering a code to be evaluated by the engine.
I think the question is quite valid... Why is there a difference in the level of expressiveness between the static and dynamic APIs?
In the static one, it's possible to express the intent of loading a certain named export of a module, therefore whoever is facilitating the loading of the module can make informed decisions about loading dependencies of the module being loaded (which is especially interesting when using the proposed export _ from _
semantics.
The dynamic version can only decide to use a part of the module after it has been loaded, there is no way to declare the intent of using only a part of the module.
This is an important case in my mind for things like relatively large function libraries (e.g. lodash) where the top level module is just a composition of other modules (a sort of a "fanout" scenario) and its named exports are statically analyzable (they use the export
syntax). Having the information about the intent to use just a single export out of many from the library provides the ability to exclude all the dependencies of the other exports when loading the module.
I was also under the impression that this is one of the major goals of ES6 modules, so it's interesting that the potential of doing something similar wasn't included in the loader standard.
Is there any elaboration on that decision one could read?
Unless I am mistaken you can't express named imports via the loader API in an efficient way that allows hooks to optimize (e.g. tree shake).
Currently there are 3 kinds of imports with the ES6 module syntax:
One of the benefits this new syntax gives is the ability to just import part of a given module as shown in
3
.I can see that currently
1
can be expressed in the loader import syntax with2
and3
can not without importing the entire module first (along with all dependencies):The downside of this is that the hooks only will not know exactly what a user is asking for, therefore can't make optimizations (e.g. tree shake), and is forced to load the entire module.
Is one of the goals of this project to allow the ES6 module syntax to be expressed in terms of the Loader API? If so, should named exports be passed to each hook? If not, is there another way to achieve this?