Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into pr/57-add_vike_react_…
Browse files Browse the repository at this point in the history
…zustand
  • Loading branch information
brillout committed May 6, 2024
2 parents ef15eb8 + ed1fdab commit 2666cd3
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 67 deletions.
2 changes: 2 additions & 0 deletions examples/full/.test-dev.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { testRun } from './.testRun'
testRun('pnpm run dev')
2 changes: 2 additions & 0 deletions examples/full/.test-preview.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { testRun } from './.testRun'
testRun('pnpm run preview')
126 changes: 76 additions & 50 deletions examples/full/.test.ts → examples/full/.testRun.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
export { testRun }

import { test, expect, run, fetchHtml, page, getServerUrl, autoRetry, partRegex } from '@brillout/test-e2e'

runTest()
let isProd: boolean

function testRun(cmd: `pnpm run ${'dev' | 'preview'}`) {
run(cmd)

function runTest() {
run('pnpm run dev')
isProd = cmd !== 'pnpm run dev'

const textLandingPage = 'Rendered to HTML.'
const title = 'My Vike + React App'
testUrl({
url: '/',
title,
text: textLandingPage,
text: 'Rendered to HTML.',
counter: true
})

Expand All @@ -34,63 +37,86 @@ function runTest() {
counter: true
})

{
const url = '/without-ssr'
const textNoSSR = 'This page is rendered only in the browser'
const text = textNoSSR
test(url + ' (HTML)', async () => {
const html = await fetchHtml(url)
// Isn't rendered to HTML
expect(html).toContain('<div id="react-root"></div>')
expect(html).not.toContain(text)
expect(getTitle(html)).toBe(title)
})
test(url + ' (Hydration)', async () => {
await page.goto(getServerUrl() + url)
await testCounter()
const body = await page.textContent('body')
expect(body).toContain(text)
})
test('Switch between SSR and non-SSR page', async () => {
let body: string | null
const t1 = textNoSSR
const t2 = textLandingPage

body = await page.textContent('body')
expect(body).toContain(t1)
expect(body).not.toContain(t2)
ensureWasClientSideRouted('/pages/without-ssr')

await page.click('a:has-text("Welcome")')
await testCounter()
body = await page.textContent('body')
expect(body).toContain(t2)
expect(body).not.toContain(t1)
ensureWasClientSideRouted('/pages/without-ssr')
const textNoSSR = 'This page is rendered only in the browser'
testUrl({
url: '/without-ssr',
title: 'No SSR',
text: textNoSSR,
counter: true,
noSSR: true
})

await page.click('a:has-text("Without SSR")')
await testCounter()
body = await page.textContent('body')
expect(body).toContain(t1)
expect(body).not.toContain(t2)
ensureWasClientSideRouted('/pages/without-ssr')
})
}
testNavigationBetweenWithSSRAndWithoutSSR()
}

