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

Render resolved streaming content for static render result #35221

Merged
merged 7 commits into from Mar 10, 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
1 change: 0 additions & 1 deletion packages/next/server/web-server.ts
Expand Up @@ -131,7 +131,6 @@ export default class NextWebServer extends BaseServer {
query,
{
...renderOpts,
// supportsDynamicHTML: true,
disableOptimizedLoading: true,
runtime: 'edge',
}
Expand Down
25 changes: 19 additions & 6 deletions packages/next/server/web/sandbox/readable-stream.ts
Expand Up @@ -39,17 +39,17 @@ class ReadableStream<T> {

const pull = () => {
if (opts.pull) {
if (!pullPromise) {
const shouldPull =
controller.desiredSize !== null && controller.desiredSize > 0
if (!pullPromise && shouldPull) {
pullPromise = Promise.resolve().then(() => {
pullPromise = 0
opts.pull!(controller)
})
return pullPromise
}
}
}

if (opts.start) {
opts.start(controller)
return Promise.resolve()
}

if (opts.cancel) {
Expand All @@ -59,7 +59,20 @@ class ReadableStream<T> {
}
}

pull()
function registerPull() {
const getReader = readable.getReader.bind(readable)
readable.getReader = () => {
pull()
return getReader()
}
}

const started = opts.start && opts.start(controller)
if (started && typeof started.then === 'function') {
started.then(() => registerPull())
} else {
registerPull()
}

return readable
}
Expand Down
Expand Up @@ -54,4 +54,13 @@ export default async function basic(context, { env }) {
const html = await renderViaHTTP(context.appPort, '/err/suspense')
expect(html).toContain('error-fallback')
})

it('should support React.lazy and dynamic imports', async () => {
const html = await renderViaHTTP(context.appPort, '/dynamic-imports')
expect(html).toContain('foo.client')

const browser = await webdriver(context.appPort, '/dynamic-imports')
const content = await browser.eval(`window.document.body.innerText`)
expect(content).toMatchInlineSnapshot('"foo.client"')
})
}
Expand Up @@ -2,7 +2,6 @@

import { join } from 'path'
import fs from 'fs-extra'
import webdriver from 'next-webdriver'

import { fetchViaHTTP, findPort, killApp, renderViaHTTP } from 'next-test-utils'

Expand Down Expand Up @@ -146,11 +145,6 @@ describe('Edge runtime - prod', () => {
expect(content.clientInfo).not.toContainEqual([['/404', true]])
})

it('should support React.lazy and dynamic imports', async () => {
const html = await renderViaHTTP(context.appPort, '/dynamic-imports')
expect(html).toContain('foo.client')
})

const options = { runtime: 'edge', env: 'prod' }
basic(context, options)
streaming(context, options)
Expand All @@ -171,15 +165,6 @@ describe('Edge runtime - dev', () => {
await killApp(context.server)
})

it('should support React.lazy and dynamic imports', async () => {
const html = await renderViaHTTP(context.appPort, '/dynamic-imports')
expect(html).toContain('loading...')

const browser = await webdriver(context.appPort, '/dynamic-imports')
const content = await browser.eval(`window.document.body.innerText`)
expect(content).toMatchInlineSnapshot('"foo.client"')
})

it('should have content-type and content-encoding headers', async () => {
const res = await fetchViaHTTP(context.appPort, '/')
expect(res.headers.get('content-type')).toBe('text/html; charset=utf-8')
Expand Down
@@ -1,16 +1,9 @@
/* eslint-env jest */
import webdriver from 'next-webdriver'
import cheerio from 'cheerio'
import { renderViaHTTP, check } from 'next-test-utils'
import { join } from 'path'
import fs from 'fs-extra'

import { distDir } from './utils'

function getNodeBySelector(html, selector) {
const $ = cheerio.load(html)
return $(selector)
}
import { distDir, getNodeBySelector } from './utils'

export default function (context, { runtime, env }) {
it('should render server components correctly', async () => {
Expand Down
@@ -1,6 +1,7 @@
/* eslint-env jest */
import webdriver from 'next-webdriver'
import { fetchViaHTTP, waitFor } from 'next-test-utils'
import { getNodeBySelector } from './utils'

async function resolveStreamResponse(response, onData) {
let result = ''
Expand Down Expand Up @@ -218,6 +219,10 @@ export default function (context, { env, runtime }) {
flushCount++
})
expect(flushCount).toBe(1)
const html = await res1.text()
const body = await getNodeBySelector(html, '#__next')
// Resolve data instead of fallback
expect(body.text()).toBe('next_streaming_data')

if (runtime === 'nodejs') {
expect(res1.headers.get('etag')).toBeDefined()
Expand Down
Expand Up @@ -5,6 +5,7 @@ import {
nextBuild as _nextBuild,
nextStart as _nextStart,
} from 'next-test-utils'
import cheerio from 'cheerio'

const nodeArgs = ['-r', join(__dirname, '../../react-18/test/require-hook.js')]

Expand Down Expand Up @@ -44,3 +45,8 @@ export async function nextDev(dir, port) {
nodeArgs,
})
}

export function getNodeBySelector(html, selector) {
const $ = cheerio.load(html)
return $(selector)
}