From cc65152e39e77f8784cca6395856450f0d4bad13 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 10 Aug 2024 23:53:55 +1200 Subject: [PATCH 01/10] using the a TextEncoder --- packages/start/src/server/transformStreamWithRouter.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/start/src/server/transformStreamWithRouter.ts b/packages/start/src/server/transformStreamWithRouter.ts index 2b8bfa16b98..67c73a14f78 100644 --- a/packages/start/src/server/transformStreamWithRouter.ts +++ b/packages/start/src/server/transformStreamWithRouter.ts @@ -25,10 +25,13 @@ export function transformReadableStreamWithRouter(router: AnyRouter) { const callbacks = transformHtmlCallbacks(() => router.injectedHtml.map((d) => d()).join(''), ) + + const encoder = new TextEncoder() + return new TransformStream({ transform(chunk, controller) { return callbacks.transform(chunk, (chunkToPush) => { - controller.enqueue(chunkToPush) + controller.enqueue(encoder.encode(chunkToPush)) return true }) }, From 50bf56b106764767829126068beeeb2ac2099a73 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:21:41 +1200 Subject: [PATCH 02/10] trying without the changes from #1822 --- packages/react-router/src/Matches.tsx | 8 +- packages/react-router/tests/link.test.tsx | 130 +++++++++++----------- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/packages/react-router/src/Matches.tsx b/packages/react-router/src/Matches.tsx index 738da53cf42..f19d000f3c7 100644 --- a/packages/react-router/src/Matches.tsx +++ b/packages/react-router/src/Matches.tsx @@ -109,11 +109,15 @@ export function Matches() { ) : null + const ResolvedSuspense = !router.state.matches.length + ? React.Suspense + : SafeFragment + const inner = ( - + - + ) return router.options.InnerWrap ? ( diff --git a/packages/react-router/tests/link.test.tsx b/packages/react-router/tests/link.test.tsx index 9bf54202b02..f8875be00d5 100644 --- a/packages/react-router/tests/link.test.tsx +++ b/packages/react-router/tests/link.test.tsx @@ -48,71 +48,71 @@ afterEach(() => { }) describe('Link', () => { - test('when using renderHook it returns a hook with same content to prove rerender works', async () => { - /** - * This is the hook that will be testet. - * - * @returns custom state - */ - const useLocationFromState = () => { - const { location } = useRouterState() - - // could return anything just to prove it will work. - const memoLocation = React.useMemo(() => { - return { - href: location.href, - pathname: location.pathname, - } - }, [location.href, location.pathname]) - - return memoLocation - } - - const IndexComponent = ({ children }: { children: React.ReactNode }) => { - return

{children}

- } - const RouterContainer = ({ children }: { children: React.ReactNode }) => { - const childrenRef = React.useRef(children) - const memoedRouteTree = React.useMemo(() => { - const rootRoute = createRootRoute() - const indexRoute = createRoute({ - getParentRoute: () => rootRoute, - path: '/', - component: () => ( - {childrenRef.current} - ), - }) - return rootRoute.addChildren([indexRoute]) - }, []) - - const memoedRouter = React.useMemo(() => { - const router = createRouter({ - routeTree: memoedRouteTree, - }) - - return router - }, [memoedRouteTree]) - return - } - - const { result, rerender } = renderHook( - () => { - return useLocationFromState() - }, - { wrapper: RouterContainer }, - ) - await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) - expect(result.current).toBeTruthy() - - const original = result.current - - rerender() - - await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) - const updated = result.current - - expect(original).toBe(updated) - }) + // test('when using renderHook it returns a hook with same content to prove rerender works', async () => { + // /** + // * This is the hook that will be testet. + // * + // * @returns custom state + // */ + // const useLocationFromState = () => { + // const { location } = useRouterState() + + // // could return anything just to prove it will work. + // const memoLocation = React.useMemo(() => { + // return { + // href: location.href, + // pathname: location.pathname, + // } + // }, [location.href, location.pathname]) + + // return memoLocation + // } + + // const IndexComponent = ({ children }: { children: React.ReactNode }) => { + // return

{children}

