-
Notifications
You must be signed in to change notification settings - Fork 185
support <script type=module> within HTML imports #95
Comments
Are we limiting the scope of this to native imports or including Polymer polyfilled imports? |
If it is possible to make it work for the polyfilled imports, without too much extra code, then I think we should enable that support. |
Note that since this behaviour is not specified anywhere, it is important to ensure all decisions are carefully documented / communicated if we do implement this. |
Digging up this old issue, 'cause I was just linked to it, and everyone's thoughts may have changed since then. Really not a fan of relying on the parser-blocking behavior of imports to make that go. E.g. assuming that the
We really need to be able to declare dependencies across content types (and make sure that the loader isn't imposing too many assumptions about JS-only source) |
@nevir thanks for picking up on this discussion! Can you clarify what you mean about having to double declare the dependency? The HTML imports polyfill cannot perfectly simulate the execution order either, so I guess it is exactly the same issue here? Would be interesting to hear how this has come up for users there. As far as I'm aware though, the inability for a polyfill to work has never been accepted as a valid argument for altering specified behaviour? |
@nevir I've updated the top description here to reflect the latest information as I know it. Perhaps that clarifies some things? |
Why is My hope is that <script>
System.import('main.js').catch(function(e) { console.error(e && e.stack || e)})
</script> eventually becomes <script src="main.js"></script> and works everywhere, not just in HTML imports. |
@MajorBreakfast yes that becomes |
@guybedford |
No, script is completely different and stays backwards-compatible. |
can I check what is being proposed here? At the moment, the loader is looking for script tags on DOMContentLoaded. As I understand the HTML Imports spec, this would not be fired until the imports and all nested/dependent imports were also loaded. So what is proposed here is that the function would also loop through all the import documents looking for module tags. Is that right? Would it know (or need to know) in which order to execute them? One thing that occurs to me whilst thinking about processing web components is that the polyfill would not be able to execute any modules within a |
@probins yes exactly, it would have to go through the logic as best as possible and execution order as well. Currently this feature is on hold, until there is real implementation pressure from web components users / authors. |
To be honest, I would doubt whether most developers are even aware of the module tag. Web components is in much the same status as the module loader: people are still working out how best to use them. So to me this comes under 'nice to have' rather than 'must have', particularly as you can probably use |
and another thing this proposal wouldn't handle is HTML imports loaded dynamically. As the current code does |
ok, so here's my solution for components, which works with both static and dynamic HTML Imports, and allows for bundled/concatenated templates/scripts. I've added the following function (a variant of the existing one): System.componentCallback = function(e) {
var scripts = e.target.import.getElementsByTagName('script');
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
if (script.type == 'module') {
var source = script.innerHTML.substr(1);
System.module(source)
.catch(function(err) { setTimeout(function() { throw err; }); });
}
}
}; This would be used as the onload callback on static links: For dynamic links (link injection), I'm using: function importComponent(element, href) {
var frag = document.createDocumentFragment();
var link = document.createElement('link');
link.rel = 'import';
link.href = href;
link.id = element + 'link';
link.addEventListener('load', System.componentCallback);
frag.appendChild(link);
document.head.appendChild(frag);
} A self-including component might look like: <template id="mytemplate">
<div>Hello world</div>
</template>
<script type="module">
document.body.appendChild(document.importNode(document.getElementById('mylink').import
.getElementById('mytemplate').content, true));
</script> With scripts, you can do I'm using CJS in my module, and this works fine. One small issue I noticed when you have several components with an anonymous module is that the browser's devtools refers to them all as 'undefined', so when you click on the link from the console you always get the first one - makes debugging a tad problematic. Best to make sure your anonymous modules don't have any errors :-) And of course you have to use Polymer's HTML Imports polyfill if you're not using Chrome/Opera or Firefox with flag set (and template tag isn't currently supported in IE). |
my example above doesn't work if a component is requested twice, as the callback is executed twice (at least, that's the way Chrome has implemented it - not sure if that's a bug or not). The easiest way around this is to move the module code into a separate file, so it's imported with the loader. You could do In addition, there is no link between the module code and the imported document, as this isn't the All in all, I've come to the conclusion that HTML Imports with modules instead of script tags aren't worth the bother, and have gone back to importing HTML from the modules with the text plugin and good ol So, @guybedford no 'pressure' from me to implement this - continue to concentrate on the loader :-) |
@probins The |
feel free 😄 |
Hey folks, I'm having some success over here: https://github.com/Hypercubed/systemjs-plugin-html/ . One issue I am having is that SystemJS imports within a HTML import are relative to the root document url. Not sure how to fix that. |
I guess you could consider supporting I've hesitated implementing the above in SystemJS as the semantics of the above, while likely, are still to be specified, but it may be an option. |
So right now I am calling P.S. I have a branch that is building imports using polymer vulcanize: https://github.com/Hypercubed/systemjs-plugin-html/tree/vulcanize |
but the discussion on the loader spec seems to conclude that modules loaded with a module tag would always be anonymous, so would be System.module not System.import. This is related to the issue I encountered when a component is included in more than one HTML Import: the polyfill doesn't know it's already loaded that one (as it's not in the registry) so loads (and executes) it again. This problem might well go away in native implementations though, as the browser would know it's already got it in cache. IMHO the HTML Import spec needs revisiting/revising to define how they should be handled in a modular environment. |
For interest, see recent discussion at https://github.com/dglazkov/webcomponents/blob/html-modules/proposals/HTML-Imports-and-ES-Modules.md. |
thanx for the link - that looks promising |
and https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/uba6pMr-jec/tXdg6YYPBAAJ gives some info on status in Chrome/blink |
ISTM you can close this with a "won't fix". |
To summarize
<script type=module>
, there are two forms - an anonymous form with module code inside:and a named form for loading from external module files:
In both cases, the parsing of the tag above can immediately trigger the fetch cycle for modules, which will in turn fetch their dependencies.
Execution itself is deferred only until the execution thread of the HTML page reaches that point in the page, just like a normal script tag.
This behaviour then needs to thread into HTML imports in the same way as for a script tag - that is with the delayed execution following the import readiness, and the parser triggering the tree loading.
The text was updated successfully, but these errors were encountered: