Skip to content

Commit a0388a2

Browse files
Addressing Domenic's Feedback In Declarative CSS Modules (#1143)
Per our chat, this PR addresses all of the action items from our discussion with Domenic.
1 parent 9df1cfd commit a0388a2

1 file changed

Lines changed: 44 additions & 2 deletions

File tree

ShadowDOM/explainer.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ content location of future work and discussions.
4646
- [Scoping](#scoping)
4747
- [`<script>` vs `<style>` For CSS Modules](#script-vs-style-for-css-modules)
4848
- [Behavior with script disabled](#behavior-with-script-disabled)
49+
- [Updates to Module Map Key](#updates-to-module-map-key)
4950
- [Detailed Parsing Workflow](#detailed-parsing-workflow)
5051
- [Use with Imperative Module Scripts](#use-with-imperative-module-scripts)
5152
- [Use with Import Maps](#use-with-import-maps)
@@ -262,12 +263,27 @@ A global map does come with some tradeoffs, particularly when names collide. Wit
262263

263264
### `<script>` vs `<style>` For CSS Modules
264265

265-
Earlier versions of this document used the `<script>` tag for declaring CSS Modules. Developer feedback has shown a strong preference for using the `<style>` tag when declaring CSS Modules, so this proposal has been updated accordingly. The `<script>` tag remains a more natural wrapper for [other declarative modules](#other-declarative-modules).
266+
Earlier versions of this document used the `<script>` tag for declaring CSS Modules, which would be more consistent with the current set of module types (as they are all script-related). Developer feedback has shown a strong preference for using the `<style>` tag when declaring CSS Modules, so this proposal has been updated accordingly. This concept of using a non-`<script>` tag for defining Declarative CSS Modules could be expanded for future declarative modules such as HTML and SVG. The `<script>` tag remains a natural wrapper for [other declarative modules](#other-declarative-modules) that are script-based, such as JavaScript, JSON, and WASM.
266267

267268
### Behavior with script disabled
268269

269270
User agents allow for disabling JavaScript, and declarative modules should still work with JavaScript disabled. However, the module graph as it exists today only functions with script enabled. Browser engines should confirm whether this is feasible with their current implementations. Chromium has been verified as compatible, but other engines such as WebKit and Gecko have not been verified yet.
270271

272+
### Updates to Module Map Key
273+
274+
A significant piece of this proposal involves modifying the [module map](https://html.spec.whatwg.org/#module-map) to be keyed by a string instead of a URL (the current key is a (URL, module type) pair, which this proposal updates to a (string, module type) pair). A string is a superset of a URL, so this modification will not break existing scenarios.
275+
276+
This proposal could avoid this requirement by instead requiring a declarative specifier to be a [URL fragment](https://url.spec.whatwg.org/#concept-url-fragment), but we believe this would introduce several potentially confusing and undesirable outcomes:
277+
278+
1. The [Find a potential indicated element](https://html.spec.whatwg.org/#find-a-potential-indicated-element) algorithm only searches the top-level document and does not query shadow roots. While this proposal does not require the [find a potential indicated element](https://html.spec.whatwg.org/#find-a-potential-indicated-element) to function (the indicated element in this case is the `<style>` element that is directly modifying the module map, so there is no element to find), it could be confusing to introduce a new fragment syntax intended for use in shadow roots that violates this principle.
279+
2. [Import maps](https://html.spec.whatwg.org/#import-map) remap URL's, which allows relative and bare URL's to map to a full URL. It's not clear if there is a use case for remapping same-document references with import maps that cannot be accomplished by adjusting the local reference's identifier. If import maps are performed on a same-document URL reference, an import map entry intended for an external URL could unintentially break a local reference. [Import map resolution](https://html.spec.whatwg.org/#resolving-a-url-like-module-specifier) could be adjusted to skip same-document references, but it could be confusing to have a URL identifier that does not participate in the [resolved module set](https://html.spec.whatwg.org/#resolved-module-set).
280+
3. HTML documents are already using fragments for many different concepts, such as [fragment navigations](https://html.spec.whatwg.org/#navigate-fragid), [history updates](https://html.spec.whatwg.org/#url-and-history-update-steps), [internal resource links](https://html.spec.whatwg.org/#process-internal-resource-links), [SVG href targets](https://www.w3.org/TR/SVG2/struct.html#UseElement), and more. Although these use cases are very different, a common factor between them is that they all reference elements in the main document, and cannot refer to elements within a shadow root. An important piece of this proposal is that nested shadow roots can modify the global module map. Introducing a new scoping behavior for fragments that does not fit this model could be confusing to authors.
281+
4. URL's that consist only of a fragment resolve to a [relative URL](https://url.spec.whatwg.org/#relative-url-string), with the base url defined as the source document per [the URL parsing algorithm](https://url.spec.whatwg.org/#url-parsing). This means that using a fragment-only syntax (which would be desired in this scenario) could break if a [`<base>` element](https://html.spec.whatwg.org/#the-base-element) exists that remaps the document's base URL.
282+
283+
Another alternative could be to define a new [scheme](https://url.spec.whatwg.org/#concept-url-scheme) for local references. This is a potential solution, however, since the containing HTML document already has a scheme, this option would require developers to always specify the [scheme](https://url.spec.whatwg.org/#concept-url-scheme) per [absolute URL with fragment string](https://url.spec.whatwg.org/#absolute-url-with-fragment-string) processing, rather than just the fragment (a fragment-only URL is valid due to the way [relative URL](https://url.spec.whatwg.org/#relative-url-string) processing applies). Developers might find it cumbersome to specify the scheme for local references versus an approach that requires only an identifier (for example, `localid://foo` versus `#foo` or `foo`). A new scheme could also imply scoping behaviors that are not supported, such as [external-file references](https://www.w3.org/TR/SVG2/linking.html#definitions) that are valid in SVG, or potentially even imply that module identifiers can span between `<iframe>` documents. A new scheme may also not be compatible with existing [custom scheme handlers](https://html.spec.whatwg.org/#custom-handlers).
284+
285+
For these reasons, we believe that modifying the [module map](https://html.spec.whatwg.org/#module-map) to be keyed by a string instead of a URL is a more natural solution for developers, as it avoids all of these situations.
286+
271287
### Detailed Parsing Workflow
272288

273289
In the following example:
@@ -445,7 +461,7 @@ parsing SVG inside the <template>. -->
445461
```
446462
SVG makes heavy use of IDREF's, for example `href` on `<use>` and SVG filters. Per existing Shadow DOM behavior, these IDREF's would be scoped per shadow root.
447463
448-
CSS Modules are not the only type of module - there are also JavasScript, JSON, SVG, HTML, and WASM that need to be considered.
464+
CSS Modules are not the only type of module - there are also JavaScript, JSON, SVG, HTML, and WASM that need to be considered.
449465
450466
| Module type | Script Module | Declarative Module |
451467
| -------------- | -------------------------------------------------------- | --------------------------------------------------------------------------|
@@ -456,6 +472,32 @@ CSS Modules are not the only type of module - there are also JavasScript, JSON,
456472
| SVG | `import {foo} from "bar.svg" with {type: "svg"};` | `<template type="svg-module" specifier="bar"></template>` |
457473
| WASM | `import {foo} from "bar.wasm" with {type: "wasm"};` | `<script type="wasm-module" specifier="bar"></script>` |
458474
475+
Modules that support declarative content (such as CSS Modules and HTML Modules) need both a declarative export mechanism (`<style type="module">` for CSS Modules) and a declarative import mechanism (the `adoptedstylesheets` attribute and/or the `<link>` tag for CSS Modules), while purely script-based modules types (such as JavaScript, JSON, and WASM) only require a declarative export mechanism, as they are expected to be imported via script.
476+
477+
The following example demonstrates how a JavaScript module could be exported declaratively and imported imperatively:
478+
479+
```html
480+
<script type="module" specifier="foo">
481+
export const magic_number = 42;
482+
</script>
483+
<script type="module">
484+
import {magic_number} from "foo";
485+
console.log(magic_number);
486+
</script>
487+
```
488+
489+
...and likewise for a JSON module:
490+
491+
```html
492+
<script type="json-module" specifier="foo">
493+
{"people": [{"craft": "ISS", "name": "Oleg Kononenko"}, {"craft": "ISS", "name": "Nikolai Chub"}], "number": 2, "message": "success"}
494+
</script>
495+
<script type="module">
496+
import people_in_space from "foo" with { type: "json" };
497+
console.log(people_in_space.message);
498+
</script>
499+
```
500+
459501
## Alternate proposals
460502
461503
### Using A Link Tag To Adopt Stylesheets

0 commit comments

Comments
 (0)