+ // } + // const RouterContainer = ({ children }: { children: React.ReactNode }) => { + // const childrenRef = React.useRef(children) + // const memoedRouteTree = React.useMemo(() => { + // const rootRoute = createRootRoute() + // const indexRoute = createRoute({ + // getParentRoute: () => rootRoute, + // path: '/', + // component: () => ( + // {childrenRef.current} + // ), + // }) + // return rootRoute.addChildren([indexRoute]) + // }, []) + + // const memoedRouter = React.useMemo(() => { + // const router = createRouter({ + // routeTree: memoedRouteTree, + // }) + + // return router + // }, [memoedRouteTree]) + // return + // } + + // const { result, rerender } = renderHook( + // () => { + // return useLocationFromState() + // }, + // { wrapper: RouterContainer }, + // ) + // await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) + // expect(result.current).toBeTruthy() + + // const original = result.current + + // rerender() + + // await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) + // const updated = result.current + + // expect(original).toBe(updated) + // }) test('when a Link is disabled', async () => { const rootRoute = createRootRoute() From 9dd07520c40a2cb76abaa1ad646cab9150dc917e Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:27:04 +1200 Subject: [PATCH 03/10] revert that last commit --- packages/react-router/src/Matches.tsx | 8 +- packages/react-router/tests/link.test.tsx | 130 +++++++++++----------- 2 files changed, 67 insertions(+), 71 deletions(-) diff --git a/packages/react-router/src/Matches.tsx b/packages/react-router/src/Matches.tsx index f19d000f3c7..738da53cf42 100644 --- a/packages/react-router/src/Matches.tsx +++ b/packages/react-router/src/Matches.tsx @@ -109,15 +109,11 @@ export function Matches() { ) : null - const ResolvedSuspense = !router.state.matches.length - ? React.Suspense - : SafeFragment - const inner = ( - + - + ) return router.options.InnerWrap ? ( diff --git a/packages/react-router/tests/link.test.tsx b/packages/react-router/tests/link.test.tsx index f8875be00d5..9bf54202b02 100644 --- a/packages/react-router/tests/link.test.tsx +++ b/packages/react-router/tests/link.test.tsx @@ -48,71 +48,71 @@ afterEach(() => { }) describe('Link', () => { - // test('when using renderHook it returns a hook with same content to prove rerender works', async () => { - // /** - // * This is the hook that will be testet. - // * - // * @returns custom state - // */ - // const useLocationFromState = () => { - // const { location } = useRouterState() - - // // could return anything just to prove it will work. - // const memoLocation = React.useMemo(() => { - // return { - // href: location.href, - // pathname: location.pathname, - // } - // }, [location.href, location.pathname]) - - // return memoLocation - // } - - // const IndexComponent = ({ children }: { children: React.ReactNode }) => { - // return

{children}

- // } - // const RouterContainer = ({ children }: { children: React.ReactNode }) => { - // const childrenRef = React.useRef(children) - // const memoedRouteTree = React.useMemo(() => { - // const rootRoute = createRootRoute() - // const indexRoute = createRoute({ - // getParentRoute: () => rootRoute, - // path: '/', - // component: () => ( - // {childrenRef.current} - // ), - // }) - // return rootRoute.addChildren([indexRoute]) - // }, []) - - // const memoedRouter = React.useMemo(() => { - // const router = createRouter({ - // routeTree: memoedRouteTree, - // }) - - // return router - // }, [memoedRouteTree]) - // return - // } - - // const { result, rerender } = renderHook( - // () => { - // return useLocationFromState() - // }, - // { wrapper: RouterContainer }, - // ) - // await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) - // expect(result.current).toBeTruthy() - - // const original = result.current - - // rerender() - - // await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) - // const updated = result.current - - // expect(original).toBe(updated) - // }) + test('when using renderHook it returns a hook with same content to prove rerender works', async () => { + /** + * This is the hook that will be testet. + * + * @returns custom state + */ + const useLocationFromState = () => { + const { location } = useRouterState() + + // could return anything just to prove it will work. + const memoLocation = React.useMemo(() => { + return { + href: location.href, + pathname: location.pathname, + } + }, [location.href, location.pathname]) + + return memoLocation + } + + const IndexComponent = ({ children }: { children: React.ReactNode }) => { + return

{children}

