Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/plugin-rsc/e2e/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@
const res = await page.request.get(f.url('/__test_restart'))
expect(await res.text()).toBe('ok')
await new Promise((r) => setTimeout(r, 100))
await page.goto(f.url('./'))

Check failure on line 631 in packages/plugin-rsc/e2e/basic.test.ts

View workflow job for this annotation

GitHub Actions / test-rsc (macos-latest / chromium)

[chromium] › e2e/basic.test.ts:627:5 › dev-isolated › no FOUC after server restart @nojs

6) [chromium] › e2e/basic.test.ts:627:5 › dev-isolated › no FOUC after server restart @nojs ────── Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:5173/ Call log: - navigating to "http://localhost:5173/", waiting until "load" 629 | expect(await res.text()).toBe('ok') 630 | await new Promise((r) => setTimeout(r, 100)) > 631 | await page.goto(f.url('./')) | ^ 632 | await testCss(page) 633 | await testTailwind(page) 634 | }) at /Users/runner/work/vite-plugin-react/vite-plugin-react/packages/plugin-rsc/e2e/basic.test.ts:631:18

Check failure on line 631 in packages/plugin-rsc/e2e/basic.test.ts

View workflow job for this annotation

GitHub Actions / test-rsc (macos-latest / chromium)

[chromium] › e2e/basic.test.ts:627:5 › dev-base › no FOUC after server restart @nojs

4) [chromium] › e2e/basic.test.ts:627:5 › dev-base › no FOUC after server restart @nojs ────────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:5173/ Call log: - navigating to "http://localhost:5173/", waiting until "load" 629 | expect(await res.text()).toBe('ok') 630 | await new Promise((r) => setTimeout(r, 100)) > 631 | await page.goto(f.url('./')) | ^ 632 | await testCss(page) 633 | await testTailwind(page) 634 | }) at /Users/runner/work/vite-plugin-react/vite-plugin-react/packages/plugin-rsc/e2e/basic.test.ts:631:18

Check failure on line 631 in packages/plugin-rsc/e2e/basic.test.ts

View workflow job for this annotation

GitHub Actions / test-rsc (macos-latest / chromium)

[chromium] › e2e/basic.test.ts:627:5 › dev-base › no FOUC after server restart @nojs

4) [chromium] › e2e/basic.test.ts:627:5 › dev-base › no FOUC after server restart @nojs ────────── Error: page.goto: net::ERR_CONNECTION_RESET at http://localhost:5173/ Call log: - navigating to "http://localhost:5173/", waiting until "load" 629 | expect(await res.text()).toBe('ok') 630 | await new Promise((r) => setTimeout(r, 100)) > 631 | await page.goto(f.url('./')) | ^ 632 | await testCss(page) 633 | await testTailwind(page) 634 | }) at /Users/runner/work/vite-plugin-react/vite-plugin-react/packages/plugin-rsc/e2e/basic.test.ts:631:18

Check failure on line 631 in packages/plugin-rsc/e2e/basic.test.ts

View workflow job for this annotation

GitHub Actions / test-rsc (macos-latest / chromium)

[chromium] › e2e/basic.test.ts:627:5 › dev-default › no FOUC after server restart @nojs

2) [chromium] › e2e/basic.test.ts:627:5 › dev-default › no FOUC after server restart @nojs ─────── Error: page.goto: net::ERR_EMPTY_RESPONSE at http://localhost:5174/ Call log: - navigating to "http://localhost:5174/", waiting until "load" 629 | expect(await res.text()).toBe('ok') 630 | await new Promise((r) => setTimeout(r, 100)) > 631 | await page.goto(f.url('./')) | ^ 632 | await testCss(page) 633 | await testTailwind(page) 634 | }) at /Users/runner/work/vite-plugin-react/vite-plugin-react/packages/plugin-rsc/e2e/basic.test.ts:631:18

Check failure on line 631 in packages/plugin-rsc/e2e/basic.test.ts

View workflow job for this annotation

GitHub Actions / test-rsc (macos-latest / webkit)

[webkit] › e2e/basic.test.ts:627:5 › dev-default › no FOUC after server restart @nojs

