Re: [w3c/webcomponents] CSS Modules (#759)

@matthewp , @bzbarsky 
Option 2 vs 3 would not behave differently in terms of the the styles that are applied.  The difference is just whether a doubly-`@imported` stylesheet in a CSS module tree would have distinct identities for each time that it is `@imported` (as is the case for non-module CSS), or whether each `@import` of the same stylesheet in a CSS module tree would point to the same `CSSStyleSheet` object.  I suppose that the order in which CSS files are fetched could be affected by whether `@imports` are modules or not but this is more of an implementation detail as that doesn't change the form of the final cascade and CSS OM.

I think it would be helpful to write out the example being discussed above as code:

**a.css**:
```css
div { background-color: azure }
```

**b.css**:
```css
@import url("a.css");
div { background-color: brown }
```

**c.css**:
```css
@import url("a.css");
div { background-color: chartreuse }
```

**main.html**:
```html
<style>
  @import url("b.css");
  @import url("c.css");
</style>
<div>This div will be chartreuse</div>
<script>
  let style = document.querySelector("style");
  let bSheet = style.sheet.rules[0].styleSheet;
  let cSheet = style.sheet.rules[1].styleSheet;
  let aSheetFromBSheet = bSheet.rules[0].styleSheet;
  let aSheetFromCSheet = cSheet.rules[0].styleSheet;
  console.log(`${aSheetFromBSheet === aSheetFromCSheet}`); // Prints 'false'; duplicate @imports have their own identities
</script>
```

**mainUsingCSSModules.html**
```html
<script type="module">
  import bSheet from "./b.css";
  import cSheet from "./c.css";

  document.adoptedStyleSheets = [bSheet, cSheet];

  let aSheetFromBSheet = bSheet.rules[0].styleSheet;
  let aSheetFromCSheet = cSheet.rules[0].styleSheet;
  console.log(`${aSheetFromBSheet === aSheetFromCSheet}`); // Prints 'false' if option 2, 'true' if option 3
</script>
<div>This div will be chartreuse</div>
```

For mainUsingCSSModule.html, the resulting cascade is mostly the same regardless of whether we go with option 2 or option 3.  The difference is that for option 3, a single `CSSStyleSheet` is shared by the `@import` from B and the `@import` from C since "a.css" would participate in the module graph and thus be processed only once for the page.  As @justinfagnani pointed out this is similar to JS modules where multiple imports of a single script share one instance.

However, option 3 may come with certain other complications that we would need to contend with.  For example, what is the `parentStyleSheet` and the `ownerRule` of `aSheetFromBSheet`/`aSheetFromCSheet` if they are the same `CSSStyleSheet`?   I'm not sure that this divergence from existing invariants is worth it, especially since as @bzbarsky pointed out [here](https://github.com/w3c/webcomponents/issues/759#issuecomment-490309265), browser engines should generally coalesce duplicate stylesheet loads anyway, minimizing the additional performance wins that would come with option 3.  Is there some concrete improvement in developer experience that option 3 would provide that would tip the scale in its direction?

-- 
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/759#issuecomment-490654382

Received on Wednesday, 8 May 2019 21:18:49 UTC