+ } + const RouterContainer = ({ children }: { children: React.ReactNode }) => { + const childrenRef = React.useRef(children) + const memoedRouteTree = React.useMemo(() => { + const rootRoute = createRootRoute() + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () => ( + {childrenRef.current} + ), + }) + return rootRoute.addChildren([indexRoute]) + }, []) + + const memoedRouter = React.useMemo(() => { + const router = createRouter({ + routeTree: memoedRouteTree, + }) + + return router + }, [memoedRouteTree]) + return + } + + const { result, rerender } = renderHook( + () => { + return useLocationFromState() + }, + { wrapper: RouterContainer }, + ) + await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) + expect(result.current).toBeTruthy() + + const original = result.current + + rerender() + + await waitFor(() => expect(screen.getByTestId('testId')).toBeVisible()) + const updated = result.current + + expect(original).toBe(updated) + }) test('when a Link is disabled', async () => { const rootRoute = createRootRoute() From ba331b2f1621e2ea024709dcf8eeb4d865d29ce3 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:44:27 +1200 Subject: [PATCH 04/10] use TextDecoder on the client-side of the stream --- packages/start/src/client/serialization.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/start/src/client/serialization.tsx b/packages/start/src/client/serialization.tsx index 29067c03b09..86a1ab44e29 100644 --- a/packages/start/src/client/serialization.tsx +++ b/packages/start/src/client/serialization.tsx @@ -274,6 +274,7 @@ function createStreamState({ } const reader = stream.getReader() + const decoder = new TextDecoder() const read = (index: number): any => { streamState.promises[index] = createControlledPromise() @@ -285,7 +286,8 @@ function createStreamState({ return } - streamState.promises[index]!.resolve(value) + const chunk = decoder.decode(value, { stream: true }) + streamState.promises[index]!.resolve(chunk) return read(index + 1) }) From 340796e24fe73de7f4a2d0008533664a8468e15a Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 01:14:20 +1200 Subject: [PATCH 05/10] undo --- packages/start/src/client/serialization.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/start/src/client/serialization.tsx b/packages/start/src/client/serialization.tsx index 86a1ab44e29..29067c03b09 100644 --- a/packages/start/src/client/serialization.tsx +++ b/packages/start/src/client/serialization.tsx @@ -274,7 +274,6 @@ function createStreamState({ } const reader = stream.getReader() - const decoder = new TextDecoder() const read = (index: number): any => { streamState.promises[index] = createControlledPromise() @@ -286,8 +285,7 @@ function createStreamState({ return } - const chunk = decoder.decode(value, { stream: true }) - streamState.promises[index]!.resolve(chunk) + streamState.promises[index]!.resolve(value) return read(index + 1) }) From c273aab327de727ba231c4f1d2305091a5e8eee4 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 01:33:42 +1200 Subject: [PATCH 06/10] temporary disable --- .../start/src/server/defaultStreamHandler.tsx | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/start/src/server/defaultStreamHandler.tsx b/packages/start/src/server/defaultStreamHandler.tsx index fd21f9692c3..05797481c94 100644 --- a/packages/start/src/server/defaultStreamHandler.tsx +++ b/packages/start/src/server/defaultStreamHandler.tsx @@ -19,32 +19,34 @@ export const defaultStreamHandler: HandlerCallback = async ({ router, responseHeaders, }) => { - if (typeof ReactDOMServer.renderToReadableStream === 'function') { - const stream = await ReactDOMServer.renderToReadableStream( - , - { - signal: request.signal, - }, - ) + // if (typeof ReactDOMServer.renderToReadableStream === 'function') { + // console.log('ReactDOMServer.renderToReadableStream') + // const stream = await ReactDOMServer.renderToReadableStream( + // , + // { + // signal: request.signal, + // }, + // ) - if (isbot(request.headers.get('User-Agent'))) { - await stream.allReady - } + // if (isbot(request.headers.get('User-Agent'))) { + // await stream.allReady + // } - const transforms = [transformReadableStreamWithRouter(router)] + // const transforms = [transformReadableStreamWithRouter(router)] - const transformedStream = transforms.reduce( - (stream, transform) => stream.pipeThrough(transform), - stream as ReadableStream, - ) + // const transformedStream = transforms.reduce( + // (stream, transform) => stream.pipeThrough(transform), + // stream as ReadableStream, + // ) - return new Response(transformedStream, { - status: router.state.statusCode, - headers: responseHeaders, - }) - } + // return new Response(transformedStream, { + // status: router.state.statusCode, + // headers: responseHeaders, + // }) + // } if (typeof ReactDOMServer.renderToPipeableStream === 'function') { + console.log('ReactDOMServer.renderToPipeableStream') const passthrough = new PassThrough() const pipeable = ReactDOMServer.renderToPipeableStream( From 67a2e1c484abcae54368df92ab95297d8038fe20 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 01:37:12 +1200 Subject: [PATCH 07/10] re-enable --- .../start/src/server/defaultStreamHandler.tsx | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/start/src/server/defaultStreamHandler.tsx b/packages/start/src/server/defaultStreamHandler.tsx index 05797481c94..fd21f9692c3 100644 --- a/packages/start/src/server/defaultStreamHandler.tsx +++ b/packages/start/src/server/defaultStreamHandler.tsx @@ -19,34 +19,32 @@ export const defaultStreamHandler: HandlerCallback = async ({ router, responseHeaders, }) => { - // if (typeof ReactDOMServer.renderToReadableStream === 'function') { - // console.log('ReactDOMServer.renderToReadableStream') - // const stream = await ReactDOMServer.renderToReadableStream( - // , - // { - // signal: request.signal, - // }, - // ) + if (typeof ReactDOMServer.renderToReadableStream === 'function') { + const stream = await ReactDOMServer.renderToReadableStream( + , + { + signal: request.signal, + }, + ) - // if (isbot(request.headers.get('User-Agent'))) { - // await stream.allReady - // } + if (isbot(request.headers.get('User-Agent'))) { + await stream.allReady + } - // const transforms = [transformReadableStreamWithRouter(router)] + const transforms = [transformReadableStreamWithRouter(router)] - // const transformedStream = transforms.reduce( - // (stream, transform) => stream.pipeThrough(transform), - // stream as ReadableStream, - // ) + const transformedStream = transforms.reduce( + (stream, transform) => stream.pipeThrough(transform), + stream as ReadableStream, + ) - // return new Response(transformedStream, { - // status: router.state.statusCode, - // headers: responseHeaders, - // }) - // } + return new Response(transformedStream, { + status: router.state.statusCode, + headers: responseHeaders, + }) + } if (typeof ReactDOMServer.renderToPipeableStream === 'function') { - console.log('ReactDOMServer.renderToPipeableStream') const passthrough = new PassThrough() const pipeable = ReactDOMServer.renderToPipeableStream( From bc1741a231dcc3dfbdab3bcb053113a41820faa6 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 01:42:51 +1200 Subject: [PATCH 08/10] style: eslint warnings --- packages/start/src/server/transformStreamWithRouter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/start/src/server/transformStreamWithRouter.ts b/packages/start/src/server/transformStreamWithRouter.ts index 67c73a14f78..b215942cdd1 100644 --- a/packages/start/src/server/transformStreamWithRouter.ts +++ b/packages/start/src/server/transformStreamWithRouter.ts @@ -62,6 +62,7 @@ function transformHtmlCallbacks(getHtml: () => string) { let leftoverHtml = '' return { + // eslint-disable-next-line @typescript-eslint/require-await async transform(chunk: any, push: (chunkToPush: string) => boolean) { const chunkString = leftover + textDecoder.decode(chunk) @@ -126,6 +127,7 @@ function transformHtmlCallbacks(getHtml: () => string) { throw err } }, + // eslint-disable-next-line @typescript-eslint/require-await async flush(push: (chunkToPush: string) => boolean) { if (leftover) { push(leftover) From 218256b5eed2b8ef47e0f3e9b3f5829b94822d2d Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 02:37:30 +1200 Subject: [PATCH 09/10] log error events --- packages/start/src/server/defaultStreamHandler.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/start/src/server/defaultStreamHandler.tsx b/packages/start/src/server/defaultStreamHandler.tsx index fd21f9692c3..468bc47afc7 100644 --- a/packages/start/src/server/defaultStreamHandler.tsx +++ b/packages/start/src/server/defaultStreamHandler.tsx @@ -24,6 +24,9 @@ export const defaultStreamHandler: HandlerCallback = async ({ , { signal: request.signal, + onError(error, errorInfo) { + console.error(error, errorInfo) + }, }, ) From 753cc2d552a30cc5194799506c66baa1cca4928b Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sun, 11 Aug 2024 12:45:59 +1200 Subject: [PATCH 10/10] gitignore wrangler outputs --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7d0cf969f32..ce8d7b7cd98 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ artifacts .rpt2_cache coverage *.tgz +.wrangler # tests packages/router-generator/tests/**/*.gen.ts