diff --git a/packages/next/export/worker.ts b/packages/next/export/worker.ts index 08c3c14fcacd..265aed3cf1ee 100644 --- a/packages/next/export/worker.ts +++ b/packages/next/export/worker.ts @@ -2,7 +2,7 @@ import type { ComponentType } from 'react' import type { FontManifest } from '../server/font-utils' import type { GetStaticProps } from '../types' import type { IncomingMessage, ServerResponse } from 'http' -import type { NextConfigComplete } from '../server/config-shared' +import type { DomainLocale, NextConfigComplete } from '../server/config-shared' import type { NextParsedUrlQuery } from '../server/request-meta' import url from 'url' import { extname, join, dirname, sep } from 'path' @@ -23,6 +23,7 @@ import { isInAmpMode } from '../shared/lib/amp-mode' import { setHttpAgentOptions } from '../server/config' import RenderResult from '../server/render-result' import isError from '../lib/is-error' +import { addRequestMeta } from '../server/request-meta' const envConfig = require('../shared/lib/runtime-config') @@ -84,6 +85,7 @@ interface RenderOpts { locales?: string[] locale?: string defaultLocale?: string + domainLocales?: DomainLocale[] trailingSlash?: boolean appDir?: boolean } @@ -208,6 +210,18 @@ export default async function exportPage({ req.url += '/' } + if ( + locale && + buildExport && + renderOpts.domainLocales && + renderOpts.domainLocales.some( + (dl) => + dl.defaultLocale === locale || dl.locales?.includes(locale || '') + ) + ) { + addRequestMeta(req, '__nextIsLocaleDomain', true) + } + envConfig.setConfig({ serverRuntimeConfig, publicRuntimeConfig: renderOpts.runtimeConfig, diff --git a/test/integration/i18n-support/test/shared.js b/test/integration/i18n-support/test/shared.js index 34c48c021fe9..cfc69fdda8b1 100644 --- a/test/integration/i18n-support/test/shared.js +++ b/test/integration/i18n-support/test/shared.js @@ -407,6 +407,49 @@ export function runTests(ctx) { } }) + // The page is accessible on subpath as well as on the domain url without subpath. + // Once this is not the case the test will need to be changed to access it via domain. + // Beware of the different expectations on dev and prod version since the pre-rendering on dev does not work with domain locales + it('should prerender with the correct href for locale domain', async () => { + let browser = await webdriver(ctx.appPort, `${ctx.basePath || ''}/go`) + + for (const [element, pathname] of [ + ['#to-another', '/another'], + ['#to-gsp', '/gsp'], + ['#to-fallback-first', '/gsp/fallback/first'], + ['#to-fallback-hello', '/gsp/fallback/hello'], + ['#to-gssp', '/gssp'], + ['#to-gssp-slug', '/gssp/first'], + ]) { + const href = await browser.elementByCss(element).getAttribute('href') + if (ctx.isDev) { + expect(href).toBe(`${ctx.basePath || ''}/go${pathname}`) + } else { + expect(href).toBe(`https://example.com${ctx.basePath || ''}${pathname}`) + } + } + + browser = await webdriver(ctx.appPort, `${ctx.basePath || ''}/go-BE`) + + for (const [element, pathname] of [ + ['#to-another', '/another'], + ['#to-gsp', '/gsp'], + ['#to-fallback-first', '/gsp/fallback/first'], + ['#to-fallback-hello', '/gsp/fallback/hello'], + ['#to-gssp', '/gssp'], + ['#to-gssp-slug', '/gssp/first'], + ]) { + const href = await browser.elementByCss(element).getAttribute('href') + if (ctx.isDev) { + expect(href).toBe(`${ctx.basePath || ''}/go-BE${pathname}`) + } else { + expect(href).toBe( + `https://example.com${ctx.basePath || ''}/go-BE${pathname}` + ) + } + } + }) + it('should render the correct href with locale domains but not on a locale domain', async () => { let browser = await webdriver( ctx.appPort,