diff --git a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts index 26ddc3dfdf75..8990e3ba503f 100644 --- a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts +++ b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts @@ -12,7 +12,6 @@ export default async function middlewareSSRLoader(this: any) { absoluteErrorPath, isServerComponent, stringifiedConfig, - ...restRenderOpts } = this.getOptions() const stringifiedAbsolutePagePath = stringifyRequest(this, absolutePagePath) @@ -59,6 +58,7 @@ export default async function middlewareSSRLoader(this: any) { getServerSideProps: pageMod.getServerSideProps, getStaticPaths: pageMod.getStaticPaths, ComponentMod: undefined, + serverComponentManifest: ${isServerComponent} ? rscManifest : null, // components errorMod, @@ -73,16 +73,9 @@ export default async function middlewareSSRLoader(this: any) { } const render = getRender({ - App, Document, - pageMod, - errorMod, - buildManifest, - reactLoadableManifest, - rscManifest, isServerComponent: ${isServerComponent}, config: ${stringifiedConfig}, - restRenderOpts: ${JSON.stringify(restRenderOpts)} }) export default function rscMiddleware(opts) { diff --git a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts index 8358264d1508..5211140af551 100644 --- a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts +++ b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts @@ -12,9 +12,6 @@ const createHeaders = (args?: any) => ({ 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', }) -// const encoder = new TextEncoder() -// const decoder = new TextDecoder() - function sendError(req: any, error: Error) { const defaultMessage = 'An error occurred while rendering ' + req.url + '.' return new Response((error && error.message) || defaultMessage, { @@ -24,26 +21,12 @@ function sendError(req: any, error: Error) { } export function getRender({ - App, Document, - pageMod, - errorMod, - rscManifest, - buildManifest, - reactLoadableManifest, isServerComponent, - restRenderOpts, config, }: { - App: any Document: any - pageMod: any - errorMod: any - rscManifest: object - buildManifest: any - reactLoadableManifest: any isServerComponent: boolean - restRenderOpts: any config: NextConfig }) { // Used by `path-browserify`. @@ -88,14 +71,10 @@ export function getRender({ ? JSON.parse(query.__props__) : undefined - delete query.__flight__ - delete query.__props__ - // Extend the options. Object.assign((self as any).__server_context, { renderServerComponentData, serverComponentProps, - serverComponentManifest: isServerComponent ? rscManifest : null, }) const extendedReq = new WebNextRequest(request) @@ -103,89 +82,5 @@ export function getRender({ const extendedRes = new WebNextResponse(transformStream) requestHandler(extendedReq, extendedRes) return await extendedRes.toResponse() - - // const renderOpts = { - // ...restRenderOpts, - // // Locales are not supported yet. - // // locales: i18n?.locales, - // // locale: detectedLocale, - // // defaultLocale, - // // domainLocales: i18n?.domains, - // dev: process.env.NODE_ENV !== 'production', - // App, - // Document, - // buildManifest, - // Component: pageMod.default, - // pageConfig: pageMod.config || {}, - // getStaticProps: pageMod.getStaticProps, - // getServerSideProps: pageMod.getServerSideProps, - // getStaticPaths: pageMod.getStaticPaths, - // reactLoadableManifest, - // env: process.env, - // supportsDynamicHTML: true, - // concurrentFeatures: true, - // // When streaming, opt-out the `defer` behavior for script tags. - // disableOptimizedLoading: true, - // renderServerComponentData, - // serverComponentProps, - // serverComponentManifest: isServerComponent ? rscManifest : null, - // ComponentMod: null, - // } - - // const transformStream = new TransformStream() - // const writer = transformStream.writable.getWriter() - - // let result: RenderResult | null - // let renderError: any - // try { - // result = await renderToHTML( - // req as any, - // {} as any, - // pathname, - // query, - // renderOpts - // ) - // } catch (err: any) { - // console.error( - // 'An error occurred while rendering the initial result:', - // err - // ) - // const errorRes = { statusCode: 500, err } - // renderError = err - // try { - // req.url = '/_error' - // result = await renderToHTML( - // req as any, - // errorRes as any, - // '/_error', - // query, - // { - // ...renderOpts, - // err, - // Component: errorMod.default, - // getStaticProps: errorMod.getStaticProps, - // getServerSideProps: errorMod.getServerSideProps, - // getStaticPaths: errorMod.getStaticPaths, - // } - // ) - // } catch (err2: any) { - // return sendError(req, err2) - // } - // } - - // if (!result) { - // return sendError(req, new Error('No result returned from render.')) - // } - - // result.pipe({ - // write: (str: string) => writer.write(encoder.encode(str)), - // end: () => writer.close(), - // // Not implemented: cork/uncork/on/removeListener - // } as any) - - // return new Response(transformStream.readable, { - // headers: createHeaders(), - // status: renderError ? 500 : 200, - // }) } } diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 2bc4f542e638..d57359c100f5 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -597,10 +597,6 @@ export default abstract class Server { // Backwards compatibility protected async close(): Promise {} - protected setImmutableAssetCacheControl(res: BaseNextResponse): void { - res.setHeader('Cache-Control', 'public, max-age=31536000, immutable') - } - protected getCustomRoutes(): CustomRoutes { const customRoutes = this.getRoutesManifest() let rewrites: CustomRoutes['rewrites'] diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 986b9b71447e..5f4e027f31d1 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -200,6 +200,10 @@ export default class NextNodeServer extends BaseServer { : [] } + protected setImmutableAssetCacheControl(res: BaseNextResponse): void { + res.setHeader('Cache-Control', 'public, max-age=31536000, immutable') + } + protected generateFsStaticRoutes(): Route[] { return [ { diff --git a/packages/next/server/web-server.ts b/packages/next/server/web-server.ts index 651e3efe7e39..e4f7fc99f522 100644 --- a/packages/next/server/web-server.ts +++ b/packages/next/server/web-server.ts @@ -140,6 +140,13 @@ export default class NextWebServer extends BaseServer { end: () => writer.close(), // Not implemented: cork/uncork/on/removeListener } as any) + + // To prevent Safari's bfcache caching the "shell", we have to add the + // `no-cache` header to document responses. + res.setHeader( + 'Cache-Control', + 'no-cache, no-store, max-age=0, must-revalidate' + ) res.send() } protected async runApi() { diff --git a/test/integration/react-streaming-and-server-components/test/index.test.js b/test/integration/react-streaming-and-server-components/test/index.test.js index 7378fa040df2..dfb68408db28 100644 --- a/test/integration/react-streaming-and-server-components/test/index.test.js +++ b/test/integration/react-streaming-and-server-components/test/index.test.js @@ -355,7 +355,7 @@ async function runBasicTests(context, env) { expect(pathNotFoundHTML).toContain(page404Content) }) - it('should disable cache for RSC pages', async () => { + it('should disable cache for fizz pages', async () => { const urls = ['/', '/next-api/image', '/next-api/link'] await Promise.all( urls.map(async (url) => { @@ -375,16 +375,21 @@ async function runBasicTests(context, env) { expect(linkText).toContain('go home') const browser = await webdriver(context.appPort, '/next-api/link') + + // We need to make sure the app is fully hydrated before clicking, otherwise + // it will be a full redirection instead of being taken over by the next + // router. This timeout prevents it being flaky caused by fast refresh's + // rebuilding event. + await new Promise((res) => setTimeout(res, 1000)) await browser.eval('window.beforeNav = 1') + await browser.waitForElementByCss('#next_id').click() await check(() => browser.elementByCss('#query').text(), 'query:1') await browser.waitForElementByCss('#next_id').click() await check(() => browser.elementByCss('#query').text(), 'query:2') - if (!isDev) { - expect(await browser.eval('window.beforeNav')).toBe(1) - } + expect(await browser.eval('window.beforeNav')).toBe(1) }) it('should suspense next/image on server side', async () => {