react icon indicating copy to clipboard operation
react copied to clipboard

Vite plugin for React Server Components

Open frandiox opened this issue 3 years ago • 17 comments
trafficstars

Summary

Hi! This PR implements a Vite plugin for React Server Components. This is the approach we are currently exploring at @shopify/hydrogen and is extracted from here. Hydrogen is right now using a custom implementation of RSC but we would like to switch to the official implementation as soon as possible and make it work with SSR. This PR is meant to serve as a discussion to see what would be the best approach and some trade-offs.

Assumptions and constraints

As far as I understand, React 18 experimental supports server components by importing a "module reference" instead of actual client components in a Node process. This is done by using Node's native --conditions and registers/loaders. However, in order to do SSR we need the "real" client components in the process, not these module references. Therefore, it sounds like these two features are right now mutually exclusive unless we create 2 bundles or 2 different Node environments.

On the other hand, Vite typically runs on only 1 process and its philosophy is basically no-bundles in development to speed things up. Plus, the main build target for Hydrogen is Oxygen and Cloudflare Workers, which can't be run as 2 processes and don't have Node's native --conditions or registers.

Proposed approach

Instead of relying on Node flags or registers, the Vite plugin in this PR is wrapping every client component in a proxy that merges the component itself with its module reference in the same object. The React SSR renderer will treat this resulting object as a normal component whereas the RSC renderer will use it as a module reference. This way, it can run RSC and SSR in the same process without requiring multiple bundles or Node flags.

Implementation details and clarifications

  • ~~The ClientProxy is basically wrapping components in ForwardRefs. The only reason to do this is so that the whole thing evaluates to typeof component === 'object' (instead of 'function') in order to reach this line in the RSC renderer. This could be simplified if we are willing to change the attemptResolveElement logic a bit. Also, this proxy could be removed if we only want to support RSC=>SSR (consuming RSC response in the server, then triggering SSR with that). It is needed, however, if we want to support running pure SSR without a prior RSC pass.~~
  • This does not use any manifest or "bundler config" because it relies on Vite's glob imports. These imports are injected around the __INJECTED_CLIENT_IMPORTERS__ object. Vite automatically adds a list of sub-dependencies to each of the client components so, when downloading a component during hydration, it gets all the sub-dependencies together to avoid waterfall requests.

Apart from implementation details that can be fixed or improved, would this be a valid approach in your opinion? Any other ideas that work with the constraints mentioned above?

There's a demo project using this implementation here (only RSC, not SSR): GitHub source | Stackblitz live demo

frandiox avatar Dec 14 '21 05:12 frandiox

