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 client router for tests #36822

Merged
merged 6 commits into from May 12, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion packages/next/build/webpack-config.ts
Expand Up @@ -554,7 +554,7 @@ export default async function getBaseWebpackConfig(
path
.relative(
dir,
path.join(NEXT_PROJECT_ROOT_DIST_CLIENT, 'root-next.js')
path.join(NEXT_PROJECT_ROOT_DIST_CLIENT, 'views-next.js')
)
.replace(/\\/g, '/'),
}
Expand Down
Expand Up @@ -194,11 +194,58 @@ const RSCComponent = (props: any) => {
)
}

const ViewRouterContext = React.createContext({})

// TODO: move to client component when handling is implemented
function ViewRouter({ initialUrl, children }: any) {
const initialState = {
url: initialUrl,
}
const previousUrlRef = React.useRef(initialState)
const [current, setCurrent] = React.useState(initialState)

const viewRouter = React.useMemo(() => {
return {
push: (url: string) => {
previousUrlRef.current = current
setCurrent({ ...current, url })
// TODO: update url eagerly or not?
window.history.pushState(current, '', url)
},
url: current.url,
}
}, [current])

// @ts-ignore TODO: for testing
window.viewRouter = viewRouter

console.log({
viewRouter,
previous: previousUrlRef.current,
current,
})

let root
if (current.url !== previousUrlRef.current?.url) {
// eslint-disable-next-line
const data = useServerResponse(current.url)
root = data.readRoot()
}

return (
<ViewRouterContext.Provider value={viewRouter}>
{root ? root : children}
</ViewRouterContext.Provider>
)
}

export function hydrate() {
renderReactElement(appElement!, () => (
<React.StrictMode>
<Root>
<RSCComponent />
<ViewRouter initialUrl={location.pathname}>
<RSCComponent />
</ViewRouter>
</Root>
</React.StrictMode>
))
Expand Down
@@ -1,4 +1,4 @@
import { hydrate, version } from './root-index'
import { hydrate, version } from './views-index'

window.next = {
version,
Expand Down
12 changes: 4 additions & 8 deletions packages/next/lib/views-layout.tsx
@@ -1,21 +1,17 @@
import React from 'react'

export type LayoutProps = {
headChildren: any
bodyChildren: any
children: any
}

export default function ViewsLayout({
headChildren,
bodyChildren,
}: LayoutProps) {
export default function ViewsLayout({ children }: LayoutProps) {
return (
<html>
<head>
{headChildren}
{/* TODO: Remove <title> */}
<title>Test</title>
</head>
<body>{bodyChildren}</body>
<body>{children}</body>
</html>
)
}
28 changes: 3 additions & 25 deletions packages/next/server/node-web-streams-helper.ts
Expand Up @@ -139,11 +139,13 @@ export function createFlushEffectStream(
export function renderToInitialStream({
ReactDOMServer,
element,
streamOptions,
}: {
ReactDOMServer: any
element: React.ReactElement
streamOptions?: any
}): Promise<ReactReadableStream> {
return ReactDOMServer.renderToReadableStream(element)
return ReactDOMServer.renderToReadableStream(element, streamOptions)
}

export async function continueFromInitialStream(
Expand Down Expand Up @@ -181,30 +183,6 @@ export async function continueFromInitialStream(
)
}

export async function renderToStream({
ReactDOMServer,
element,
suffix,
dataStream,
generateStaticHTML,
flushEffectHandler,
}: {
ReactDOMServer: typeof import('react-dom/server')
element: React.ReactElement
suffix?: string
dataStream?: ReadableStream<Uint8Array>
generateStaticHTML: boolean
flushEffectHandler?: () => string
}): Promise<ReadableStream<Uint8Array>> {
const renderStream = await renderToInitialStream({ ReactDOMServer, element })
return continueFromInitialStream(renderStream, {
suffix,
dataStream,
generateStaticHTML,
flushEffectHandler,
})
}

export function createSuffixStream(
suffix: string
): TransformStream<Uint8Array, Uint8Array> {
Expand Down
18 changes: 9 additions & 9 deletions packages/next/server/view-render.tsx
Expand Up @@ -326,12 +326,11 @@ export async function renderToHTML(
}
}

// if this is the root layout pass children as bodyChildren prop
// if this is the root layout pass children as children prop
if (!isSubtreeRender && i === 0) {
return React.createElement(layout.Component, {
...props,
headChildren: props.headChildren,
bodyChildren: React.createElement(
children: React.createElement(
lastComponent || React.Fragment,
{},
null
Expand All @@ -356,10 +355,8 @@ export async function renderToHTML(
// }
}

const headChildren = !isSubtreeRender
? buildManifest.rootMainFiles.map((src) => (
<script src={'/_next/' + src} async key={src} />
))
const bootstrapScripts = !isSubtreeRender
? buildManifest.rootMainFiles.map((src) => '/_next/' + src)
: undefined

let serverComponentsInlinedTransformStream: TransformStream<
Expand Down Expand Up @@ -429,7 +426,7 @@ export async function renderToHTML(
if (renderServerComponentData) {
return new RenderResult(
renderToReadableStream(
<WrappedComponent headChildren={headChildren} />,
<WrappedComponent />,
serverComponentManifest
).pipeThrough(createBufferedTransformStream())
)
Expand All @@ -452,13 +449,16 @@ export async function renderToHTML(
const bodyResult = async () => {
const content = (
<AppContainer>
<Component headChildren={headChildren} />
<Component />
</AppContainer>
)

const renderStream = await renderToInitialStream({
ReactDOMServer,
element: content,
streamOptions: {
bootstrapScripts,
},
})

const flushEffectHandler = (): string => {
Expand Down
5 changes: 2 additions & 3 deletions test/e2e/views-dir/app/views/(newroot)/layout.server.js
Expand Up @@ -6,14 +6,13 @@ export async function getServerSideProps() {
}
}

export default function Root({ headChildren, bodyChildren, world }) {
export default function Root({ children, world }) {
return (
<html className="this-is-another-document-html">
<head>
{headChildren}
<title>{`hello ${world}`}</title>
</head>
<body className="this-is-another-document-body">{bodyChildren}</body>
<body className="this-is-another-document-body">{children}</body>
</html>
)
}
5 changes: 2 additions & 3 deletions test/e2e/views-dir/app/views/layout.server.js
Expand Up @@ -6,14 +6,13 @@ export async function getServerSideProps() {
}
}

export default function Root({ headChildren, bodyChildren, world }) {
export default function Root({ children, world }) {
return (
<html className="this-is-the-document-html">
<head>
{headChildren}
<title>{`hello ${world}`}</title>
</head>
<body className="this-is-the-document-body">{bodyChildren}</body>
<body className="this-is-the-document-body">{children}</body>
</html>
)
}