* [Flight] Move from suspensey readRoot() to use(thenable)
* Update noop tests
These are no longer sync so they need some more significant updating.
Some of these tests are written in a non-idiomatic form too which is not
great.
* Update Relay tests
I kept these as sync for now and just assume a sync Promise.
* Updated the main tests
* Gate tests
* We need to cast through any because Thenable doesn't support unknown strings
* Move files
* Update paths
* Rename import variables
* Rename /server to /writer
This is mainly because "React Server Server" is weird so we need another
dimension.
* Use "react-server" convention to enforce that writer is only loaded in a server
* Basic scan of the file system to find Client modules
This does a rudimentary merge of the plugins. It still uses the global
scan and writes to file system.
Now the plugin accepts a search path or a list of referenced client files.
In prod, the best practice is to provide a list of files that are actually
referenced rather than including everything possibly reachable. Probably
in dev too since it's faster.
This is using the same convention as the upstream ContextModule - which
powers the require.context helpers.
* Add neo-async to dependencies
* Remove react/unstable_cache
We're probably going to make it available via the dispatcher. Let's remove this for now.
* Add readContext() to the dispatcher
On the server, it will be per-request.
On the client, there will be some way to shadow it.
For now, I provide it on the server, and throw on the client.
* Use readContext() from react-fetch
This makes it work on the server (but not on the client until we implement it there.)
Updated the test to use Server Components. Now it passes.
* Fixture: Add fetch from a Server Component
* readCache -> getCacheForType<T>
* Add React.unstable_getCacheForType
* Add a feature flag
* Fix Flow
* Add react-suspense-test-utils and port tests
* Remove extra Map lookup
* Unroll async/await because build system
* Add some error coverage and retry
* Add unstable_getCacheForType to Flight entry
* Rename "name"->"filepath" field on Webpack module references
This field name will get confused with the imported name or the module id.
* Switch back to transformSource instead of getSource
getSource would be more efficient in the cases where we don't need to read
the original file but we'll need to most of the time.
Even then, we can't return a JS file if we're trying to support non-JS
loader because it'll end up being transformed.
Similarly, we'll need to parse the file and we can't parse it before it's
transformed. So we need to chain with other loaders that know how.
* Add acorn dependency
This should be the version used by Webpack since we have a dependency on
Webpack anyway.
* Parse exported names of ESM modules
We need to statically resolve the names that a client component will
export so that we can export a module reference for each of the names.
For export * from, this gets tricky because we need to also load the
source of the next file to parse that. We don't know exactly how the
client is built so we guess it's somewhat default.
* Handle imported names one level deep in CommonJS using a Proxy
We use a proxy to see what property the server access and that will tell
us which property we'll want to import on the client.
* Add export name to module reference and Webpack map
To support named exports each name needs to be encoded as a separate
reference. It's possible with module splitting that different exports end
up in different chunks.
It's also possible that the export is renamed as part of minification.
So the map also includes a map from the original to the bundled name.
* Special case plain CJS requires and conditional imports using __esModule
This models if the server tries to import .default or a plain require.
We should replicate the same thing on the client when we load that
module reference.
* Dedupe acorn-related deps
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
This lets the Flight fixture run as "type": "module" or "commonjs".
Experimental loaders can be used similar to require.extensions to do the
transpilation and replacement of .client.js references.
* Expand fixture
Use .server convention. /server/index.js should really change too so it can be compiled but for now we treat it as bootstrapping code outside the compiled code.
Move App.server. It's part of the application code rather than the infra.
Add hybrid component used in both server/client and an extra component shared by multiple entry points.
* Use require.extensions to replace .client imports
The simplest server doesn't need AOT compilation. Instead we can just
configure require.extensions. This is probably not the best idea to use
in prod but is enough to show the set up.
* Rename Flight to Transport
Flight is still the codename for the implementation details (like Fiber).
However, now the public package is react-transport-... which is only
intended to be used directly by integrators.
* Rename names
Originally the idea was to hide all suspending behind getters or proxies.
However, this has some issues with perf on hot code like React elements.
It also makes it too easy to accidentally access it the first time in an
effect or callback where things aren't allowed to suspend. Making it
an explicit method call avoids this issue.
All other suspending has moved to explicit lazy blocks (and soon elements).
The only thing remaining is the root. We could require the root to be an
element or block but that creates an unfortunate indirection unnecessarily.
Instead, I expose a readRoot method on the response. Typically we try to
avoid virtual dispatch but in this case, it's meant that you build
abstractions on top of a Flight response so passing it a round is useful.
This replaces the HTML renderer with instead resolving host elements into
arrays tagged with the react.element symbol. These turn into proper
React Elements on the client.
The symbol is encoded as the magical value "$". This has security implications
so this special value needs to remain escaped for other strings.
We could just encode the element as {$$typeof: "$", key: key props: props}
but that's a lot more bytes. So instead I encode it as:
["$", key, props] and then convert it back.
It would be nicer if React's reconciler could just accept these tuples.
* Move Flight DOM to Webpack Specific Packagee
We'll have Webpack specific coupling so we need to ensure that it can be
versioned separately from various Webpack versions. We'll also have builds
for other bundlers in the future.
* Move to peerDep
* Move DOM Flight Tests
* Merge ReactFlightIntegration into ReactFlightDOM
This was an integration test. We can add to it.
* Fix fixture paths