Re: [w3c/webcomponents] HTML Modules (#645)

I really like how general purpose this "import as" approach is. It looks like it covers a lot of cases for bringing in general-purpose sub-resources:

```js
import doc from "./x.html" as Document;
import img from "./x.png" as Image;
import buf from "./x.bin" as ArrayBuffer;
import blob from "./x.bin" as Blob;
import json from "./x.json" as JSON;
import str from "./x.txt" as String;
```

With a few custom functions using Symbol.importer this looks like it could fairly straightforwardly be extended to some interesting new cases with the help of a small library:

```js
import elem from "./x.html" as Selector("#elem");
import elemArr from "./x.html" as SelectorAll(".className");

// Automatically apply the CSS to the main document, as
// per original design of HTML imports
import style from "./x.css" as MainDocumentStyle;

// Custom implementations
import csv from "./x.csv" as CSVData;
import customerData from "./customerData.json" as CustomerData;
```

I think this looks like a great feature, very flexible and general-purpose without too big a spec surface area.

My view on some other points:

- I don't see a need to use a string in these statements, I think you'd either import an external resource, or just use an inline string in script (as is already done today)
- I don't think there should be an `import ... as HTMLTemplateElement` - it seems both a lot of work to define importers for each kind of element, and it's too limiting (how does it know which template element to return?). Something like `import templateElem from "./x.html" as Selector("#idOfTemplateElem")` seems better IMO, and more in line with how you'd use HTML imports today.
- normal script imports don't return promises, so I don't think any of these imports should either. You can `import img from "./x.png" as Image` if waiting for that import suits you; otherwise you can always create a new Image and wait for its onload as you can today. No need to reinvent that wheel.

Actually, thinking of async imports, it could actually be supported with custom importers. Suppose `import ... as X` calls a function with this signature:

```js
X[Symbol.importer] = function (url)
{
 // return a promise when the import is done
}
```

So as an example the JSON importer could be implemented like this:

```js
JSON[Symbol.importer] = function (url)
{
 return fetch(url)
 .then(response => response.json());
}
```

If there's some way to actually resolve with a promise, then you could implement imports which return a promise. The difficulty is, of course, that you can't resolve a promise with a promise, it will just wait for that promise to resolve and continue the chain. But if we try to work around that we could do something like:

```js
AsyncJSON[Symbol.importer] = function (url)
{
 // Return promise without waiting for it by putting it in
 // an object property
 return {
  promise: fetch(url)
    .then(response => response.json())
 };
}
```

Now you can do:

```js
import jsonPromise from "./x.json" as AsyncJSON;

// wait for import to load
jsonPromise.then(() => ...);
```

If that works, there's no need to distinguish "sync" vs. async imports, it can be implemented either way via Symbol.importer.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/645#issuecomment-310837725

Received on Saturday, 24 June 2017 13:14:35 UTC