Skip to content

Commit 7b74198

Browse files
authored
feat(tiny-react/ssr): add renderToString and hydrate (#150)
1 parent 4dbec25 commit 7b74198

32 files changed

+1588
-32
lines changed

packages/tiny-react/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ Internal architecture is inspired by [yew](https://github.com/yewstack/yew) and
1010
- functional component
1111
- hooks
1212
- jsx-runtime (similar typescript DX as react)
13-
- HMR (via [`tiny-refresh`](https://github.com/hi-ogawa/js-utils/blob/a93f919c083c3ab0f505f1179124397c8f8f1b0d/packages/tiny-refresh/README.md))
13+
- hmr (via [`tiny-refresh`](https://github.com/hi-ogawa/js-utils/blob/a93f919c083c3ab0f505f1179124397c8f8f1b0d/packages/tiny-refresh/README.md))
14+
- ssr
1415

1516
## unsupported
1617

17-
- ssr https://github.com/hi-ogawa/js-utils/pull/150
1818
- context https://github.com/hi-ogawa/js-utils/pull/151
1919
- suspense
2020
- error boundary

packages/tiny-react/examples/basic/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html>
33
<head>
44
<meta charset="UTF-8" />
5-
<title>tiny-react</title>
5+
<title>tiny-react basic demo</title>
66
<meta
77
name="viewport"
88
content="width=device-width, height=device-height, initial-scale=1.0"

packages/tiny-react/examples/basic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "tiny-react-examples-jsx",
2+
"name": "tiny-react-examples-basic",
33
"private": true,
44
"scripts": {
55
"dev": "pnpm run /^dev:/",
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# tiny-react ssr demo
2+
3+
- https://tiny-react-ssr-hiro18181.vercel.app/
4+
5+
```sh
6+
pnpm dev
7+
8+
# preview local build
9+
pnpm build-preview
10+
pnpm preview
11+
12+
# deploy to vercel edge
13+
pnpm build
14+
pnpm release-production
15+
```
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { tinyassert } from "@hiogawa/utils";
2+
import { Page, expect, test } from "@playwright/test";
3+
4+
test("event listener", async ({ page }) => {
5+
await page.goto("/");
6+
await waitHydrated(page);
7+
8+
await page.getByRole("button", { name: "Hello!" }).click();
9+
await page.getByRole("button", { name: "World!" }).click();
10+
await page.getByRole("button", { name: "Hello!" }).click();
11+
});
12+
13+
test("url", async ({ page }) => {
14+
await page.goto("/");
15+
await waitHydrated(page);
16+
17+
await page.getByPlaceholder("?q=...").fill("hello");
18+
await page.waitForURL("/?q=hello");
19+
20+
await page.reload();
21+
await waitHydrated(page);
22+
await expect(page.getByPlaceholder("?q=...")).toHaveValue("hello");
23+
await page.waitForURL("/?q=hello");
24+
});
25+
26+
test("ssr", async ({ request }) => {
27+
{
28+
const res = await request.get("/");
29+
tinyassert(res.ok);
30+
31+
const text = await res.text();
32+
expect(text).toContain(
33+
`<input class="antd-input px-1" placeholder="?q=..." value=""/>`
34+
);
35+
}
36+
37+
{
38+
const res = await request.get("/?q=hello");
39+
tinyassert(res.ok);
40+
41+
const text = await res.text();
42+
expect(text).toContain(
43+
`<input class="antd-input px-1" placeholder="?q=..." value="hello"/>`
44+
);
45+
}
46+
});
47+
48+
async function waitHydrated(page: Page) {
49+
await page.getByTestId("hydrated").waitFor();
50+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>tiny-react ssr demo</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, height=device-height, initial-scale=1.0"
9+
/>
10+
<link
11+
rel="icon"
12+
type="image/svg+xml"
13+
href="https://iconify-dark-hiro18181.vercel.app/icon/ri/code-s-slash-line"
14+
/>
15+
<style>
16+
html,
17+
body,
18+
#root {
19+
height: 100%;
20+
}
21+
</style>
22+
</head>
23+
<body>
24+
<div id="root"><!--@INJECT_SSR@--></div>
25+
<script type="module" src="./src/client/index.tsx"></script>
26+
</body>
27+
</html>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# misc
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"runtime": "edge",
3+
"entrypoint": "index.js"
4+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# vercel
2+
3+
misc script for vercel deployment
4+
5+
```sh
6+
# initial project setup
7+
vercel projects add tiny-react-ssr-hiro18181
8+
vercel link -p tiny-react-ssr-hiro18181
9+
```
10+
11+
## references
12+
13+
- based on https://github.com/hi-ogawa/vite-plugins/blob/e3ddf3766bcf3fbd5325623acad1d46d8a71ea23/packages/demo/misc/vercel/README.md
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
set -eu -o pipefail
3+
4+
# https://vercel.com/docs/build-output-api/v3/primitives#edge-functions
5+
6+
# .vercel/
7+
# project.json
8+
# output/
9+
# config.json
10+
# static/
11+
# assets/ = dist/client/assets
12+
# functions/
13+
# index.func/
14+
# .vc-config.json
15+
# index.js = dist/server/index.js
16+
17+
this_dir="$(dirname "${BASH_SOURCE[0]}")"
18+
19+
# clean
20+
rm -rf .vercel/output
21+
mkdir -p .vercel/output
22+
23+
# config.json
24+
cp "$this_dir/config.json" .vercel/output/config.json
25+
26+
# static
27+
mkdir -p .vercel/output/static
28+
cp -r dist/client/assets .vercel/output/static/assets
29+
30+
# functions
31+
mkdir -p .vercel/output/functions/index.func
32+
cp "$this_dir/.vc-config.json" .vercel/output/functions/index.func/.vc-config.json
33+
npx esbuild dist/server/index.js \
34+
--outfile=.vercel/output/functions/index.func/index.js \
35+
--metafile=dist/server/esbuild-metafile.json \
36+
--bundle --minify --format=esm --platform=browser \
37+
--external:node:async_hooks

0 commit comments

Comments
 (0)