Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update RSC plugin to support useId #1577

Merged
merged 3 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/hydrogen/src/entry-server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -408,10 +408,10 @@ async function runSSR({
bootstrapScripts,
bootstrapModules,
onError(error) {
ssrDidError = error;
ssrDidError = error as Error;

if (dev && !writable.closed && !!responseOptions.status) {
writable.write(getErrorMarkup(error));
writable.write(getErrorMarkup(error as Error));
}

log.error(error);
Expand Down
45 changes: 18 additions & 27 deletions packages/hydrogen/src/streaming.server.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import {
// @ts-ignore
renderToPipeableStream as _ssrRenderToPipeableStream, // Only available in Node context
// @ts-ignore
renderToReadableStream as _ssrRenderToReadableStream, // Only available in Browser/Worker context
export {
renderToPipeableStream as ssrRenderToPipeableStream, // Only available in Node context
renderToReadableStream as ssrRenderToReadableStream, // Only available in Browser/Worker context
} from 'react-dom/server';

// @ts-ignore
import {renderToReadableStream as _rscRenderToReadableStream} from '@shopify/hydrogen/vendor/react-server-dom-vite/writer.browser.server';
// @ts-ignore
import {createFromReadableStream as _createFromReadableStream} from '@shopify/hydrogen/vendor/react-server-dom-vite';
import type {Writable} from 'stream';

// From Flight flow types
type ServerContextJSONValue =
| string
| boolean
| number
| null
| Readonly<ServerContextJSONValueCircular>
| {[key: string]: ServerContextJSONValueCircular};

interface ServerContextJSONValueCircular
extends Array<ServerContextJSONValue> {}

export const rscRenderToReadableStream = _rscRenderToReadableStream as (
App: JSX.Element,
options?: {
onError?: (error: Error) => void;
context?: Array<[string, ServerContextJSONValue]>;
identifierPrefix?: string;
}
) => ReadableStream<Uint8Array>;

Expand All @@ -23,27 +35,6 @@ export const createFromReadableStream = _createFromReadableStream as (
readRoot: () => JSX.Element;
};

type StreamOptions = {
nonce?: string;
bootstrapScripts?: string[];
bootstrapModules?: string[];
onError?: (error: Error) => void;
};

export const ssrRenderToPipeableStream = _ssrRenderToPipeableStream as (
App: JSX.Element,
options: StreamOptions & {
onAllReady?: () => void;
onShellReady?: () => void;
onShellError?: (error: Error) => void;
}
) => {pipe: Writable['pipe']};

export const ssrRenderToReadableStream = _ssrRenderToReadableStream as (
App: JSX.Element,
options: StreamOptions
) => Promise<ReadableStream<Uint8Array> & {allReady: Promise<void>}>;

export async function bufferReadableStream(
reader: ReadableStreamDefaultReader,
cb?: (chunk: string) => void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,10 +545,12 @@ var startPendingSuspenseBoundary1 = stringToPrecomputedChunk('<!--$?--><template
var startPendingSuspenseBoundary2 = stringToPrecomputedChunk('"></template>');
var startClientRenderedSuspenseBoundary = stringToPrecomputedChunk('<!--$!-->');
var endSuspenseBoundary = stringToPrecomputedChunk('<!--/$-->');
var clientRenderedSuspenseBoundaryError1 = stringToPrecomputedChunk('<template data-hash="');
var clientRenderedSuspenseBoundaryError1A = stringToPrecomputedChunk('" data-msg="');
var clientRenderedSuspenseBoundaryError1B = stringToPrecomputedChunk('" data-stack="');
var clientRenderedSuspenseBoundaryError2 = stringToPrecomputedChunk('"></template>');
var clientRenderedSuspenseBoundaryError1 = stringToPrecomputedChunk('<template');
var clientRenderedSuspenseBoundaryErrorAttrInterstitial = stringToPrecomputedChunk('"');
var clientRenderedSuspenseBoundaryError1A = stringToPrecomputedChunk(' data-dgst="');
var clientRenderedSuspenseBoundaryError1B = stringToPrecomputedChunk(' data-msg="');
var clientRenderedSuspenseBoundaryError1C = stringToPrecomputedChunk(' data-stck="');
var clientRenderedSuspenseBoundaryError2 = stringToPrecomputedChunk('></template>');
var startSegmentHTML = stringToPrecomputedChunk('<div hidden id="');
var startSegmentHTML2 = stringToPrecomputedChunk('">');
var endSegmentHTML = stringToPrecomputedChunk('</div>');
Expand Down Expand Up @@ -578,7 +580,7 @@ var endSegmentColGroup = stringToPrecomputedChunk('</colgroup></table>');
// const SUSPENSE_PENDING_START_DATA = '$?';
// const SUSPENSE_FALLBACK_START_DATA = '$!';
//
// function clientRenderBoundary(suspenseBoundaryID, errorHash, errorMsg, errorComponentStack) {
// function clientRenderBoundary(suspenseBoundaryID, errorDigest, errorMsg, errorComponentStack) {
// // Find the fallback's first element.
// const suspenseIdNode = document.getElementById(suspenseBoundaryID);
// if (!suspenseIdNode) {
Expand All @@ -592,9 +594,9 @@ var endSegmentColGroup = stringToPrecomputedChunk('</colgroup></table>');
// suspenseNode.data = SUSPENSE_FALLBACK_START_DATA;
// // assign error metadata to first sibling
// let dataset = suspenseIdNode.dataset;
// if (errorHash) dataset.hash = errorHash;
// if (errorDigest) dataset.dgst = errorDigest;
// if (errorMsg) dataset.msg = errorMsg;
// if (errorComponentStack) dataset.stack = errorComponentStack;
// if (errorComponentStack) dataset.stck = errorComponentStack;
// // Tell React to retry it if the parent already hydrated.
// if (suspenseNode._reactRetry) {
// suspenseNode._reactRetry();
Expand Down Expand Up @@ -678,7 +680,7 @@ var endSegmentColGroup = stringToPrecomputedChunk('</colgroup></table>');

var completeSegmentFunction = 'function $RS(a,b){a=document.getElementById(a);b=document.getElementById(b);for(a.parentNode.removeChild(a);a.firstChild;)b.parentNode.insertBefore(a.firstChild,b);b.parentNode.removeChild(b)}';
var completeBoundaryFunction = 'function $RC(a,b){a=document.getElementById(a);b=document.getElementById(b);b.parentNode.removeChild(b);if(a){a=a.previousSibling;var f=a.parentNode,c=a.nextSibling,e=0;do{if(c&&8===c.nodeType){var d=c.data;if("/$"===d)if(0===e)break;else e--;else"$"!==d&&"$?"!==d&&"$!"!==d||e++}d=c.nextSibling;f.removeChild(c);c=d}while(c);for(;b.firstChild;)f.insertBefore(b.firstChild,c);a.data="$";a._reactRetry&&a._reactRetry()}}';
var clientRenderFunction = 'function $RX(b,c,d,e){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.hash=c),d&&(a.msg=d),e&&(a.stack=e),b._reactRetry&&b._reactRetry())}';
var clientRenderFunction = 'function $RX(b,c,d,e){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),b._reactRetry&&b._reactRetry())}';
var completeSegmentScript1Full = stringToPrecomputedChunk(completeSegmentFunction + ';$RS("');
var completeSegmentScript1Partial = stringToPrecomputedChunk('$RS("');
var completeSegmentScript2 = stringToPrecomputedChunk('","');
Expand Down Expand Up @@ -883,6 +885,14 @@ function readContext(context) {
return value;
}

var currentRequest = null;
function prepareToUseHooksForRequest(request) {
currentRequest = request;
}
function resetHooksForRequest() {
currentRequest = null;
}

function readContext$1(context) {
{
if (context.$$typeof !== REACT_SERVER_CONTEXT_TYPE) {
Expand Down Expand Up @@ -931,7 +941,7 @@ var Dispatcher = {
useLayoutEffect: unsupportedHook,
useImperativeHandle: unsupportedHook,
useEffect: unsupportedHook,
useId: unsupportedHook,
useId: useId,
useMutableSource: unsupportedHook,
useSyncExternalStore: unsupportedHook,
useCacheRefresh: function () {
Expand All @@ -958,6 +968,16 @@ function getCurrentCache() {
return currentCache;
}

function useId() {
if (currentRequest === null) {
throw new Error('useId can only be used while React is rendering');
}

var id = currentRequest.identifierCount++; // use 'S' for Flight components to distinguish from 'R' and 'r' in Fizz/Client

return ':' + currentRequest.identifierPrefix + 'S' + id.toString(32) + ':';
}

var ContextRegistry = ReactSharedInternals.ContextRegistry;
function getOrCreateServerContext(globalName) {
if (!ContextRegistry[globalName]) {
Expand All @@ -976,7 +996,7 @@ function defaultErrorHandler(error) {
var OPEN = 0;
var CLOSING = 1;
var CLOSED = 2;
function createRequest(model, bundlerConfig, onError, context) {
function createRequest(model, bundlerConfig, onError, context, identifierPrefix) {
var pingedSegments = [];
var request = {
status: OPEN,
Expand All @@ -993,6 +1013,8 @@ function createRequest(model, bundlerConfig, onError, context) {
writtenSymbols: new Map(),
writtenModules: new Map(),
writtenProviders: new Map(),
identifierPrefix: identifierPrefix || '',
identifierCount: 1,
onError: onError === undefined ? defaultErrorHandler : onError,
toJSON: function (key, value) {
return resolveModelToJSON(request, this, key, value);
Expand Down Expand Up @@ -1605,6 +1627,7 @@ function performWork(request) {
var prevCache = getCurrentCache();
ReactCurrentDispatcher.current = Dispatcher;
setCurrentCache(request.cache);
prepareToUseHooksForRequest(request);

try {
var pingedSegments = request.pingedSegments;
Expand All @@ -1624,6 +1647,7 @@ function performWork(request) {
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
setCurrentCache(prevCache);
resetHooksForRequest();
}
}

Expand Down Expand Up @@ -1749,7 +1773,7 @@ function importServerContexts(contexts) {
return rootContextSnapshot;
}

function renderToReadableStream(model, options, context) {
function renderToReadableStream(model, options) {
var request = createRequest( // Wrap root in a dummy element that simply adds a flag
// to the current dispatcher to check later in the proxies.
assign({}, model, {
Expand All @@ -1762,7 +1786,7 @@ function renderToReadableStream(model, options, context) {
return model;
}
}), {}, // Manifest, not used
options ? options.onError : undefined, context);
options ? options.onError : undefined, options ? options.context : undefined, options ? options.identifierPrefix : undefined);
var stream = new ReadableStream({
type: 'bytes',
start: function (controller) {
Expand Down