On Aug 28, 2014, at 10:10 AM, Ian Hickson <[email protected]> wrote:
> Here are the changes that would be needed to make the ES6 loader
> infrastructure underpin the Web platform's loader infrastructure
> (basically, placing the ES6 loader the management layer between the Web
> platform APIs on top, and Service Workers underneath).
> ...
> If we can reuse this for the rest of the Web platform, it gives authors a
> really uniform API for all loading operations.
The module loader isn't the right layer for the kinds of things you're trying
to do. I understand you're trying to avoid having similar mechanisms at
multiple layers of the platform, but repurposing the module loader system as a
general purpose web resource loading system means conflating web resources and
modules, which leads to a mixing of concerns exposed to the development model.
Let me go into some more detail.
## What the `System` module loader is for
First, let's talk about what the module loader *is* for, and what the important
requirements the browser's default `System` loader should address. In
particular, I'm *not* saying that there should be *no* reflection of web assets
to the JS module system.
### JS module name resolution
* *Basic name resolution for JS modules.* Refer to global and relative modules.
* *Module naming conventions that work across JS ecosystems.* Conventions that
work on both client and server, particularly with npm.
Straw-examples:
```javascript
import _ from "underscore"; // global module
import spinner from "./spinner.js"; // relative module
```
### HTML interop
* *Making JS modules available to HTML.* Allow HTML files to import from JS.
Straw-examples:
```html
<!-- for now: -->
<script type="module">
import $ from "jquery";
import frobify from "/scripts/frobify.js";
$(".frob").each((i, elt) => {
frobify(elt);
});
</script>
<!-- eventually, but we can save this discussion for another day: -->
<module>
import $ from "jquery";
// etc.
</module>
```
* *Reflecting web assets as JS modules.* Make web assets available to JS as
modules that export a DOM element.
Straw-example:
```javascript
import icon from "./icon.png";
console.log(icon instanceof HTMLImageElement); // true
```
### Installing HTML/CSS components via module import
* *Applying CSS via import.* Mechanism for applying stylesheets by importing
them from JS.
Straw-example:
```javascript
import "./main.css"; // guarantees CSS is loaded and applied by the time this
module executes
import $ from "jquery";
$("#main").show();
```
* *Installing HTML imports via import.* Mechanism for installing HTML imports
by importing them from JS.
Straw-example:
```javascript
import widget from "./widget.html";
console.log(widget instanceof DocumentFragment); // true
```
### Enriched response API
* *Cross-origin fetch.* Cross-origin requests should succeed by returning and
opaque response, just as ServiceWorker does, that cannot be inspected but can
be returned back into the pipeline for execution.
* *Streaming fetch.* It should be possible for a request to return a stream
instead of a string, to allow asynchronous stream processing; this should use
the API that results from the stream standardization process.
## What the `System` module loader is NOT for
* *Bundling requests.*
While it's attractive to use the loader for serving multiple assets in a single
payload, this wants a more general solution for bundling arbitrary assets --
perhaps for performance (since despite the impending coolness of HTTP2, people
will likely still use bundling as a successful optimization technique for a
long time), but also for ergonomic deployment and inclusion. Jeni Tennison has
done an excellent [proposal based on the link
tag](https://github.com/w3ctag/packaging-on-the-web), and I've started
exploring another approach based on URLs. Meanwhile people can experiment in
userland with ServiceWorker-based techniques for bundling payloads.
* *Repurposing the module registry to reflect caching of arbitrary browser
fetches.*
The registry is meant to record installation of things that are conceptually
modules, not arbitrary network fetches of web assets. It's not the right place
to store a cache of fetches. In particular, notice how above I said that it
makes sense for modules to be able to import from, say, PNG files. In that
case, the developer has explicitly requested that a web resource be reflected
as a module, and it should be installed as a module. But using the registry for
all web fetches means that non-JS is polluting the module registry with random
modules reflecting arbitrary assets in the application.
* *Forcing resource management to be reflected as modules.*
The ServiceWorker API gives programmatic control over fetching of network
payloads and a caching API. The module loader API gives programmatic control
over fetching of modules and a caching API. What you're describing is using the
latter for programmatic control over fetching and caching web assets, but that
means you force them -- in the exposed API -- to be reflected as modules.
* *Exposing loaded assets in a permanent global table.*
The registry is a strongly mapped global table. If the DOM eliminates a
resource that was loaded from the network, and that is necessarily installed in
the module registry, it's pinned by the registry and uncollectable.
## What I suggest
It's still not completely clear to me what your use cases are, so I'm not sure
exactly how much user-visible API you need. But if you are trying to reflect
the browser's fetching policies and priorities based on different types of
assets, then you are looking for a layer in between ServiceWorker and module
loader -- call it an asset manager or resource manager. I'd be happy to discuss
this with you and see if we can flesh out the use cases and requirements to get
a better handle on the problem space.
Dave
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss