On Aug 28, 2014, at 10:10 AM, Ian Hickson <i...@hixie.ch> 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to