Commit Graph

28 Commits

Author SHA1 Message Date
Josh Story
701ac2e572 [Flight][Float] Preinitialize module imports during SSR (#27314)
Currently when we SSR a Flight response we do not emit any resources for
module imports. This means that when the client hydrates it won't have
already loaded the necessary scripts to satisfy the Imports defined in
the Flight payload which will lead to a delay in hydration completing.

This change updates `react-server-dom-webpack` and
`react-server-dom-esm` to emit async script tags in the head when we
encounter a modules in the flight response.

To support this we need some additional server configuration. We need to
know the path prefix for chunk loading and whether the chunks will load
with CORS or not (and if so with what configuration).
2023-09-27 09:53:31 -07:00
Sebastian Markbåge
da6c23a45c [Flight] Fallback to importing the whole module instead of encoding every name (#26624)
We currently don't just "require" a module by its module id/path. We
encode the pair of module id/path AND its export name. That's because
with module splitting, a single original module can end up in two or
more separate modules by name. Therefore the manifest files need to
encode how to require the whole module as well as how to require each
export name.

In practice, we don't currently use this because we end up forcing
Webpack to deopt and keep it together as a single module, and we don't
even have the code in the Webpack plugin to write separate values for
each export name.

The problem is with CJS we don't statically know what all the export
names will be. Since these cases will never be module split, we don't
really need to know.

This changes the Flight requires to first look for the specific name
we're loading and then if that name doesn't exist in the manifest we
fallback to looking for the `"*"` name containing the entire module and
look for the name in there at runtime.

We could probably optimize this a bit if we assume that CJS modules on
the server never get built with a name. That way we don't have to do the
failed lookup.

Additionally, since we've recently merged filepath + name into a single
string instead of two values, we now have to split those back out by
parsing the string. This is especially unfortunate for server references
since those should really not reveal what they are but be a hash or
something. The solution might just be to split them back out into two
separate fields again.

cc @shuding
2023-04-14 21:09:09 -04:00
dan
1308e49a69 [Flight Plugin] Scan for "use client" (#26474)
## Summary

Our toy webpack plugin for Server Components is pretty broken right now
because, now that `.client.js` convention is gone, it ends up adding
every single JS file it can find (including `node_modules`) as a
potential async dependency. Instead, it should only look for files with
the `'use client'` directive.

The ideal way is to implement this by bundling the RSC graph first.
Then, we would know which `'use client'` files were actually discovered
— and so there would be no point to scanning the disk for them. That's
how Next.js bundler does it.

We're not doing that here.

This toy plugin is very simple, and I'm not planning to do heavy
lifting. I'm just bringing it up to date with the convention. The change
is that we now read every file we discover (alas), bail if it has no
`'use client'`, and parse it if it does (to verify it's actually used as
a directive). I've changed to use `acorn-loose` because it's forgiving
of JSX (and likely TypeScript/Flow). Otherwise, this wouldn't work on
uncompiled source.

## Test plan

Verified I can get our initial Server Components Demo running after this
change. Previously, it would get stuck compiling and then emit thousands
of errors.

Also confirmed the fixture still works. (It doesn’t work correctly on
the first load after dev server starts, but that’s already the case on
main so seems unrelated.)
2023-03-30 22:05:03 +01:00
Sebastian Markbåge
e0241b6600 Simplify Webpack References by encoding file path + export name as single id (#26300)
We always look up these references in a map so it doesn't matter what
their value is. It could be a hash for example.

The loaders now encode a single $$id instead of filepath + name.

This changes the react-client-manifest to have a single level. The value
inside the map is still split into module id + export name because
that's what gets looked up in webpack.

The react-ssr-manifest is still two levels because that's a reverse
lookup.
2023-03-04 19:51:34 -05:00
Sebastian Markbåge
67a61d5bd7 [Flight Fixture] Show SSR Support with CSS (#26263)
Builds on #26257.

To do this we need access to a manifest for which scripts and CSS are
used for each "page" (entrypoint).

The initial script to bootstrap the app is inserted with
`bootstrapScripts`. Subsequent content are loaded using the chunks
mechanism built-in.

The stylesheets for each pages are prepended to each RSC payload and
rendered using Float. This doesn't yet support styles imported in
components that are also SSR:ed nor imported through Server Components.
That's more complex and not implemented in the node loader.

HMR doesn't work after reloads right now because the SSR renderer isn't
hot reloaded because there's no idiomatic way to hot reload ESM modules
in Node.js yet. Without killing the HMR server. This leads to hydration
mismatches when reloading the page after a hot reload.

Notably this doesn't show serializing the stream through the HTML like
real implementations do. This will lead to possible hydration mismatches
based on the data. However, manually serializing the stream as a string
isn't exactly correct due to binary data. It's not the idiomatic way
this is supposed to work. This will all be built-in which will make this
automatic in the future.
2023-02-28 19:44:37 -05:00
Sebastian Markbåge
60144a04da Split out Edge and Node implementations of the Flight Client (#26187)
This splits out the Edge and Node implementations of Flight Client into
their own implementations. The Node implementation now takes a Node
Stream as input.

I removed the bundler config from the Browser variant because you're
never supposed to use that in the browser since it's only for SSR.
Similarly, it's required on the server. This also enables generating a
SSR manifest from the Webpack plugin. This is necessary for SSR so that
you can reverse look up what a client module is called on the server.

I also removed the option to pass a callServer from the server. We might
want to add it back in the future but basically, we don't recommend
calling Server Functions from render for initial render because if that
happened client-side it would be a client-side waterfall. If it's never
called in initial render, then it also shouldn't ever happen during SSR.
This might be considered too restrictive.

~This also compiles the unbundled packages as ESM. This isn't strictly
necessary because we only need access to dynamic import to load the
modules but we don't have any other build options that leave
`import(...)` intact, and seems appropriate that this would also be an
ESM module.~ Went with `import(...)` in CJS instead.
2023-02-21 13:18:24 -05:00
Sebastian Markbåge
189f70e17b Create a bunch of custom webpack vs unbundled node bundles (#26172)
We currently have an awkward set up because the server can be used in
two ways. Either you can have the server code prebundled using Webpack
(what Next.js does in practice) or you can use an unbundled Node.js
server (what the reference implementation does).

The `/client` part of RSC is actually also available on the server when
it's used as a consumer for SSR. This should also be specialized
depending on if that server is Node or Edge and if it's bundled or
unbundled.

Currently we still assume Edge will always be bundled since we don't
have an interceptor for modules there.

I don't think we'll want to support this many combinations of setups for
every bundler but this might be ok for the reference implementation.

This PR doesn't actually change anything yet. It just updates the
plumbing and the entry points that are built and exposed. In follow ups
I'll fork the implementation and add more features.

---------

Co-authored-by: dan <dan.abramov@me.com>
2023-02-16 11:01:52 -05:00
Sebastian Markbåge
f0cf832e1d Update Flight Fixture to "use client" instead of .client.js (#26118)
This updates the Flight fixture to support the new ESM loaders in newer
versions of Node.js.

It also uses native fetch since react-fetch is gone now. (This part
requires Node 18 to run the fixture.)

I also updated everything to use the `"use client"` convention instead
of file name based convention.

The biggest hack here is that the Webpack plugin now just writes every
`.js` file in the manifest. This needs to be more scoped. In practice,
this new convention effectively requires you to traverse the server
graph first to find the actual used files. This is enough to at least
run our own fixture though.

I didn't update the "blocks" fixture.

More details in each commit message.
2023-02-07 12:09:29 -05:00
Jan Kassens
6b30832666 Upgrade prettier (#26081)
The old version of prettier we were using didn't support the Flow syntax
to access properties in a type using `SomeType['prop']`. This updates
`prettier` and `rollup-plugin-prettier` to the latest versions.

I added the prettier config `arrowParens: "avoid"` to reduce the diff
size as the default has changed in Prettier 2.0. The largest amount of
changes comes from function expressions now having a space. This doesn't
have an option to preserve the old behavior, so we have to update this.
2023-01-31 08:25:05 -05:00
Jan Kassens
e2424f33b3 [flow] enable exact_empty_objects (#25973)
This enables the "exact_empty_objects" setting for Flow which makes
empty objects exact instead of building up the type as properties are
added in code below. This is in preparation to Flow 191 which makes this
the default and removes the config.

More about the change in the Flow blog
[here](https://medium.com/flow-type/improved-handling-of-the-empty-object-in-flow-ead91887e40c).
2023-01-09 17:00:36 -05:00
Jan Kassens
0b4f443020 [flow] enable enforce_local_inference_annotations (#25921)
This setting is an incremental path to the next Flow version enforcing
type annotations on most functions (except some inline callbacks).

Used
```
node_modules/.bin/flow codemod annotate-functions-and-classes --write .
```
to add a majority of the types with some hand cleanup when for large
inferred objects that should just be `Fiber` or weird constructs
including `any`.

Suppressed the remaining issues.

Builds on #25918
2023-01-09 15:46:48 -05:00
Leo Lamprecht
996b00b787 [Tiny] Fixed incorrect import in react-server-dom-webpack (#25554)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn debug-test --watch TestName`, open
`chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

In https://github.com/facebook/react/pull/25504,
`react-server-dom-webpack/` was deprecated in favor of
`react-server-dom-webpack/client`, but a remaining import wasn't
adjusted accordingly.

As a result, the remaining conditions within the file are no longer
firing appropriately, which I ran into while playing around with a fork
of
[server-components-demo](https://github.com/reactjs/server-components-demo).

The `index.js` file now contains a
[placeholder](https://github.com/facebook/react/blob/main/packages/react-server-dom-webpack/index.js)
and the actual logic of the client now sits in `/client`.

## How did you test this change?

I replaced `require.resolve('../')` with `require.resolve('../client')`
in the `react-server-dom-webpack` package in `node_modules` and
confirmed that the output of the build looked good again.
2022-10-24 10:40:18 -07:00
Andrew Clark
9cdf8a99ed [Codemod] Update copyright header to Meta (#25315)
* Facebook -> Meta in copyright

rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g'

* Manual tweaks
2022-10-18 11:19:24 -04:00
Sebastian Markbåge
3bb71dfd4b Rename react-server-dom-webpack entry points to /client and /server (#25504) 2022-10-18 10:15:52 -04:00
Jan Kassens
3b6826ed9e Flow: inference_mode=constrain_writes
This mode is going to be the new default in Flow going forward.
There was an unfortuante large number of suppressions in this update.

More on the changes can be found in this [Flow blog post](https://medium.com/flow-type/new-flow-language-rule-constrained-writes-4c70e375d190).

Added some of the required annotations using the provided codemod:

```sh
node_modules/.bin/flow codemod annotate-declarations --write .
```

ghstack-source-id: 0b168e1b23
Pull Request resolved: https://github.com/facebook/react/pull/25422
2022-10-04 15:49:48 -04:00
Jan Kassens
9f8a98a390 Flow upgrade to 0.153
- method unbinding is no longer supported in Flow for soundness, this added a bunch of suppressions
- Flow now prevents objects to be supertypes of interfaces/classes

ghstack-source-id: d7749cbad8
Pull Request resolved: https://github.com/facebook/react/pull/25412
2022-10-04 11:30:06 -04:00
Jan Kassens
64fe791be8 Flow upgrade to 0.146
This upgrade made more expressions invalidate refinements. In some
places this lead to a large number of suppressions that I automatically
suppressed and should be followed up on when the code is touched.
I think most of them might require either manual annotations or moving
a value into a const to allow refinement.

ghstack-source-id: a45b40abf0
Pull Request resolved: https://github.com/facebook/react/pull/25410
2022-10-04 11:01:50 -04:00
Jan Kassens
346c7d4c43 straightford explicit types (#25253) 2022-09-13 17:57:38 -04:00
Jan Kassens
ba7b6f4183 Flow: upgrade to 0.132 (#25244) 2022-09-12 14:36:02 -04:00
Jan Kassens
8003ab9cf5 Flow: remove explicit object syntax (#25223) 2022-09-09 16:03:48 -04:00
Jan Kassens
8a9e7b6cef Flow: implicit-inexact-object=error (#25210)
* implicit-inexact-object=error
* default everything ambiguous to exact object
* inexact where exact causes errors
2022-09-09 10:13:58 -04:00
Jan Kassens
a473d08fce Update to Flow from 0.97 to 0.122 (#25204)
* flow 0.122
* update ReactModel type
2022-09-08 11:46:07 -04:00
Michelle Chen
0cc724c777 update ReactFlightWebpackPlugin to be compatiable with webpack v5 (#22739) 2021-11-25 22:43:22 +00:00
Sebastian Markbåge
172e89b4bf Reland Remove redundant initial of isArray (#21188)
* Remove redundant initial of isArray (#21163)

* Reapply prettier

* Type the isArray function with refinement support

This ensures that an argument gets refined just like it does if isArray is
used directly.

I'm not sure how to express with just a direct reference so I added a
function wrapper and confirmed that this does get inlined properly by
closure compiler.

* A few more

* Rename unit test to internal

This is not testing a bundle.

Co-authored-by: Behnam Mohammadi <itten@live.com>
2021-04-07 07:57:43 -07:00
Dan Abramov
070372cde2 [Flight] Fix webpack watch mode issue (#20457) 2020-12-14 15:50:20 +00:00
Dan Abramov
0f80dd1484 [Flight] Support concatenated modules in Webpack plugin (#20449)
* Extract recordModule

* Add support for concatenated modules
2020-12-13 17:44:59 +00:00
Dan Abramov
94aa365e3a [Flight] Fix webpack plugin to use chunk groups (#20421) 2020-12-10 03:03:53 +00:00
Sebastian Markbåge
5fd9db732d [Flight] Rename react-transport-... packages to react-server-... (#20403)
* 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
2020-12-08 08:08:57 -05:00