rsnext/test/lib/react-channel-require-hook.js
Josh Story 7a5ef27b5e
Preload css (#48840)
This PR implements preloading of CSS from RSC.

1. The underlying Flight protocol was extended in
https://github.com/facebook/react/pull/26502 to allow sending hints from
RSC to SSR and Client runtimes. React was updated to include these
changes.
2. We now call `ReactDOM.preload()` for each stylesheet used in a
layout/page layer

There are a few implementation details to take note of
1. we were previously using the `.browser` variant of a few React
packages. This was a holdover from when there was just browser and node
and we wanted to use the browser variant b/c we wanted the same code to
work in edge/node runtimes. React now publishes a `.edge` variant which
is like `.browser` but expects to be server only. This is necessary to
get the opt-in for `AsyncLocalStorage`.
2. Even with the above change, AsyncLocalStorage was not patched on the
global scope until after React was loaded. I moved this into a module
which is loaded first
3. The component passed to RSC's `renderToReadableStream` is not
actually part of the RSC module graph. If I tried to call
`ReactDOM.preload()` inside that function or any other function defined
inside `app-render.tsx` file it would actually see the wrong instance of
`react-dom`. I added a new export on the RSC top level export which
exposes a `preloadStyle(...)` function which just delegates to
`ReactDOM.preload(...)`. This makes the preload run in the right module
graph


~There are a couple of bugs in React that this work uncovered that I
will upstream. We may want to delay merging until they are addressed.
I'll update this comment when that is complete.~
1. ~React, during SSR, can emit a preload for a style twice in some
circumstances because late discovered stylesheets don't consider whether
a preload has already been flushed when preparing to reveal a boundary
they are within~
2. ~React, during RSC updates on the client, can preload a style that is
already in the document because it currently only looks for existing
preload links and does not consider if there is a stylesheet link with
the same href.~

~both of these issues will not break functionality, they just make the
network tab look at bit more noisy. We would expect network deduping to
prevent multiple actual loads~

The above React bugs were fixed and included now in the React update in
this PR

---------

Co-authored-by: Shu Ding <g@shud.in>
2023-04-27 12:51:52 +02:00

24 lines
914 B
JavaScript

const mod = require('module')
const reactDir = 'react'
const reactDomDir = 'react-dom'
const hookPropertyMap = new Map([
['react', reactDir],
['react/package.json', `${reactDir}/package.json`],
['react/jsx-runtime', `${reactDir}/jsx-runtime`],
['react/jsx-dev-runtime', `${reactDir}/jsx-dev-runtime`],
['react-dom', `${reactDomDir}`],
['react-dom/package.json', `${reactDomDir}/package.json`],
['react-dom/client', `${reactDomDir}/client`],
['react-dom/server', `${reactDomDir}/server`],
['react-dom/server.browser', `${reactDomDir}/server.browser`],
['react-dom/server.edge', `${reactDomDir}/server.edge`],
])
const resolveFilename = mod._resolveFilename
mod._resolveFilename = function (request, parent, isMain, options) {
const hookResolved = hookPropertyMap.get(request)
if (hookResolved) request = hookResolved
return resolveFilename.call(mod, request, parent, isMain, options)
}