Comparing: 1e5245df89e45b788acf3af3769f0d816b18458d...e03c8ccbdface50a648f9954a35fcfb25893d286

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 134.28 kB 134.28 kB = 42.94 kB 42.94 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 140.35 kB 140.35 kB = 44.74 kB 44.74 kB
facebook-www/ReactDOM-prod.classic.js = 474.44 kB 474.44 kB = 84.88 kB 84.88 kB
facebook-www/ReactDOM-prod.modern.js = 459.68 kB 459.68 kB = 82.62 kB 82.63 kB
facebook-www/ReactDOMForked-prod.classic.js = 474.44 kB 474.44 kB = 84.88 kB 84.88 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.62 kB +∞% 0.00 kB 7.02 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 66.27 kB +∞% 0.00 kB 17.21 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.58 kB +∞% 0.00 kB 6.57 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +∞% 0.00 kB 67.67 kB +∞% 0.00 kB 17.30 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +∞% 0.00 kB 18.00 kB +∞% 0.00 kB 6.65 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite.development.js +∞% 0.00 kB 16.37 kB +∞% 0.00 kB 4.85 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.13 kB +∞% 0.00 kB 1.88 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +∞% 0.00 kB 2.99 kB +∞% 0.00 kB 1.25 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.63 kB +∞% 0.00 kB 7.03 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +∞% 0.00 kB 66.18 kB +∞% 0.00 kB 17.16 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +∞% 0.00 kB 67.59 kB +∞% 0.00 kB 17.25 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite.js +∞% 0.00 kB 16.25 kB +∞% 0.00 kB 4.80 kB
oss-experimental/react-server-dom-vite/index.js +∞% 0.00 kB 0.22 kB +∞% 0.00 kB 0.16 kB
oss-experimental/react-server-dom-vite/plugin.js +∞% 0.00 kB 0.08 kB +∞% 0.00 kB 0.10 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 69.67 kB +∞% 0.00 kB 17.44 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.76 kB +∞% 0.00 kB 6.60 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite.development.js +∞% 0.00 kB 17.61 kB +∞% 0.00 kB 4.97 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.35 kB +∞% 0.00 kB 1.97 kB
oss-experimental/react-server-dom-vite/writer.browser.server.js +∞% 0.00 kB 0.27 kB +∞% 0.00 kB 0.17 kB
oss-experimental/react-server-dom-vite/writer.node.server.js +∞% 0.00 kB 0.26 kB +∞% 0.00 kB 0.17 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.62 kB +∞% 0.00 kB 7.02 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 66.21 kB +∞% 0.00 kB 17.19 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.53 kB +∞% 0.00 kB 6.55 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +∞% 0.00 kB 67.62 kB +∞% 0.00 kB 17.28 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +∞% 0.00 kB 17.95 kB +∞% 0.00 kB 6.63 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite.development.js +∞% 0.00 kB 16.37 kB +∞% 0.00 kB 4.85 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.13 kB +∞% 0.00 kB 1.88 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +∞% 0.00 kB 2.99 kB +∞% 0.00 kB 1.25 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.63 kB +∞% 0.00 kB 7.03 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +∞% 0.00 kB 66.13 kB +∞% 0.00 kB 17.14 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +∞% 0.00 kB 67.53 kB +∞% 0.00 kB 17.24 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite.js +∞% 0.00 kB 16.25 kB +∞% 0.00 kB 4.80 kB
oss-stable-semver/react-server-dom-vite/index.js +∞% 0.00 kB 0.22 kB +∞% 0.00 kB 0.16 kB
oss-stable-semver/react-server-dom-vite/plugin.js +∞% 0.00 kB 0.08 kB +∞% 0.00 kB 0.10 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 69.61 kB +∞% 0.00 kB 17.42 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.72 kB +∞% 0.00 kB 6.58 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite.development.js +∞% 0.00 kB 17.61 kB +∞% 0.00 kB 4.97 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.35 kB +∞% 0.00 kB 1.97 kB
oss-stable-semver/react-server-dom-vite/writer.browser.server.js +∞% 0.00 kB 0.27 kB +∞% 0.00 kB 0.17 kB
oss-stable-semver/react-server-dom-vite/writer.node.server.js +∞% 0.00 kB 0.26 kB +∞% 0.00 kB 0.17 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.62 kB +∞% 0.00 kB 7.02 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 66.21 kB +∞% 0.00 kB 17.19 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.53 kB +∞% 0.00 kB 6.55 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +∞% 0.00 kB 67.62 kB +∞% 0.00 kB 17.28 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +∞% 0.00 kB 17.95 kB +∞% 0.00 kB 6.63 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite.development.js +∞% 0.00 kB 16.37 kB +∞% 0.00 kB 4.85 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.13 kB +∞% 0.00 kB 1.88 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +∞% 0.00 kB 2.99 kB +∞% 0.00 kB 1.25 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.63 kB +∞% 0.00 kB 7.03 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +∞% 0.00 kB 66.13 kB +∞% 0.00 kB 17.14 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +∞% 0.00 kB 67.53 kB +∞% 0.00 kB 17.24 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite.js +∞% 0.00 kB 16.25 kB +∞% 0.00 kB 4.80 kB
oss-stable/react-server-dom-vite/index.js +∞% 0.00 kB 0.22 kB +∞% 0.00 kB 0.16 kB
oss-stable/react-server-dom-vite/plugin.js +∞% 0.00 kB 0.08 kB +∞% 0.00 kB 0.10 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 69.61 kB +∞% 0.00 kB 17.42 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.72 kB +∞% 0.00 kB 6.58 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite.development.js +∞% 0.00 kB 17.61 kB +∞% 0.00 kB 4.97 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.35 kB +∞% 0.00 kB 1.97 kB
oss-stable/react-server-dom-vite/writer.browser.server.js +∞% 0.00 kB 0.27 kB +∞% 0.00 kB 0.17 kB
oss-stable/react-server-dom-vite/writer.node.server.js +∞% 0.00 kB 0.26 kB +∞% 0.00 kB 0.17 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.62 kB +∞% 0.00 kB 7.02 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 66.27 kB +∞% 0.00 kB 17.21 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.58 kB +∞% 0.00 kB 6.57 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +∞% 0.00 kB 67.67 kB +∞% 0.00 kB 17.30 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +∞% 0.00 kB 18.00 kB +∞% 0.00 kB 6.65 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite.development.js +∞% 0.00 kB 16.37 kB +∞% 0.00 kB 4.85 kB
oss-experimental/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.13 kB +∞% 0.00 kB 1.88 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +∞% 0.00 kB 2.99 kB +∞% 0.00 kB 1.25 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.63 kB +∞% 0.00 kB 7.03 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +∞% 0.00 kB 66.18 kB +∞% 0.00 kB 17.16 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +∞% 0.00 kB 67.59 kB +∞% 0.00 kB 17.25 kB
oss-experimental/react-server-dom-vite/esm/react-server-dom-vite.js +∞% 0.00 kB 16.25 kB +∞% 0.00 kB 4.80 kB
oss-experimental/react-server-dom-vite/index.js +∞% 0.00 kB 0.22 kB +∞% 0.00 kB 0.16 kB
oss-experimental/react-server-dom-vite/plugin.js +∞% 0.00 kB 0.08 kB +∞% 0.00 kB 0.10 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 69.67 kB +∞% 0.00 kB 17.44 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.76 kB +∞% 0.00 kB 6.60 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite.development.js +∞% 0.00 kB 17.61 kB +∞% 0.00 kB 4.97 kB
oss-experimental/react-server-dom-vite/umd/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.35 kB +∞% 0.00 kB 1.97 kB
oss-experimental/react-server-dom-vite/writer.browser.server.js +∞% 0.00 kB 0.27 kB +∞% 0.00 kB 0.17 kB
oss-experimental/react-server-dom-vite/writer.node.server.js +∞% 0.00 kB 0.26 kB +∞% 0.00 kB 0.17 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.62 kB +∞% 0.00 kB 7.02 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 66.21 kB +∞% 0.00 kB 17.19 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.53 kB +∞% 0.00 kB 6.55 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +∞% 0.00 kB 67.62 kB +∞% 0.00 kB 17.28 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +∞% 0.00 kB 17.95 kB +∞% 0.00 kB 6.63 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite.development.js +∞% 0.00 kB 16.37 kB +∞% 0.00 kB 4.85 kB
oss-stable-semver/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.13 kB +∞% 0.00 kB 1.88 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +∞% 0.00 kB 2.99 kB +∞% 0.00 kB 1.25 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.63 kB +∞% 0.00 kB 7.03 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +∞% 0.00 kB 66.13 kB +∞% 0.00 kB 17.14 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +∞% 0.00 kB 67.53 kB +∞% 0.00 kB 17.24 kB
oss-stable-semver/react-server-dom-vite/esm/react-server-dom-vite.js +∞% 0.00 kB 16.25 kB +∞% 0.00 kB 4.80 kB
oss-stable-semver/react-server-dom-vite/index.js +∞% 0.00 kB 0.22 kB +∞% 0.00 kB 0.16 kB
oss-stable-semver/react-server-dom-vite/plugin.js +∞% 0.00 kB 0.08 kB +∞% 0.00 kB 0.10 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 69.61 kB +∞% 0.00 kB 17.42 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.72 kB +∞% 0.00 kB 6.58 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite.development.js +∞% 0.00 kB 17.61 kB +∞% 0.00 kB 4.97 kB
oss-stable-semver/react-server-dom-vite/umd/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.35 kB +∞% 0.00 kB 1.97 kB
oss-stable-semver/react-server-dom-vite/writer.browser.server.js +∞% 0.00 kB 0.27 kB +∞% 0.00 kB 0.17 kB
oss-stable-semver/react-server-dom-vite/writer.node.server.js +∞% 0.00 kB 0.26 kB +∞% 0.00 kB 0.17 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.62 kB +∞% 0.00 kB 7.02 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 66.21 kB +∞% 0.00 kB 17.19 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.53 kB +∞% 0.00 kB 6.55 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +∞% 0.00 kB 67.62 kB +∞% 0.00 kB 17.28 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +∞% 0.00 kB 17.95 kB +∞% 0.00 kB 6.63 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite.development.js +∞% 0.00 kB 16.37 kB +∞% 0.00 kB 4.85 kB
oss-stable/react-server-dom-vite/cjs/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.13 kB +∞% 0.00 kB 1.88 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js +∞% 0.00 kB 2.99 kB +∞% 0.00 kB 1.25 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +∞% 0.00 kB 21.63 kB +∞% 0.00 kB 7.03 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +∞% 0.00 kB 66.13 kB +∞% 0.00 kB 17.14 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +∞% 0.00 kB 67.53 kB +∞% 0.00 kB 17.24 kB
oss-stable/react-server-dom-vite/esm/react-server-dom-vite.js +∞% 0.00 kB 16.25 kB +∞% 0.00 kB 4.80 kB
oss-stable/react-server-dom-vite/index.js +∞% 0.00 kB 0.22 kB +∞% 0.00 kB 0.16 kB
oss-stable/react-server-dom-vite/plugin.js +∞% 0.00 kB 0.08 kB +∞% 0.00 kB 0.10 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.development.server.js +∞% 0.00 kB 69.61 kB +∞% 0.00 kB 17.42 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite-writer.browser.production.min.server.js +∞% 0.00 kB 17.72 kB +∞% 0.00 kB 6.58 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite.development.js +∞% 0.00 kB 17.61 kB +∞% 0.00 kB 4.97 kB
oss-stable/react-server-dom-vite/umd/react-server-dom-vite.production.min.js +∞% 0.00 kB 4.35 kB +∞% 0.00 kB 1.97 kB
oss-stable/react-server-dom-vite/writer.browser.server.js +∞% 0.00 kB 0.27 kB +∞% 0.00 kB 0.17 kB
oss-stable/react-server-dom-vite/writer.node.server.js +∞% 0.00 kB 0.26 kB +∞% 0.00 kB 0.17 kB
facebook-relay/flight/ReactFlightNativeRelayServer-prod.js +0.65% 22.03 kB 22.17 kB +0.18% 5.48 kB 5.49 kB
facebook-www/ReactFlightDOMRelayServer-prod.classic.js +0.51% 27.84 kB 27.98 kB +0.15% 7.34 kB 7.35 kB
facebook-www/ReactFlightDOMRelayServer-prod.modern.js +0.51% 27.91 kB 28.06 kB +0.14% 7.37 kB 7.38 kB
facebook-relay/flight/ReactFlightNativeRelayServer-dev.js +0.50% 40.00 kB 40.20 kB +0.15% 10.28 kB 10.30 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +0.49% 41.09 kB 41.29 kB +0.08% 10.47 kB 10.48 kB
oss-stable-semver/react-server/cjs/react-server-flight.development.js +0.49% 41.09 kB 41.29 kB +0.08% 10.47 kB 10.48 kB
oss-stable/react-server/cjs/react-server-flight.development.js +0.49% 41.09 kB 41.29 kB +0.08% 10.47 kB 10.48 kB
facebook-www/ReactFlightDOMRelayServer-dev.classic.js +0.37% 54.70 kB 54.90 kB +0.09% 14.00 kB 14.01 kB
facebook-www/ReactFlightDOMRelayServer-dev.modern.js +0.37% 54.76 kB 54.96 kB +0.06% 14.02 kB 14.02 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.development.server.js +0.31% 65.28 kB 65.48 kB +0.07% 16.92 kB 16.93 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.development.server.js +0.31% 65.28 kB 65.48 kB +0.07% 16.92 kB 16.93 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.development.server.js +0.31% 65.33 kB 65.53 kB +0.06% 16.94 kB 16.95 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.development.server.js +0.30% 68.63 kB 68.84 kB +0.06% 17.15 kB 17.16 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.development.server.js +0.30% 68.63 kB 68.84 kB +0.06% 17.15 kB 17.16 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.development.server.js +0.30% 66.68 kB 66.88 kB +0.08% 17.01 kB 17.03 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.development.server.js +0.30% 66.68 kB 66.88 kB +0.08% 17.01 kB 17.03 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.development.server.js +0.30% 68.69 kB 68.90 kB +0.06% 17.17 kB 17.18 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.development.server.js +0.30% 66.74 kB 66.94 kB +0.07% 17.03 kB 17.04 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.production.min.server.js +0.22% 17.11 kB 17.15 kB +0.09% 6.40 kB 6.41 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.production.min.server.js +0.22% 17.11 kB 17.15 kB +0.09% 6.40 kB 6.41 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.production.min.server.js +0.22% 17.16 kB 17.19 kB +0.11% 6.42 kB 6.43 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.production.min.server.js +0.21% 17.30 kB 17.33 kB +0.14% 6.44 kB 6.44 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.production.min.server.js +0.21% 17.30 kB 17.33 kB +0.14% 6.44 kB 6.44 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.production.min.server.js +0.21% 17.34 kB 17.38 kB +0.17% 6.46 kB 6.47 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.production.min.server.js +0.21% 17.53 kB 17.57 kB +0.09% 6.49 kB 6.49 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.production.min.server.js +0.21% 17.53 kB 17.57 kB +0.09% 6.49 kB 6.49 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.production.min.server.js +0.21% 17.58 kB 17.61 kB +0.09% 6.51 kB 6.52 kB