1) [webkit] › e2e/basic.test.ts:627:5 › dev-default › no FOUC after server restart @nojs ───────── Error: page.goto: Could not connect to the server. Call log: - navigating to "http://localhost:5175/", waiting until "load" 629 | expect(await res.text()).toBe('ok') 630 | await new Promise((r) => setTimeout(r, 100)) > 631 | await page.goto(f.url('./')) | ^ 632 | await testCss(page) 633 | await testTailwind(page) 634 | }) at /Users/runner/work/vite-plugin-react/vite-plugin-react/packages/plugin-rsc/e2e/basic.test.ts:631:18
await testCss(page)
await testTailwind(page)
})
Expand Down Expand Up @@ -952,4 +952,17 @@
await waitForHydration(page)
expect(errors).toEqual([])
})

test('browser only', async ({ page, browser }) => {
await page.goto(f.url())
await expect(page.getByTestId('test-browser-only')).toHaveText(
'test-browser-only: true',
)

const pageNoJs = await browser.newPage({ javaScriptEnabled: false })
await pageNoJs.goto(f.url())
await expect(pageNoJs.getByTestId('test-browser-only')).toHaveText(
'test-browser-only: loading...',
)
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function BrowserDep() {
return <>{String(!!window)}</>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use client'

import * as React from 'react'

const BrowserDep = (
import.meta.env.SSR ? undefined : React.lazy(() => import('./browser-dep'))
)!

export function TestBrowserOnly() {
return (
<div data-testid="test-browser-only">
test-browser-only:{' '}
<BrowserOnly fallback={<>loading...</>}>
<BrowserDep />
</BrowserOnly>
</div>
)
}

function BrowserOnly(props: React.SuspenseProps) {
const hydrated = useHydrated()
if (!hydrated) {
return props.fallback
}
return <React.Suspense {...props} />
}

const noopStore = () => () => {}

const useHydrated = () =>
React.useSyncExternalStore(
noopStore,
() => true,
() => false,
)

/*
If we were to implement this whole logic via hypothetical `browserOnly` helper with transform:

======= input ======

const SomeDep = browserOnly(() => import('./some-dep'))

======= output ======

const __TmpLazy = import.meta.env.SSR ? undefined : React.lazy(() => import('./some-dep'}));

const SomeDep = ({ browserOnlyFallback, ...props }) => {
const hydrated = useHydrated()
if (!hydrated) {
return browserOnlyFallback
}
return (
<React.Suspense fallback={browserOnlyFallback}>
<__TmpLazy {...props} />
</React.Suspense>
)
}

=== helper types ===

declare function browserOnly<T>(fn: () => Promise<{ default: React.ComponentType<T> }>):
React.ComponentType<T & { browserOnlyFallback?: React.ReactNode }>

*/
2 changes: 2 additions & 0 deletions packages/plugin-rsc/examples/basic/src/routes/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { TestTailwindServer } from './tailwind/server'
import { TestTemporaryReference } from './temporary-reference/client'
import { TestUseCache } from './use-cache/server'
import { TestHydrationMismatch } from './hydration-mismatch/server'
import { TestBrowserOnly } from './browser-only/client'

export function Root(props: { url: URL }) {
return (
Expand Down Expand Up @@ -67,6 +68,7 @@ export function Root(props: { url: URL }) {
<TestServerInClient />
<TestActionStateServer />
<TestModuleInvalidationServer />
<TestBrowserOnly />
<TestUseCache />
</body>
</html>
Expand Down
20 changes: 19 additions & 1 deletion packages/plugin-rsc/examples/basic/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import assert from 'node:assert'
import rsc, { transformHoistInlineDirective } from '@vitejs/plugin-rsc'
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
import { type Plugin, defineConfig, parseAstAsync } from 'vite'
import { type Plugin, defineConfig, normalizePath, parseAstAsync } from 'vite'
import inspect from 'vite-plugin-inspect'
import path from 'node:path'

// log unhandled rejection to debug e2e failures
if (!(globalThis as any).__debugHandlerRegisterd) {
Expand Down Expand Up @@ -96,6 +97,23 @@ export default defineConfig({
}
},
},
{
name: 'test-browser-only',
writeBundle(_options, bundle) {
const moduleIds = Object.values(bundle).flatMap((c) =>
c.type === 'chunk' ? [...c.moduleIds] : [],
)
const browserId = normalizePath(
path.resolve('src/routes/browser-only/browser-dep.tsx'),
)
if (this.environment.name === 'client') {
assert(moduleIds.includes(browserId))
}
if (this.environment.name === 'ssr') {
assert(!moduleIds.includes(browserId))
}
},
},
{
name: 'cf-build',
enforce: 'post',
Expand Down
Loading