Closed justinfagnani closed 2 years ago
The specific issue of adoptedStyleSheets
is tracked in the issue 45.
Thanks for your kind replies.
If I add some context to my own usage :
A] It is important to await async functions
arr = ['a'];
function resolveAfter (value, ms) {
return new Promise(f => setTimeout(() => f(value), ms));
}
async function addB() {
arr = [...arr, await resolveAfter('b', 100)];
}
async function addC() {
arr = [...arr, await resolveAfter('c', 50)];
}
await addB(); // <------- It is important to await async functions
await addC(); // <------- It is important to await async functions
// immediately...
console.log(arr); // ['a', 'b', 'c'] <------- as expected
The litigious code :
document.adoptedStyleSheets = [...document.adoptedStyleSheets, await import('./style.css')];
... was expected to be part of an async function, and this function was expected to be awaited, as its ancestors, until we reach the main function.
// deep code
const style = async () => {
document.adoptedStyleSheets = [...document.adoptedStyleSheets, await import('./style.css')];
}
await style(); // <------- I do await in 99.99% of my code
B] The only case I authorize myself to not await an async function is... the main.
// index.js
const main = async () => {
// ...
}
main(); // <------- I do *not* await at top level
A developer can still use the litigious code in the main function. In this specific case, developer might experience race conditions. Result seems strongly related to the very nature of async / await and how the developer masters it.
Opened an issue to discuss an alternative name to adoptedStyleSheets
: https://github.com/WICG/construct-stylesheets/issues/97
Mozilla appears to be way behind on this stuff. You can't even achieve CSS Modules the manual way which already works in Chromium.
If I open up a console in Firefox 68.0.2, and type:
let sheet = new CSSStyleSheet();
I get this error:
TypeError: Illegal constructor.
You can achieve some efficiency in Firefox using <link rel="stylesheet">
, but that's inferior to a javascript variable in both performance and portability.
If you have persuasive points that might expedite Firefox's progress on this, please post them at the bug report here. In the meantime, I'll be using css blobs for achieving self-contained, self-sufficient web components.
I have made a demo that can import without Service Worker (but service worker can cache and enhance the experience).
css-module-loader.js
const src = new URL(import.meta.url).searchParams.get('src')
const container = new CSSStyleSheet()
fetch(src)
.then(x => x.text())
.then(x => container.replace(x))
export default container
index.js
import article from './markdown-loader.js?src=./article.md'
import css from './css-module-loader.js?src=./style.css'
document.body.appendChild(document.createElement('div')).appendChild(article)
document.adoptedStyleSheets = [css]
This pattern works for all types of file that do not need a sync loading.
For async loading, you need top level await
or sync xhr
. For async compiling, only can be done by Service worker.
My demo at: https://github.com/Jack-Works/loader-with-esmodule-example
Supports Markdown module, CSS Module, JSON Module
Given the security issue raised by Apple, could a concept similar to Preload's as
attribute be a way out, so the import can be parsed accordingly?
import styles from "styles.css" as style;
Or alternatively more specific naming?
importCSS styles from "styles.css";
Given the security issue raised by Apple, could a concept similar to Preload's
as
attribute be a way out, so the import can be parsed accordingly?import styles from "styles.css" as style;
Or alternatively more specific naming?
importCSS styles from "styles.css";
That issue is being discussed over at this thread, and changes to the import syntax like those suggestions are one of the options being considered.
This thread seems to be getting pretty long. It's not quite clear where the proposal currently stands and what the best way to submit feedback is. E.g. is it more than a historical accident that this issue in in the webcomponents repo? Would non-webcomponents feedback be relevant here? Given the overlap with existing patterns in ecosystem code (for better or worse), it seems to me like this discussion may deserve a more prominent place.
@jkrems I opened it here because this is where we were also discussing HTML modules. I'm not sure how others feel about potentially forking the discussion vs finding a more prominent home, but I think at this point that this issue is well-known enough and referenced from other places (explainers, spec PRs, etc) that I'd be inclined to continue the discussion here.
And non-web-components related feedback is most definitely welcome - this proposal is for minimal semantics that have no real coupling with web components aside from constructible stylesheets.
@Rich-Harris , I wonder why you did not use push
, when you knew that you would fill the array asynchronously. You showed a race condition, but it was caused by a bug in the code. I can imagine other bugs caused by assigning into a variable.
Was you intention to prevent such bugs in the client code by a more limited interface? Did you have other intention?
Corrected code:
arr = ['a'];
function resolveAfter (value, ms) {
return new Promise(f => setTimeout(() => f(value), ms));
}
async function addB() {
arr.push(await resolveAfter('b', 100));
}
async function addC() {
arr.push(await resolveAfter('c', 50));
}
addB();
addC();
// later...
console.log(arr); // ['a', 'c', 'b']
support has landed in chrome: https://web.dev/css-module-scripts/
support has landed in chrome: https://web.dev/css-module-scripts/
This is beautiful
Closing as this feature is standardized and should have been closed as part of the HTML Standard change.
support has landed in chrome: https://web.dev/css-module-scripts/
Brillant, well done to all! This really helps make web components much more usable in the real world. Any idea if this would be possible to polyfill? Can't find any polyfills for it.
@mangelozzi Check out es-module-shims
to see if this works:
https://github.com/guybedford/es-module-shims#css-modules
In addition to HTML Modules, the ability to load CSS into a component definition is an important capability that we're currently lacking. Loading CSS is probably a more important use case judging by the popularity of CSS loaders in JavaScript bundlers.
Currently, styles are usually either defined inline with HTML templating or JSX or loaded with various JS Bundler CSS Loaders. The CSS loaders often have global side-effects like appending a
<style>
tag to the document, which does not generally work well with the style scoping of Shadow DOM.I propose that we add Cascading Style Sheet module scripts to the platform, allowing CSS to be imported directly by JavaScript:
Exports
The semantics for Cascading Style Sheet module scripts can be very simple, and combined with Constructable Stylesheets allow the importer to determine how the CSS should be applied to the document.
To start with, the only export of a Cascading Style Sheet module script would be a default export of the CSSStyleSheet object. This can then simply be added to
document.styles
orshadowRoot.styles
:Additional Features
Other userland CSS module systems often have more features, like the ability to import or export symbols that are defined in the module. ie:
These features may be very useful, but they can be considered for addition to the CSSOM itself so that they're exposed on CSSStyleSheet and available to both Cascading Style Sheet module scripts and styles loaded via
<style>
and<link>
tags, or constructed from a string.Polyfilling
It's not easy to polyfill a new module type, but build-time tools can create JavaScript modules that adhere to the Cascading Style Sheet module script interface.
Can be compiled to:
edit: updated to the actually Constructible StyleSheet API. edit: updated to refer to the feature by "Cascading Style Sheet module script"