Generated by :no_entry_sign: dangerJS against e03c8ccbdface50a648f9954a35fcfb25893d286

sizebot avatar Dec 14 '21 05:12 sizebot

Hi @frandiox!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

facebook-github-bot avatar Dec 14 '21 06:12 facebook-github-bot

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

facebook-github-bot avatar Dec 16 '21 15:12 facebook-github-bot

@acdlite Hi! Would it be possible to get some feedback here now that all checks are passing? Or who should I ask?

I've updated this PR since the last time we talked with some extra features and fixes. If there's no one in the team that is familiar with Vite, I'm available (JST) for a call if you want to ask questions directly.

We are using a built version of this plugin in Hydrogen, you can see an example here deployed to CFW (using RSC + SSR).

frandiox avatar Feb 02 '22 08:02 frandiox

the main build target for Hydrogen is Oxygen and Cloudflare Workers, which can't be run as 2 processes

For cloudflare workers, you don't have to run two workers. You can run two bundles in the same worker if you want.

Vite typically runs on only 1 process and its philosophy is basically no-bundles in development to speed things up.

For development, you're going to run a separate server environment to run the server components in anyway. So you can configure that environment differently without bundling it, right?

sebmarkbage avatar Feb 26 '22 02:02 sebmarkbage

@sebmarkbage Thanks for the feedback and the updates in the RFC. I'm replying here instead to avoid polluting the RFC with implementation details for the Vite plugin. I'm trying to get this PR working with your latest feedback but I'd like to confirm something (the updates are in the last 3 commits).

