-
Notifications
You must be signed in to change notification settings - Fork 376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTML Modules #645
Comments
@TakayoshiKochi made a polyfill (based on the <script type-module> polyfill by @matthewp) that implements one set of choices to the questions, and shows JS and HTML modules working together: https://github.com/TakayoshiKochi/script-type-module/tree/html-module-experiment |
Thanks for starting the discussion, @justinfagnani! For context for others, I've been involved with @TakayoshiKochi and others trying to firm up what HTML modules means before we present it widely. There's still a variety of possibilities. Here's my high-level overview: Writing a custom element that authors can include using a single file is a bit tricky. In particular, how do you get your template HTML? (Which is often literally a
At a high level, HTML modules wants to solve this problem. I think the case for it being a worthwhile problem would be stronger if we had data on the costs of the HTML-in-a-JS-string solution, but just by inspection it seems pretty bad. Still, I hope we can provide some data. The next big question then is about developer ergonomics: what should the authoring and consumption experience for web components be?
Hope this helps set the stage! |
Thanks for getting a public discussion going, @justinfagnani! I see HTML Modules as being a good container format for achieving generic subresource dependency specification. They solve a need for platform-level colocated Some questions:
|
I also want to point out that HTML modules would not prescribe how component developers package their libraries, or even prescribe Web Components for that matter. There are a number of styles that components could be written and/or packaged:
These styles could all be compatible. |
That's a good point. Even if we go with an opinionated container format with new capabilities, like @TakayoshiKochi's prototype, it will likely be possible to opt-out of those new capabilities, e.g. by just making your main element a |
It looks like @TakayoshiKochi's experiment doesn't create a new document for the imported module. Not sure if this is an intentional omission or not, as the @dglazkov sketch does mention there being a new document like in html imports. Here's an example module for those interested. In the interest of listing problems and not solutions I would say some things I want (in addition to other things mentioned by people above) are:
|
Thanks @justinfagnani for starting this thread! Thanks @domenic for the summary. We're open to any questions / problems for HTML modules. FYI, here's slide deck I presented in BlinkOn back in February: |
Re @matthewp (#645 (comment))
Yes, it was intentional. Imported HTML is treated as DocumentFragment (as opposed to Document), so we don't have to bother about various semantics to be satisfied, although it yields some weirdness (e.g. why/how can <script> inside be executed?). I'm interested if you prefer Document (other than that was described in Dimitri's doc) to DocumentFragment. If you're interested in history, here's record of Document vs DocumentFramgent for HTML Imports: |
We are interested in hearing requirements from framework authors, as HTML modules is not (should not be?) specific to web components definition (= container for custom elements and shadow DOM definition). I admit that my experimental polyfill was biased towards HTML Imports + web components, and would be a good fit for Polymer or Vue use cases, but I would be more excited if the resulting HTML modules would be usable for more than these frameworks or libraries. In my blink-dev thread, a developer from Scirra introduced me his very inspiring blog post: |
Here's my take on this. In today's world, developers are putting HTML inside their JS, not JS inside their HTML. The fact that we don't currently preload resources in a string literal, or we end up two string representations of HTML if you used string literal to include HTML in a JS file is a pure implementation detail. There is nothing preventing us from implementing an optimization if there was a well known symbol which was used to tag a HTML in a JS. Furthermore, for various performance reasons, we really need to have a mechanism to define an in-file ES6 module; a mechanism which allows multiple modules to be defined within a single JS file. Once we have that, then it's very natural to define three modules: one with HTML, one with CSS, and one with JS in a single JS file. So I'm not all convinced that we need to put JS into HTML as done in the HTML import. In fact, we'd likely oppose to such an approach on the basis that popular JS frameworks such as React have gone to the completely other direction of embedding HTML inside JS. |
@rniwa I find this opinion confusing given your interest in template parts. Are you not interested in that feature either, now? Or are you saying you'd prefer to define your |
While not being a framework author nor a browser developer here, just an end-user, I'd like to say that, although it is a widely adopted approach, it still requires tooling and you'll not be able to serve vanilla HTML, CSS and JS unprocessed by stuff like Webpack and so on. I'd also like to remind you that React was initially built with PHP where including HTML was once widely used. But is such a mixing really considered as a good practice by PHP developers now? Furthermore, how shall HTML modules work in browsers with disabled JavaScript? If markup stays in HTML, I can imagine them still working somehow. But what if it is placed in string literals? |
I wrote this blog post. I'm interested in participating in work for HTML modules, and I think our experience is valuable: we have published a commercial PWA using ~300 HTML imports. As I touched on in the blog, I quite like the idea of being able to import a HTML file and get a Document, much like XHR for type "document". So this:
would be similar to assigning Then all you need to do is add a HTML tag that can propagate to further dependencies. I suggested changing
to be equivalent to
It could equally be I have to say style application from imports is a useful feature for us - see my example of a dialog definition for an example. It's possible a framework could work around this (e.g. If HTML modules covered that, I'd guess that largely covers everything we use imports for. In our case they're largely just the architectural scaffolding that brings together all the components of our web app, and as I tried to emphasise in my blog, they excel at that, particularly since it covers all three aspects of a web app (markup, style, script, at least until Google roll back style application 😢). I am strongly against trying to use script for any markup or style content. I know some frameworks are having success with that approach, and so we shouldn't do anything that makes that harder. But if you have 1000 lines of markup, surely nobody wants to paste that in to a script as a giant string? I strongly believe that there should at least be the provision for leaving markup in HTML files, and not orient the spec around doing what one framework does today. Remember frameworks come and go over the years. In our case, our PWA is notable for not using VDOM, has almost no use of markup-in-script, uses plain markup (no Angular-style directives), no templating (like {{this}} in markup), and no two-way data binding. I don't think any other framework on the web today takes this approach, but I believe our PWA proves that you can still build scalable, complex web apps that way. I do worry that people have framework-blindness where they think things should be done like the frameworks do, rather than thinking in terms of providing general-purpose capabilities that frameworks of different designs and approaches can make use of, even in the future when everything likely changes. Anyway, here's a couple of extra ideas that may be useful to extend the utility of HTML modules as I described them. Perhaps it'd be useful to add a selector to pick out specific elements, e.g.:
Now Finally I don't know if it makes sense to export from a HTML module, but perhaps you could have something like:
where myimport.html has a special tag like
Perhaps that could also be reconfigured to re-export a JS module that the HTML module imports, e.g:
...then allowing |
I can answer that, at least: they won't. HTML modules are part of the module system, which is entirely dependent on JavaScript. Even HTML imports never worked in browsers without JavaScript. (The document would be "imported", but useless, since you need script to access imported documents.) |
Depending on future developments of course. Declarative custom elements (which we'll talk about at TPAC) presumably wouldn't need script enabled. |
Uh... let's just say I disagree with you very strongly on that, and we can leave that discussion for another time, instead of derailing the thread. |
@rniwa I wouldn't want to encode only what has become most popular today for two reasons:
I'm not saying JS shouldn't also gain pre-loading and multi-module support, of course. |
If we intended to make JavaScript mandatory then we would combine the
specs. As the HTML spec sits today JS and CSS support HTML, not the other
way around. We can make new specs that mix those concerns, but they would
not be HTML anymore. It would look like classic ASP or early PHP. It is
worth observing neither of these became specifications. Nor are either in
wide use today.
I am happy to support the use cases where components mix HTML/CSS/JS but
there are more use cases than this. As mentioned above, this is simply a
trend in some circles today. I do not support making this mandatory. HTML
Imports as it stands today requires JavaScript. As such i do not consider
HTML Imports finished.
If we finished the spec for HTML Imports, would we need HTML Modules at
all? A syntax similar to what Ashely proposes seems sufficient.
…On Wed, Jun 21, 2017 at 12:07 Justin Fagnani ***@***.***> wrote:
@rniwa <https://github.com/rniwa> I wouldn't want to encode *only* what
has become most popular today for two reasons:
1.
Because where we are now is largely a consequence of what capabilities
the platform has had. JavaScript developed popular user-land module systems
and loaders long before HTML Imports, and is now getting widespread native
modules before HTML. Given the lack of support HTML Imports has, Polymer
has had to carefully weigh it's options for working in browsers without
polyfills. If Polymer had decided to support a pure-JS distribution that
would have been be a pragmatic choice only and not an indication of what
we'd really like to use.
2.
The assertion (developers are putting HTML inside their JS, not JS
inside their HTML) might not be so absolute. Polymer and Vue are current
examples of libraries that support single-file HTML components with
scripts. There would be much more if it were a native capability.
I'm not saying JS shouldn't also gain pre-loading and multi-module
support, of course.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#645 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGYGJ10U3td_PM_RGgRTbVQZGIfr5bY2ks5sGT_YgaJpZM4N_wrF>
.
|
The only way I can imagine HTML modules being useful with script disabled is if they basically inserted their full DOM content at the place they were included. So to use HTML imports as an example, I get that some people are annoyed by the obnoxious things JS does on some pages. But if you're building a web app, it's simply inconceivable to develop it without JS. It would be like writing an Android app with Java disabled - can you still produce a useful app? The web is still an amazing resource for static documents which can work with JS disabled, but on the whole I think modules are aimed very much at the app side of development, where it would naturally pair with JS logic for an app. Still, I don't see any reason to exclude the HTML-only case. Maybe an |
That is precisely the use case. In the bad old days some of us built out
template systems that used server side includes. The point is not to
eliminate JS and CSS by the way, but to have graceful fallback options
while still allowing for some sort of modularity for sites with a large
amounts of mostly static content. It would work hand in hand with
<template> and custom elements.
That fallback by the way? It also allows that often machines are reading
and making use of that content. Combine with something like Linked Data and
we actually have a web that works as intended.
…On Wed, Jun 21, 2017 at 19:01 Ashley (Scirra) ***@***.***> wrote:
The only way I can imagine HTML modules being useful with script disabled
is if they basically inserted their full DOM content at the place they were
included. So to use HTML imports as an example, <link rel="import"
href="import.html"> would be equivalent to copy-pasting the contents of
import.html in place of that tag. Is that really a significant use case?
Perhaps there could be an extra mode to do that, but would anyone use it?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#645 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGYGJ_yAGHU_C4uE_PtoBQiKQUag6J3bks5sGaDNgaJpZM4N_wrF>
.
|
Perhaps we need to figure out what the declarative syntax for shadow DOM / custom elements will look like before we can figure out what HTML import should look like. It's hard to talk about packaging a thing without knowing what the thing looks like. |
For including HTML into HTML, probably you can imagine there is a |
Yes, I think the include case should be split out in to a separate discussion. Maybe a new issue should be filed for it? |
@AshleyScirra if you want it to happen, whatwg/html would be more appropriate place to file an issue than here. @rniwa declarative Shadow DOM / Custom Elements would be nice to have, but we don't have to be blocked on it, because assuming it's all written in HTML and no script then it is just a plain HTML. Although I can imagine that declarative syntax would not be such a simple thing because its semantics would involve hooks into HTML parser and DOM tree construction...
Is this idea presented or discussed anywhere? This is very interesting and I would like to learn more about it.
Real-world web development is constrained by actual implementations of browsers available and used today, and React may be the optimal thing to do modular development on the current web platform, but as we are expanding (relaxing?) the constraints of the platform, we don't have to be trapped in the local optima. (that said, I don't say we should ignore React's popularity) |
I would be very curious to hear opinions from some framework authors - e.g @sebmarkbage (React), @developit (Preact), @yyx990803 (Vue) and @IgorMinar (Angular) on the direction of embedding resources like styles and HTML inside JS. I acknowledge this is an increasingly popular pattern, however I'm curious if the availability of HTML Modules where colocated resources (including ES Modules) are a first-class citizen would actually be something they would find useful. In particular for the final bundles that get generated from their tools/Webpack. Vue, at least during the dev/iteration workflow appears to have shifted closer to a HTML Imports-type thing while preserving some of the options for authoring in JSX or styles-in-JS if you really want to. It still converts everything to JS during the build cycle.
Do you see the need for a mechanism offering multiple ES modules in a single JS file being much different to a HTML module being the container enabling that? e.g bundle.1.html
|
I'd like to emphasise that a lack of declarative shadow DOM is a pretty massive complaint from the community and shouldn't be dismissed as a nice to have. |
I don't think it's a dismissal at all. In the context of HTML Modules, the question is whether or not declarative custom elements and shadow roots should block moving forward on modules. |
👍 just making sure it's being heard is all. |
@addyosmani I do think this general architecture is valuable. It can be used to import both somewhat static content but also for loading pieces of a server-rendered page out-of-order and inject dynamically. So, I'm all for it for frameworks that are HTML heavy and centric. However, for React, and I believe this is a more general trend, we're increasingly looking for ways to avoid passing static, or server responses, as HTML as the serialization format. For these use cases we might use custom byte codes like Glimmer or some other format. There's a lot of value in a richer serialization format that can include more data to pass to JS, cheap branching and conditional logic, immediate access to references to nodes etc. I'm asking myself what value HTML, as the serialization format, offers to a JS library once it's already up and running. I see soft value like familiarity, and concrete value like browser specific caching formats. However, those have to be weighed against other things. Even if you use what seems to happen is that you end up with two modes in the JS library to deal with nodes created from HTML and nodes created from another mechanism. That adds complexity and code. |
Can you clarify
Node in HTML Modules would be standard Nodes in the rest of the DOM, there wouldn't be different types. |
Anyone played with some of these ideas in real life? I come with some good engagement with the usecase and I can say that what the warfront is dictating is a HTML-primary, JS-secodnary type of a module system. It seems to me that the JS approach is all being induced for some reason I can't figure out! It seems to me that important comments here emphasizing a HTML-oriented approach aren't being honoured at all. But truth is, these comments are simply the usecase talking. Even with the passing of time, the usecase today is still all about just being able to reuse HTML all by itself. Unfortunately, JavaScript keeps hunting down HTML everywhere. It's a feeling we don't want! And if we end up shipping one more thing like this, we would naturally seek peace with some other means to the same end, and "HTML Modules" would sit all by itself! All I have ever wanted, is being able to reuse HTML content; and without JavaScript! I already have ES6 modules for anything JS! Let me explain properly...
I can say convincingly that once you begin working with You'll find out however that all of the above features is only a part of what we need together to be able to author modular, reactive UI with just native HTML. Answering this challenge has been my project at WebQit which I have summed up as OOHTML (formally CHTML). OOHTML (Object-Oriented HTML) is a proposed suite of UI features that let's us build modular, reactive UIs natively.
|
I also come in advocacy of HTML modules, and an HTML-first approach. I'm working on a tool that will compile TypeScript (+ JSX) to HTML Modules. It just takes existing tools, the TS compiler & WBN (for creating web bundles), and spits out HTML modules, either disparately, or as part of a single bundle. I only have a bare-bones prototype working, but I figured it couldn't hurt to add to the discussion here in favor of standardizing HTML modules. (Feel free to tell me how bad you think this idea is; I have many ideas, not all of them are worth seeing the light of day, lol. On the off chance that you approve of the idea, I'm looking for help.) |
Html include is a still hot topic. Html module just a sugar on top of concept. HTC is a w3c proposal and does include most of needed but well forgotten. |
I am pleased to announce our new documentation for OOHTML: https://webqit.io/tooling/oohtml. It's been over 7 months since I posted about OOHTML - our implementation of a HTML-based module system for HTML.
The months since then have furnished us a complete picture of this approach and have brought even more stability to our implementation. OOHTML is fully usable today. Here is a 3-min overview: https://webqit.io/tooling/oohtml/docs/getting-started/overview |
@ox-harris the thing that you do is really impressive and I admire that, but I have great doubts about the marketing promises that you make. You mention |
It's indeed an important feedback @GeorgeTailor . But somehow, we also have factored this into OOHTML; maybe it isn't very obvious. This page in the docs - https://webqit.io/tooling/oohtml/docs/resources/meta-tag - recommends using the OOHTML meta tag to customise attribute and element names to something like what you've wished. So, the We're hoping to see the different ways developers imagine a module system for HTML. And with an implementation that is completely bendable, we hope OOTHML can be a great foundation for that. I am hoping I can put up a more formal proposal at the relevant for OOHTML. The goal is to get OOHTML on a standards track. |
@ox-harris , could you highlight the difference between oohtml and web components v1? |
@justinfagnani , @dglazkov, @domenic let take a look into root cause of the need for such html imports, how it was addressed in history and what is really missing in given proposal. The imports for different content types has been in demand since HTML appearance. Except of initially they been addressed differently in own "tiers" and there was no systematic/unified approach. IFrame, CSS, images in HTML, of course SCRIPT of few kinds, etc. That combination of not unified load and consuming resources have created the need for unification as the volume of web apps simply could not be supported by such approach. Industry have developed the work around as site builders and later build toolchains which been treated resources in same fashion - from registry/dependency tree to loading. import './mystyles.scss`
import `@typography/spacing.scss`
import `@typography/roboto.ttf`
import scopedDef from `./myCssMod.scss`
import logo from './app.svg'
import headerTemplate from './headerTemplate.html`
... images, fonts, images, html templates are been treated alike by WebPack, RollUp, and other build toolchains. SASS been compiled into CSS, than converted either to LINK or STYLE. Along the way it also been massaged to add compatibility layers or virtually any programmable functionality. Similar transformation is done for images and fonts. If we are going to tackle little problems like HTML imports or import maps in insulation from whole delivery chain, the standard would prevent the concept extension into already existing patterns proven to be in high demand ( build toolchains) in web platform. Rather 'html', 'import maps', etc. we need from browser platform the layers of functionality needed for complex Web 3.0. The module resolvers capable of working with semver CDNs with integrity in mind: The loader with pre- and post- processing transformation chain driven by the changing along content type. The container capable of insulation layers from CSS to JS gradually exposing or hiding internals. And so on, everything which we are currently utilize as app build framework but in browser. The idea is not new: build toolchains running in browser are known more than decade. Question is The html import here is just a string loader as I see it. The import as module could treat itself or its parts in several different ways:
and so on. Taking/picking one or another side of implementation now would mean 100% future deprecation! Instead, the page and particular module should have ability to control ( or point to external descriptor ) the content-type driven transformation. The app developer would pick or define the way this transformation happen. And consumer JS or HTML would be written according to defined transformation chain. |
I might need direct pointers to the areas of comparison you have in mind. But OOHTML and Web Components aren't competing for the same problems. OOHTML is seeking to address aspects that (we think) do not necessarily fall in the domain of Web Components. Yet, it bases itself off Web Components to offer a higher-level feature set. And in turn, these feature set comes with a simpler way to make Web Components. (Lest the name "OOHTML" sounds like a big thing to ask, think of it as simply a codename for a set of features that solve common HTML-related difficulties.) For example:
Overall, "OOHTML" is simply an umbrella name for a feature-set that saves us of unnecessary JavaScript, help us write better HTML and simplify how we author web components. |
It would be really nice if somehow we could fix inline event handlers with HTML modules. |
This may require its own champion and proposal/explainer, but I feel like it falls well enough in line that it might be worth mentioning: Scoping of JavaScript references inside of To elaborate slightly (before rushing to dinner), the actual mechanism may include waiting to evaluate JS references in attributes for children of a <template id="myCustomElementTemplate">
<button onclick="this.#handleClick">Click me!</button>
</template>
<script type="module">
/* ... */
class myCustomElement extends HTMLElement {
constructor() {
super();
// ShadowDOM is attached to instance of myCustomElement here
let shadowRoot = this.attachShadow({ mode: "open" });
let template = importDoc.getElementById("myCustomElementTemplate");
// The `this` of any children of a ShadowRoot will be equal to the instance of the
// element, allowing access to public **and private** methods
shadowRoot.appendChild(template.content.cloneNode(true));
}
#handleClick(e) {
console.log("Clicked!", e);
}
}
/* ... */
</script> Again, this may very well need to be in its own proposal |
This could potentially pave the way for other mechanisms, including (one which is certainly out of the scope of this proposal): binding attribute values to instance properties, and so on. |
This sort've concept is interesting, but web specs don't add features that have special powers to be able to do things in other JS scopes. Like in order to resolve A general rule of thumb, is that web objects don't really have more power than JS objects, they are just (potentially) implemented in a different language. In this case there would be no way to implement something like what you were describing: class ShadowRoot extends DocumentFragment {
appendChild(node) {
if (node.hasAttribute("onclick")) {
// No way to access this.#handleClick in this method
// so web specs can't either
}
}
} The exact reasons for this general rule of thumb are varied, some reasons include the ability to separate the JS engine from the browser, some are to allow the engine to optimize things it otherwise couldn't, some are just to respect the intended design of features (i.e. private means private), some are to allow JS to faithfully mock APIs in tests, etc. |
You can already create this monstrosity: <template id="myCustomElementTemplate">
<button onclick="this.getRootNode().host.constructor.handleClick.call(this, event)">Click me!</button>
</template> And yes, it works and is cloneable. Though |
@Jamesernator Fair enough for private members. However, I still feel that this may still be viable for public fields, no? |
I've kinda moved to just wanting HTML to parse HTML and then some extra code for the client to consider how to use it. It then moves to the current, live document which decides when and how to adopt the imported HTML to the current, live document. For example, if an HTML import has a It kinda leans to an HTML import should probably be a DocumentFragment + extras. This would be similar to how If it's to consume the JS inside it, maybe a If it's a set of resources, we might want to immediate start fetching those resourced by calling What really gets interested is, should we just lock all the new intended functionality behind an import? For example CSS imports are just constructed Right now, I'm experimenting the use case of splitting a page that has something like 30 different Web Components as critical and non-critical Web Components. As of now, HTML-in-JS requires parsing of the string and that's done synchronously. That means my Web Components are loaded in series. I would like them be loaded in parallel by using |
Just throwing in my support and desire for HTML Modules. I like that idea of using them to import what looks to be similar to an import htmlTemplateThing from 'foo.html';
const documentFragment = htmlTemplateThing.content.cloneNode(true);
// Do stuff with documentFragment or append it wherever you want... The alternative today is authoring HTML as JS template literals and being limited to More than that though, we so badly need this for packaging Web Components. Authoring and "importing" a complete Web Component is a pretty lame experience. You have to somehow get all your components' template source code, e.g. <template>
Single File Web Component!
<style>
:host {...}
</style>
</template>
<script type="module">
customElements.define('x-sfwc', class extends HTMLElement {
#template = import.meta.document.querySelector('template');
constructor() {
super();
this.attachShadow({ mode: 'open' }).appendChild(this.#template.content.cloneNode(true));
}
})
</script> |
Now that JavaScript modules are on the verge of widespread browser support, we should think about an HTML module system that plays well with it. HTML Imports doesn't have a mechanism for exporting symbols, nor can they be imported by JavaScript, however its loading behavior is quite compatible with JavaScript modules.
@dglazkov sketched out a proposal for HTML modules here: https://github.com/dglazkov/webcomponents/blob/html-modules/proposals/HTML-Imports-and-ES-Modules.md
The main points are that, using the JavaScript modules plumbing, you can import HTML.
Either in HTML:
or JavaScript:
But within the scope of that sketch there are still several questions about the specifics of exporting symbols from HTML and importing to JavaScript.
The text was updated successfully, but these errors were encountered: