fix(web): keep marketplace route layout on the server

A client marketplace layout wrapping the async page makes Flight
double-resolve streamed children (`reason.enqueueModel`) on
cloud.dify.dev/marketplace.
This commit is contained in:
CodingOnStar 2026-08-18 14:34:12 +08:00
parent 803d5d3fe5
commit cde9aa5237
3 changed files with 55 additions and 8 deletions

View File

@ -0,0 +1,33 @@
import { readFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
vi.mock('../document-title', () => ({
default: () => <span>marketplace document title</span>,
}))
describe('marketplace route layout', () => {
it('stays a server module so Flight can stream the async marketplace page', () => {
const source = readFileSync(
resolve(dirname(fileURLToPath(import.meta.url)), '../layout.tsx'),
'utf8',
)
expect(source).not.toMatch(/^['"]use client['"]/)
})
it('renders marketplace children and the document title island', async () => {
const { default: MarketplaceLayout } = await import('../layout')
render(
<MarketplaceLayout>
<p>marketplace page</p>
</MarketplaceLayout>,
)
expect(screen.getByText('marketplace document title')).toBeInTheDocument()
expect(screen.getByText('marketplace page')).toBeInTheDocument()
})
})

View File

@ -0,0 +1,12 @@
'use client'
import { useTranslation } from 'react-i18next'
import useDocumentTitle from '@/hooks/use-document-title'
const MarketplaceDocumentTitle = () => {
const { t } = useTranslation()
useDocumentTitle(t(($) => $['mainNav.marketplace'], { ns: 'common' }))
return null
}
export default MarketplaceDocumentTitle

View File

@ -1,12 +1,14 @@
'use client'
import type { PropsWithChildren } from 'react'
import { useTranslation } from 'react-i18next'
import useDocumentTitle from '@/hooks/use-document-title'
import MarketplaceDocumentTitle from './document-title'
// This route layout must stay a Server Component. A client layout wrapping the
// async marketplace page makes Flight double-resolve streamed children
// (`reason.enqueueModel`) when opening /marketplace from cloud.dify.dev.
export default function MarketplaceLayout({ children }: PropsWithChildren) {
const { t } = useTranslation()
useDocumentTitle(t(($) => $['mainNav.marketplace'], { ns: 'common' }))
return children
return (
<>
<MarketplaceDocumentTitle />
{children}
</>
)
}