function testUrl({ url, title, text, counter }: { url: string; title: string; text: string; counter?: true }) {
function testNavigationBetweenWithSSRAndWithoutSSR() {
const textWithSSR = 'Rendered to HTML.'
const textWithoutSSR = "It isn't rendered to HTML"

const url = '/without-ssr'
test(url + " isn't rendered to HTML", async () => {
const html = await fetchHtml(url)
expect(html).toContain('<div id="react-root"></div>')
expect(html).not.toContain(textWithoutSSR)
await page.goto(getServerUrl() + url)
await testCounter()
const body = await page.textContent('body')
expect(body).toContain(textWithoutSSR)
})

test('Switch between SSR and non-SSR page', async () => {
let body: string | null
const t1 = textWithoutSSR
const t2 = textWithSSR

body = await page.textContent('body')
expect(body).toContain(t1)
expect(body).not.toContain(t2)
ensureWasClientSideRouted('/pages/without-ssr')

await page.click('a:has-text("Welcome")')
await testCounter()
body = await page.textContent('body')
expect(body).toContain(t2)
expect(body).not.toContain(t1)
ensureWasClientSideRouted('/pages/without-ssr')

await page.click('a:has-text("Without SSR")')
await testCounter()
body = await page.textContent('body')
expect(body).toContain(t1)
expect(body).not.toContain(t2)
ensureWasClientSideRouted('/pages/without-ssr')
})
}

function testUrl({
url,
title,
text,
counter,
noSSR
}: { url: string; title: string; text: string; counter?: true; noSSR?: true }) {
test(url + ' (HTML)', async () => {
const html = await fetchHtml(url)
expect(html).toContain(text)
if (!noSSR) {
expect(html).toContain(text)
}
expect(getTitle(html)).toBe(title)
const hash = /[a-zA-Z0-9_-]+/
if (!isProd) {
expect(html).toMatch(partRegex`<link rel="icon" href="/assets/logo.svg"/>`)
} else {
expect(html).toMatch(partRegex`<link rel="icon" href="/assets/static/logo.${hash}.svg"/>`)
}
})
test(url + ' (Hydration)', async () => {
await page.goto(getServerUrl() + url)
const body = await page.textContent('body')
expect(body).toContain(text)
if (counter) {
await testCounter()
}
const body = await page.textContent('body')
expect(body).toContain(text)
})
}

Expand Down
2 changes: 1 addition & 1 deletion examples/full/pages/streaming/+Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function MovieList() {
const movies = useAsync(['star-wars-movies'], async () => {
const response = await fetch('https://star-wars.brillout.com/api/films.json')
// Simulate slow network
await new Promise((r) => setTimeout(r, 2 * 1000))
await new Promise((r) => setTimeout(r, 3 * 1000))
const movies: Movie[] = (await response.json()).results
return movies
})
Expand Down
3 changes: 2 additions & 1 deletion examples/full/pages/without-ssr/+config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import type { Config } from 'vike/types'

export default {
// https://vike.dev/ssr
ssr: false
ssr: false,
title: 'No SSR'
} satisfies Config
19 changes: 10 additions & 9 deletions packages/vike-react-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,37 @@
},
"scripts": {
"dev": "tsc --watch",
"build": "rm -rf dist/ && tsc",
"build": "rimraf dist/ && tsc",
"release": "release-me patch",
"release:minor": "release-me minor",
"release:commit": "release-me commit",
"test": "vitest run"
},
"peerDependencies": {
"@tanstack/react-query": "5.x.x",
"react": "18.x.x",
"react-dom": "18.x.x",
"react-streaming": "^0.3.19",
"vike": "^0.4.160",
"vike-react": "^0.4.4",
"react-streaming": "^0.3.19",
"vite": "^4.3.8 || ^5.0.10",
"@tanstack/react-query": "5.x.x"
"vite": "^4.3.8 || ^5.0.10"
},
"devDependencies": {
"@brillout/release-me": "^0.3.4",
"@tanstack/react-query": "^5.20.1",
"@testing-library/react": "^14.2.1",
"@types/node": "^20.11.17",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"jsdom": "^24.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-streaming": "^0.3.27",
"rimraf": "^5.0.5",
"typescript": "^5.3.3",
"vike": "^0.4.168",
"vike-react": "^0.4.8",
"react-streaming": "^0.3.27",
"vitest": "^1.2.2",
"@testing-library/react": "^14.2.1",
"jsdom": "^24.0.0",
"@tanstack/react-query": "^5.20.1"
"vitest": "^1.2.2"
},
"dependencies": {
"devalue": "^4.3.2",
Expand Down
3 changes: 2 additions & 1 deletion packages/vike-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"scripts": {
"dev": "tsc --watch",
"build": "rm -rf dist/ && tsc",
"build": "rimraf dist/ && tsc",
"release": "release-me patch",
"release:minor": "release-me minor",
"release:commit": "release-me commit"
Expand All @@ -34,6 +34,7 @@
"@types/react-dom": "^18.2.19",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rimraf": "^5.0.5",
"typescript": "^5.3.3",
"vike": "^0.4.168"
},
Expand Down
3 changes: 3 additions & 0 deletions packages/vike-react/src/+config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export default {
_streamIsRequied: {
env: { server: true }
},
onBeforeRenderClient: {
env: { client: true }
},
onAfterRenderClient: {
env: { client: true }
},
Expand Down
16 changes: 14 additions & 2 deletions packages/vike-react/src/renderer/onRenderClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { getPageElement } from './getPageElement.js'

let root: ReactDOM.Root
const onRenderClient: OnRenderClientSync = (pageContext): ReturnType<OnRenderClientSync> => {
// Use case:
// - Store hydration https://github.com/vikejs/vike-react/issues/110
pageContext.config.onBeforeRenderClient?.(pageContext)

const page = getPageElement(pageContext)

// TODO: implement this? So that, upon errors, onRenderClient() throws an error and Vike can render the error. As of April 2024 it isn't released yet.
Expand All @@ -16,8 +20,13 @@ const onRenderClient: OnRenderClientSync = (pageContext): ReturnType<OnRenderCli
const onUncaughtError = (_error: any, _errorInfo: any) => {}

const container = document.getElementById('react-root')!
if (container.innerHTML !== '' && pageContext.isHydration) {
// First render (hydration)
if (
// Whether the page was rendered to HTML. (I.e. whether the user set the [`ssr`](https://vike.dev/ssr) setting to `false`.)
container.innerHTML !== '' &&
// Whether the page was already rendered to HTML. (I.e. whether this is the first client-side rendering.)
pageContext.isHydration
) {
// Hydration
root = ReactDOM.hydrateRoot(container, page, {
// @ts-expect-error
onUncaughtError
Expand Down Expand Up @@ -48,6 +57,9 @@ const onRenderClient: OnRenderClientSync = (pageContext): ReturnType<OnRenderCli

pageContext.page = page
pageContext.root = root

// Use case:
// - Testing tool https://github.com/vikejs/vike-react/issues/95
pageContext.config.onAfterRenderClient?.(pageContext)
}

Expand Down
11 changes: 8 additions & 3 deletions packages/vike-react/src/types/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ declare global {
*
*/
lang?: string

/**
* If `true`, the page is rendered twice: on the server-side (to HTML) and on the client-side (hydration).
*
Expand All @@ -49,20 +50,24 @@ declare global {
* @default true
*
*/

ssr?: boolean

/**
* Whether to stream the page's HTML. Requires Server-Side Rendering (`ssr: true`).
*
* @default false
*
*/
stream?: boolean

/**
* Client-side hook called after the page is rendered.
* Client-side hook called before the page is rendered.
*/
onBeforeRenderClient?: (pageContext: PageContextClient) => void

// https://github.com/vikejs/vike-react/pull/96
/**
* Client-side hook called after the page is rendered.
*/
onAfterRenderClient?: (pageContext: PageContextClient) => void

// Temporary until Wrapper is cumulative
Expand Down
Loading

0 comments on commit 2666cd3

Please sign in to comment.