chore: refactoring react server component client#1186
Conversation
|
@launchdarkly/js-sdk-common size report |
|
@launchdarkly/browser size report |
|
@launchdarkly/js-client-sdk-common size report |
|
@launchdarkly/js-client-sdk size report |
6e30ca5 to
562a3e6
Compare
848e4c8 to
562a3e6
Compare
|
@cursor review |
| // of meta with exclusions. | ||
| // eslint-disable-next-line no-param-reassign | ||
| opts.mangleProps = /^_([^m|_]|m[^e]|me[^t]|met[^a])/; | ||
| opts.banner = { js: '"use client";' }; |
There was a problem hiding this comment.
This is the reason that we separated the client bundle and server bundle
562a3e6 to
4bcbba2
Compare
4bcbba2 to
61658d1
Compare
There was a problem hiding this comment.
Ditching the context getter design and instead we are give the users a way to create a "scoped proxy" of the base server sdk for each request session that the LDClient is needed.
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| client.jsonVariationDetail(key, context, defaultValue), | ||
| allFlagsState: (options?: LDFlagsStateOptions) => client.allFlagsState(context, options), | ||
| }; | ||
| } |
There was a problem hiding this comment.
Internal helper createLDServerWrapper is publicly exported
Medium Severity
createLDServerWrapper is exported from LDServerSession.ts and re-exported via export * from './LDServerSession' in index.ts, making it part of the public API. However, it's only called internally by createLDServerSession and bypasses the cache() storage. If a user calls createLDServerWrapper directly, the session won't be stored in React's per-request cache, causing useLDServerSession() to return null — silently breaking the documented pattern. This function is an internal implementation detail and likely shouldn't be exported.
Additional Locations (1)
There was a problem hiding this comment.
This is by design in case developers do not want to use our cache implementation. This is the same reasoning as the ability to use named context in client components.
fc1d11f to
f2eee29
Compare
| 'createLDServerSession must only be called on the server. ' + | ||
| 'Ensure this module is not imported from client components.', |
There was a problem hiding this comment.
🟡 createLDServerWrapper error message references wrong function name
The exported createLDServerWrapper function at packages/sdk/react/src/server/LDServerSession.ts:54 throws an error with the message 'createLDServerSession must only be called on the server.', but the function's actual name is createLDServerWrapper. Since createLDServerWrapper is publicly exported via packages/sdk/react/src/server/index.ts:3, a consumer calling it directly in a browser environment would receive a confusing error referencing a different function. The error message should either say createLDServerWrapper or the function should not be exported if it's only meant to be an internal implementation detail of createLDServerSession.
| 'createLDServerSession must only be called on the server. ' + | |
| 'Ensure this module is not imported from client components.', | |
| 'createLDServerWrapper must only be called on the server. ' + | |
| 'Ensure this module is not imported from client components.', |
Was this helpful? React with 👍 or 👎 to provide feedback.
| // cache() creates a per-request memoized store — each React render tree (request) | ||
| // gets its own isolated instance. The store is populated by LDIsomorphicProvider | ||
| // and read by serverBoolVariation / useBoolVariation. |
There was a problem hiding this comment.
🟡 Stale comment references non-existent LDIsomorphicProvider and useBoolVariation
The comment at packages/sdk/react/src/server/LDServerSession.ts:8-10 states the cache store is "populated by LDIsomorphicProvider and read by serverBoolVariation / useBoolVariation", but none of these symbols exist in the server module. The store is actually populated by createLDServerSession and read by useLDServerSession. This misleads developers reading the code about how the caching mechanism works.
| // cache() creates a per-request memoized store — each React render tree (request) | |
| // gets its own isolated instance. The store is populated by LDIsomorphicProvider | |
| // and read by serverBoolVariation / useBoolVariation. | |
| // cache() creates a per-request memoized store — each React render tree (request) | |
| // gets its own isolated instance. The store is populated by createLDServerSession | |
| // and read by useLDServerSession. |
Was this helpful? React with 👍 or 👎 to provide feedback.


This PR is to finalize how the react server components can access server side LDClient. A few key points:
This address:
SDK-2026
SDK-2021
Note
Medium Risk
Changes the server entrypoint API and behavior (removes
createReactServerClient/contextProvider and no-op fallback, now throws in browser), which is potentially breaking for existing RSC integrations. Build output is also restructured into separate client/server bundles, which could affect packaging if misconfigured.Overview
Refactors the React SDK server entrypoint to a context-bound “server session” API.
createReactServerClient(and theLDContextProvider/LDReactServerOptionstypes) are removed in favor ofcreateLDServerSession(client, context), which returns anLDServerSessionwhose variation methods no longer accept a context parameter.Tightens runtime semantics and expands compatibility. Calling the server API in a browser now throws instead of returning a no-op client, and a new structural
LDServerBaseClientinterface is introduced to decouple from a concreteLDClientimplementation.Docs and examples are updated to the new session pattern, a Jest test suite is added for session binding/forwarding and the browser-guard error, and the build config is split into separate client/server outputs (client bundle gets a
"use client"banner).Written by Cursor Bugbot for commit 61658d1. This will update automatically on new commits. Configure here.