-
-
Notifications
You must be signed in to change notification settings - Fork 168
Description
Moved from hi-ogawa/vite-plugins#969
I just saw redwoodjs/sdk#625, which implements client reference css by switching <link>
(prod) and <style>
(dev). For server component css, we can probably do the same (i.e. switch to inline <style>
) since we collect css in rsc environment module graph and manually inject <link>
elements:
vite-plugin-react/packages/plugin-rsc/src/plugin.ts
Lines 1969 to 1974 in 9b2741f
React.createElement('link', { | |
key: 'css:' + href, | |
rel: 'stylesheet', | |
precedence: 'vite-rsc/importer-resources', | |
href: href, | |
}), |
However as wrote in hi-ogawa/vite-plugins#969 (comment), it might be difficult for client reference css since we currently rely on ReactDOM.preinitStyle
, which only supports <link>
injection. To replace this with inline <style>
, we would either
- new react API to hoist up inline
<style>
during ssr - inject
<style>
element via proxy getter (similar to Parcel's module proxy) - avoid client reference preload level injection and switch to
rscCssTransform
like injection
Also we also should solve potential FOUC of lazy component css
For this we might need to switch to rscCssTransform
based approach for client reference css anyways.
Also not sure how we can pass around nonce for inline style. We might need dedicated async local storage internally?
Also we might not have to worry about this at all by accepting temporary duplicate css, but just remove <link>
as early as possible when corresponding <style>
is injected on client, namely dealing with this TODO:
vite-plugin-react/packages/plugin-rsc/src/plugin.ts
Lines 834 to 844 in 9b2741f
// TODO: this doesn't have to wait for "vite:beforeUpdate" and should do it right after browser css import. | |
code += /* js */ ` | |
const ssrCss = document.querySelectorAll("link[rel='stylesheet']"); | |
import.meta.hot.on("vite:beforeUpdate", () => { | |
ssrCss.forEach(node => { | |
if (node.dataset.precedence?.startsWith("vite-rsc/")) { | |
node.remove(); | |
} | |
}); | |
}); | |
` |
Can this be achieved somehow by mutation observer? or some (new) API for import.meta.hot
event?
Oh, but one thing to worry about is that, after <link>
is manually removed, I've always wondered why React doesn't add them back again after seeing new RSC payload including the same <link>
tags. If they start to do at some point, then manual removal doesn't help (though maybe the same can be said for inline <style>
).