In the world where you compile proxies instead of module references, the Proxies should cover all named exports. They work like their underlying object/function when used outside of a Server Components render function. When accessed inside a Server Component function while rendering you can't access their properties and if called (if it proxies a function) it errors.

This means we need to detect if the current rendering is RSC or not, right? What would be a good mechanism to detect that? I'm testing with useState in https://github.com/facebook/react/pull/22952/commits/615449e07cc7f599fe8bac73c2ac6b00a5ac494e but I wonder if there's a better way to check it.

If the thing being Proxied is a string it can't be wrapped in a Proxy. Instead, the raw string is returned. If it's a short string, it ends there. If it's a long string, it can be added to a global Map. If Server Components runtime sees one of the strings in that map, it instead serializes a module reference.

So far, I was trying to avoid changes in the Flight runtime itself. However, in order to support this global string map we need to teach Flight how to get the module reference. Instead of adding a global map to the main Flight runtime code, I think it's better to push that to each bundler config implementation. For that, I've added this change https://github.com/facebook/react/pull/22952/commits/5404a5f06514da975a0b5fc55a36d0cdfd4acf5c where isModuleReference is replaced by getModuleReference. Do you think this is OK?

~~Webpack and Vite tests are passing but there's still an issue in this approach related to React's forwardRefs that I still haven't figured out. I'll try to fix that and also the flowtypes/eslint errors soon.~~ All tests passing, finally (I couldn't run Flow in M1 🤦 ).

frandiox avatar Mar 25 '22 10:03 frandiox

@frandiox Are you able to set up a reduced fixture similar to the one in fixtures/flight using Vite? I'm not familiar enough with the canonical Vite set up. Can be a separate PR that builds on top of this one.

I'm working on reducing the complexity of the Webpack one by using a minimum number of features.

sebmarkbage avatar May 03 '22 00:05 sebmarkbage

Since the latest thinking RFC has evolved to no longer represent what it's in the Webpack plugin, I think we can start landing this and then iterate on moving both to a shared model. I'll have a bunch of nits to go through first though.

sebmarkbage avatar May 04 '22 00:05 sebmarkbage

@sebmarkbage Thanks! I just added it in fixtures/flight-vite. I didn't quite understand all the Jest part in the Webpack example (it looks like there are no tests?) so I've skipped that for now.

Since the latest thinking RFC has evolved to no longer represent what it's in the Webpack plugin, I think we can start landing this and then iterate on moving both to a shared model. I'll have a bunch of nits to go through first though.

Sounds good 👍

Edit: sync_reconciler_forks failed on CI and I've no idea why 👀

frandiox avatar May 09 '22 14:05 frandiox

By the way, from the RFC:

I'm seeing more and more that the react-server ability to fork implementations for client(able) and server usage becoming more important. So we might want to still keep that. That requires a module graph implementation that's capable of forking them.

I'm also seeing that it's more and more important to be able to run small slices of server components in independent workers.

So to me it seems like the Proxy approach is DOA. It's not going to work as a required implementation detail.

Just to clarify, I think this plugin's approach can optionally support multiple bundles. It could simply use module references instead of proxies if a given option is passed. However, I don't think it's compatible with Node conditions (react-server), and I guess this is the main problem, right?

We can try the Node conditions approach in a v2 of the Vite plugin if it's an important requirement. I think we will have some issues in Hydrogen with this approach but something we can probably work around somehow. I'll start experimenting with it.

frandiox avatar May 11 '22 13:05 frandiox

I think that in theory it doesn't necessarily have to be separate bundles per se. Even in a single bundle it would be better if a Proxy could be avoided.

Next.js has tried using query params to effectively create two separate require paths in one tree. shared-component.js?server vs shared-component.js ends up as two different requires and then recursively does so. This is how I imagine esm.sh and similar CDNs could do it. The problem is that even this technique doesn't support the separate branches using different export conditions in Webpack, so we're exploring some other techniques like creating separate compilation units.

I don't think there's anything fundamentally in either Vite nor Webpack that couldn't support this. It's just not designed for it yet.

sebmarkbage avatar May 11 '22 17:05 sebmarkbage

Since we've been investing more in compiler based optimizations lately there has been a number of idea lately that has spawned that would be SSR specific compilation options:

  • Converting React.lazy to a form that can preload chunks when executed on the server (this might even be in the same plugin as RSC).
  • Compiling out useEvent and its dependencies.
  • Compiling blocks of host component JSX to HTML.
  • Not using React Forget style optimizations that only are impactful on the client.
  • Compile the component boundary protocol differently on the server vs client.

As well as Server Component specific optimizations like eagerly evaluate some branches if earlier ones suspend to avoid waterfalls.

This made us realize that we can't use the same bundles for SSR and the client, even if you're running in a "Web-like environment" on the server. Because then they couldn't apply different compilation optimizations.

However, I think that also applies to Server Components vs SSR.

These might hurt perf when applied to the other one or might actually not work. E.g. React.lazy when executed in server components should not send preload chunk signals since those won't be used on the client. JSX to HTML when the whole tree is static is an optimization we want to do for Server Components - however - because we want to preserve state that wouldn't apply the same to parent trees. However, for server rendering it's also feasible to do this for parent segments.

All this wouldn't work in the Proxy approach so I'm more and more thinking that we can't recommend that approach in good conscience - even though we could maybe keep supporting it. It just would miss out on a lot of future optimization work in React.

sebmarkbage avatar May 11 '22 20:05 sebmarkbage

Instead of changing isModuleReference, you can make it look up in the map if the string is in the map. Then inside resolveModuleMetaData and getModuleKey you can look it up again.

Alright, I've reverted it to isModuleReference and changed resolveModuleMetaData and getModuleKey accordingly. However, I think we also need make some minor changes in attemptResolveElement and resolveModelToJSON, as shown in 095b4f623586535cf13512c725f39d7193025432 . The reason is that, otherwise, functions and strings are not handled properly.

Would that be ok until we drop the proxies?

frandiox avatar May 31 '22 09:05 frandiox

I think we also need make some minor changes in attemptResolveElement and resolveModelToJSON, as shown in https://github.com/facebook/react/commit/095b4f623586535cf13512c725f39d7193025432 . The reason is that, otherwise, functions and strings are not handled properly.

You can plop in a isModuleReference check in the typeof type === 'function' branch. It's probably fine to assume that the string won't be a "long string" if it's used as a host component type (HTML tag). Short strings are better to inline anyway.

sebmarkbage avatar May 31 '22 16:05 sebmarkbage

You can plop in a isModuleReference check in the typeof type === 'function' branch. It's probably fine to assume that the string won't be a "long string" if it's used as a host component type (HTML tag). Short strings are better to inline anyway.

Is this what you meant?

Also, any pointers to fix the sync_reconciler_forks issue on CI? Running yarn replace-fork locally doesn't seem to change anything 🤔


Edit: Aside from that, do you know a better implementation for isRSC? This utility will be removed once we drop proxies but for the time being I'd like to improve it a bit. The current one is not very performant. I'm trying the following, which is much faster, but it needs to access React internals:

function isRsc() {
  return !!React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
    .ReactCurrentDispatcher.current.getCacheForType;
}

Edit2: We are now using something similar to the previous code now, but using a custom flag ffc564af8740235b57f19880d8fea85470fae552

frandiox avatar Jun 06 '22 10:06 frandiox

What do you think it'd take to get ServerContext working, I tested react@experimental in Hydrogen but I get things like Unexpected pop. and Unexpected Fiber popped. Just curious if that's coming from this plugin or maybe just caught some experimental issue on the version I tried.

natew avatar Aug 14 '22 21:08 natew

@natew I just updated this plugin with the latest changes in upstream. Not sure if it will fix your issues, though, but you can give it a try. Other than that, I think there's not much to do in this plugin about Server Context 🤔

frandiox avatar Aug 17 '22 12:08 frandiox

Closing this since it's outdated and there's a new approach following the latest conventions in https://github.com/facebook/react/pull/26926

frandiox avatar Jun 12 '23 06:06 frandiox