Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add react-server-dom-vite-example #79

Merged
merged 25 commits into from
Dec 19, 2024
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
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,22 @@ jobs:
- run: pnpm -C examples/react test-e2e
- run: pnpm -C examples/mpa test-e2e
- run: pnpm -C examples/ssr test-e2e

react-server-dom-vite:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./react-server-dom-vite-example
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: corepack enable
- run: pnpm i
- run: pnpm lint-check
- run: pnpm tsc
- run: pnpm exec playwright install chromium
- run: pnpm test-e2e
- run: pnpm build
- run: pnpm test-e2e-preview
4 changes: 4 additions & 0 deletions react-server-dom-vite-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
test-results
*.tsbuildinfo
16 changes: 16 additions & 0 deletions react-server-dom-vite-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Bare minimal example of `react-server-dom-vite` https://github.com/facebook/react/pull/31768

## implemented

- client component
- server action
- browser hmr
- server hmr

## to be improved

- "use client" transform
- "use server" transform
- normalize reference id
- css on server
- ...
9 changes: 9 additions & 0 deletions react-server-dom-vite-example/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"linter": { "enabled": false }
}
93 changes: 93 additions & 0 deletions react-server-dom-vite-example/e2e/basic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { type Page, test } from "@playwright/test";
import { createEditor } from "./helper";

test("client reference", async ({ page }) => {
await page.goto("/");
await page.getByText("[hydrated: 1]").click();
await page.getByText("Client counter: 0").click();
await page
.getByTestId("client-counter")
.getByRole("button", { name: "+" })
.click();
await page.getByText("Client counter: 1").click();
await page.reload();
await page.getByText("Client counter: 0").click();
});

test("server reference @js", async ({ page }) => {
await testServerAction(page);
});

test.describe(() => {
test.use({ javaScriptEnabled: false });
test("server reference @nojs", async ({ page }) => {
await testServerAction(page);
});
});

async function testServerAction(page: Page) {
await page.goto("/");
await page.getByText("Server counter: 0").click();
await page
.getByTestId("server-counter")
.getByRole("button", { name: "+" })
.click();
await page.getByText("Server counter: 1").click();
await page.goto("/");
await page.getByText("Server counter: 1").click();
await page
.getByTestId("server-counter")
.getByRole("button", { name: "-" })
.click();
await page.getByText("Server counter: 0").click();
}

test("client hmr @dev", async ({ page }) => {
await page.goto("/");
await page.getByText("[hydrated: 1]").click();
// client +1
await page.getByText("Client counter: 0").click();
await page
.getByTestId("client-counter")
.getByRole("button", { name: "+" })
.click();
await page.getByText("Client counter: 1").click();
// edit client
using file = createEditor("src/app/client.tsx");
file.edit((s) => s.replace("Client counter", "Client [EDIT] counter"));
await page.getByText("Client [EDIT] counter: 1").click();
});

test("server hmr @dev", async ({ page }) => {
await page.goto("/");
await page.getByText("[hydrated: 1]").click();

// server +1
await page.getByText("Server counter: 0").click();
await page
.getByTestId("server-counter")
.getByRole("button", { name: "+" })
.click();
await page.getByText("Server counter: 1").click();

// client +1
await page.getByText("Client counter: 0").click();
await page
.getByTestId("client-counter")
.getByRole("button", { name: "+" })
.click();
await page.getByText("Client counter: 1").click();

// edit server
using file = createEditor("src/app/index.tsx");
file.edit((s) => s.replace("Server counter", "Server [EDIT] counter"));
await page.getByText("Server [EDIT] counter: 1").click();
await page.getByText("Client counter: 1").click();

// server -1
await page
.getByTestId("server-counter")
.getByRole("button", { name: "-" })
.click();
await page.getByText("Server [EDIT] counter: 0").click();
});
15 changes: 15 additions & 0 deletions react-server-dom-vite-example/e2e/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import fs from "node:fs";

export function createEditor(filepath: string) {
let init = fs.readFileSync(filepath, "utf-8");
let data = init;
return {
edit(editFn: (data: string) => string) {
data = editFn(data);
fs.writeFileSync(filepath, data);
},
[Symbol.dispose]() {
fs.writeFileSync(filepath, init);
},
};
}
30 changes: 30 additions & 0 deletions react-server-dom-vite-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build --app",
"preview": "vite preview",
"tsc": "tsc -b",
"test-e2e": "playwright test",
"test-e2e-preview": "E2E_PREVIEW=1 playwright test",
"lint": "biome check --write .",
"lint-check": "biome check ."
},
"dependencies": {
"@jacob-ebey/react-server-dom-vite": "19.0.0-experimental.14",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@playwright/test": "^1.49.1",
"@types/node": "^22.10.2",
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.1",
"@vitejs/plugin-react": "^4.3.4",
"typescript": "^5.7.2",
"vite": "6.0.3"
},
"packageManager": "[email protected]+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c"
}
32 changes: 32 additions & 0 deletions react-server-dom-vite-example/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { defineConfig, devices } from "@playwright/test";

const port = Number(process.env.E2E_PORT || 6174);
const isPreview = Boolean(process.env.E2E_PREVIEW);
const command = isPreview
? `pnpm preview --port ${port} --strict-port`
: `pnpm dev --port ${port} --strict-port`;

export default defineConfig({
testDir: "e2e",
use: {
trace: "on-first-retry",
},
projects: [
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
viewport: null,
deviceScaleFactor: undefined,
},
},
],
webServer: {
command,
port,
},
grepInvert: isPreview ? /@dev/ : /@build/,
forbidOnly: !!process.env["CI"],
retries: process.env["CI"] ? 2 : 0,
reporter: "list",
});
Loading
Loading