Make @module work out of the box#5332
Draft
captbaritone wants to merge 5 commits into
Draft
Conversation
Demonstrates the minimal setup for Relay 3D with the current compiler:
- No JSDependency scalar or js() field needed — the compiler generates
componentModuleProvider/operationModuleProvider as inline dynamic imports
- OperationLoader calls the operationModuleProvider to async-load split
normalization ASTs
- MatchContainer loader wraps componentModuleProvider with React.lazy for
Suspense-based code splitting
- Server schema is just a plain union, no special 3D infrastructure
Also switches the e2e test infra to native ESM for TypeScript fixtures:
- extensionsToTreatAsEsm: ['.ts', '.tsx'] in jest config
- Skip CJS module transform for TS fixture files in jest-transform
- Use import() instead of require() in the test harness
- NODE_OPTIONS=--experimental-vm-modules in the test:e2e script
- eagerEsModules: true for babel-plugin-relay
This eliminates CJS/ESM interop issues where import() of Babel-transformed
modules produced nested { default: { default: Component } }.
Environment now auto-creates an OperationLoader when none is provided. The default handles the () => import(...) function references that the compiler generates for componentModuleProvider/operationModuleProvider, with a cache so that get() returns results synchronously after the first async load() — needed by DataChecker and RelayReferenceMarker. Users no longer need to define a custom operationLoader or construct a Store explicitly to use @module. createOperationLoader is also exported from relay-runtime for users who construct their own Store.
When componentModuleProvider is a function (the () => import(...) generated by the compiler), call it eagerly during normalization to start loading the component module in parallel with the operation normalization AST. Module systems cache import() calls, so when MatchContainer's loader calls the same function at render time it resolves from the cache — eliminating the waterfall where the component only starts loading after render.
When no loader is provided, MatchContainer resolves componentModuleProvider functions using the environment's OperationLoader — the same cache that powers normalization AST loading. This means: - get() returns the component synchronously if already cached (e.g. from the normalization-time prefetch added in the previous commit) - If not cached, a Suspense-compatible load is triggered Users no longer need to define a custom loader function or manage a React.lazy cache. The loader prop is still accepted for custom resolution strategies.
MatchContainer is now importable directly from react-relay instead of the deep path react-relay/relay-hooks/MatchContainer. Added to both index.js and hooks.js exports.
Contributor
|
@captbaritone has imported this pull request. If you are a Meta employee, you can view this in D108909152. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes Relay's data-driven dependencies (
@module) work without any special configuration beyond what's in the quick start guide. Each commit removes one piece of boilerplate:Environmentauto-creates one; removes customoperationLoader+Storeconstructionloaderpropreact-relaydirectlyAlso switches e2e test infra to native ESM for TypeScript fixtures (needed for clean
import()behavior).Before
After
Test plan
operationLoaderandloaderprop still work when provided