Repository navigation
[WIP] Rendering API React framework implementation #22504
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
Changes from all commits
0919e45
9ea2ec8
d984f8f
20d2f38
e503858
a63888e
39e7e55
0df21d7
f28670a
6cf46e6
95cacdc
eafc04c
bf99273
24b2929
41fbeac
bbfac70
db2960d
a7e9571
52c3e2e
a3d9147
99df2e0
29b6faa
208ac7f
8be4fb6
1ef578a
7afcc84
b4add53
dca3481
d54ffd8
ffeb21c
199781b
51e18d3
cae0673
9c5c4ed
2bd5d68
d56005b
1920a7c
0ba166e
b5c16dc
d4a9c7a
34cfdf0
56e9c92
2eb3362
1a0a081
2166f0c
93007de
8e659b2
704661e
1217e87
7339d18
99dd08b
894a654
ed4a887
bb19610
a64f073
3e798f1
28447ab
ecd2fed
d3bdc77
6338d55
ea78d56
d0da707
421a4f3
916d44f
c29c69b
f5122bd
f33a852
731f42c
e554c4e
ce560cd
e6aced6
da0b090
90e68fa
a47cbef
bcea163
b516eed
a8ff3f8
dab797b
b3f92b0
aea7b19
6556138
6e61206
363c4a5
53299d7
53208e2
f691ea1
101bcb1
921e357
0ac6b17
903ac7b
1a19be0
691e731
0919f23
11dc2fa
243f365
59b34ef
612d411
ac02036
36a414c
61b1ade
2701292
3a200e8
dbe15d3
361cd05
d8fa01e
7e89ca3
8b7bc0f
99a80a6
b17dccc
cda3eb5
9d67981
0b45b9c
3a23965
f145d8c
b0d3815
c07150d
cc84e27
2894e8d
247629a
fc6fdbe
5e256e4
1b01f7c
deb3e94
e92fd08
1e30570
f03a1ab
047eecc
bade403
c85ab52
43a7b65
f84f90c
bbaabed
a548ae7
58ecff4
166e961
e40238f
80c28b6
7282e92
da2be3f
5b4b99e
3b2bea9
457b4a4
bdf77f9
1a1091f
c93d8cf
5aa5906
c64dd68
0b0ffbf
c129d68
61519b3
85db756
67d2749
c1931c1
f65d89f
17fdb5b
f20b0ce
fa727b2
9270652
2ff068d
af3a1ff
7204820
4e62975
b257967
71a5f9f
0cc6325
11eddb2
891ea72
2d3223c
0971670
c2c2a16
2323011
4f0d2a5
2a7e2c9
a2689c0
799248b
1b3d0d5
16360c9
472e2d3
7227745
678843f
98b24f5
cdeb7bf
4cec2ec
3fca3b9
2474810
de999f7
cd800b0
7f96bf8
c62613e
756e590
dd9860f
8cd9b4e
ab579a3
49cfda1
243a237
b5a5fea
49a9dc7
971e467
daefbfb
1c6165e
d0fed20
661a246
e1ad16f
f43a175
8d8b037
1381de4
a17eb07
a873152
c534f0c
65e6609
b2353d6
4f21950
06cfe2e
3851137
cb14f70
62b296b
72b7956
fc9538b
69a76d4
f262e32
ceaab9e
6977b36
2153fe4
a6d3808
86af3dd
efb508e
2f02e4e
3ca89ab
cc78a1b
ff84564
31352bc
952436f
33537b6
a20a718
031f124
74f4fcf
c9b5ba1
dde1f9e
81999c2
fbd58db
da5bf73
329c793
5972cf2
7dfed6b
3cb6447
7aef153
4a4a377
ed1eb21
e306ac8
6e3ee65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| bun-framework-react*.tgz |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||
| <img src="https://bun.com/logo.png" height="36" /> | ||||||
|
|
||||||
| # `bun-framework-react` | ||||||
|
|
||||||
| An implementation of the Bun Rendering API for React, with RSC (React Server Components) | ||||||
|
|
||||||
| 1. `bun add bun-framework-react --dev` | ||||||
| 2. Make a `pages/index.tsx` file, with a page component defualt export | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typo in documentation. Line 8 contains a typo: "defualt" should be "default". Apply this diff to correct the typo: -2. Make a `pages/index.tsx` file, with a page component defualt export
+2. Make a `pages/index.tsx` file, with a page component default export📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| 3. Run `bun --app` | ||||||
| 4. Open [localhost:3000](https://localhost:3000) 🎉 | ||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,64 @@ | ||||||||||||||||||
| import { onServerSideReload } from "bun:app/client"; | ||||||||||||||||||
| import { hydrateRoot } from "react-dom/client"; | ||||||||||||||||||
| import { initialRscPayloadThen } from "./src/client/app.ts"; | ||||||||||||||||||
| import { router } from "./src/client/constants.ts"; | ||||||||||||||||||
| import { Root } from "./src/client/root.tsx"; | ||||||||||||||||||
|
|
||||||||||||||||||
| hydrateRoot(document, <Root />, { | ||||||||||||||||||
| onUncaughtError(e) { | ||||||||||||||||||
| console.error(e); | ||||||||||||||||||
| }, | ||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| const firstPageId = Date.now(); | ||||||||||||||||||
| { | ||||||||||||||||||
| history.replaceState(firstPageId, "", location.href); | ||||||||||||||||||
| initialRscPayloadThen(result => { | ||||||||||||||||||
| if (router.hasNavigatedSinceDOMContentLoaded()) return; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Collect the list of CSS files that were added from SSR | ||||||||||||||||||
| const links = document.querySelectorAll<HTMLLinkElement>("link[data-bake-ssr]"); | ||||||||||||||||||
| router.css.clear(); | ||||||||||||||||||
|
|
||||||||||||||||||
| for (let i = 0; i < links.length; i++) { | ||||||||||||||||||
| const link = links[i]; | ||||||||||||||||||
| if (!link) continue; | ||||||||||||||||||
| const href = new URL(link.href).pathname; | ||||||||||||||||||
| router.css.push(href); | ||||||||||||||||||
|
|
||||||||||||||||||
| // Hack: cannot add this to `cssFiles` because React owns the element, and | ||||||||||||||||||
| // it will be removed when any navigation is performed. | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| router.setCachedPage(firstPageId, { | ||||||||||||||||||
| css: [...router.css.getList()], | ||||||||||||||||||
| element: result, | ||||||||||||||||||
| }); | ||||||||||||||||||
| }); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (document.startViewTransition !== undefined) { | ||||||||||||||||||
| // View transitions are used by navigations to ensure that the page rerender | ||||||||||||||||||
| // all happens in one operation. Additionally, developers may animate | ||||||||||||||||||
| // different elements. The default fade animation is disabled so that the | ||||||||||||||||||
| // out-of-the-box experience feels like there are no view transitions. | ||||||||||||||||||
| // This is done client-side because a React error will unmount all elements. | ||||||||||||||||||
| const sheet = new CSSStyleSheet(); | ||||||||||||||||||
| document.adoptedStyleSheets.push(sheet); | ||||||||||||||||||
| sheet.replaceSync(":where(*)::view-transition-group(root){animation:none}"); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| window.addEventListener("popstate", async event => { | ||||||||||||||||||
| const state = typeof event.state === "number" ? event.state : undefined; | ||||||||||||||||||
| await router.navigate(location.href, state); | ||||||||||||||||||
| }); | ||||||||||||||||||
|
Comment on lines
+51
to
+54
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid unhandled rejections in popstate handler Event listeners ignore returned Promises. Catch navigation errors to prevent "Unhandled promise rejection" noise. -window.addEventListener("popstate", async event => {
- const state = typeof event.state === "number" ? event.state : undefined;
- await router.navigate(location.href, state);
-});
+window.addEventListener("popstate", event => {
+ const state = typeof event.state === "number" ? event.state : undefined;
+ void router.navigate(location.href, state).catch(console.error);
+});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| if (import.meta.env.DEV) { | ||||||||||||||||||
| // Frameworks can call `onServerSideReload` to hook into server-side hot | ||||||||||||||||||
| // module reloading. | ||||||||||||||||||
| onServerSideReload(async () => { | ||||||||||||||||||
| const newId = Date.now(); | ||||||||||||||||||
| history.replaceState(newId, "", location.href); | ||||||||||||||||||
| await router.navigate(location.href, newId); | ||||||||||||||||||
| }); | ||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import type { Framework } from "bun:app"; | ||
|
|
||
| function resolve(specifier: string) { | ||
| return Bun.fileURLToPath(import.meta.resolve(specifier)); | ||
| } | ||
|
|
||
| const framework: Framework = { | ||
| serverComponents: { | ||
| separateSSRGraph: true, | ||
| serverRuntimeImportSource: resolve("./vendor/react-server-dom-bun/server.node.js"), | ||
| }, | ||
| reactFastRefresh: { | ||
| importSource: resolve("react-refresh/runtime"), | ||
| }, | ||
| fileSystemRouterTypes: [ | ||
| { | ||
| root: "pages", | ||
| clientEntryPoint: resolve("./client.tsx"), | ||
| serverEntryPoint: resolve("./server.tsx"), | ||
| extensions: [".tsx", ".jsx"], | ||
| style: "nextjs-pages", | ||
| layouts: true, | ||
| ignoreUnderscores: true, | ||
| prefix: "/", | ||
| ignoreDirs: ["node_modules", ".git"], | ||
| }, | ||
| ], | ||
| // bundlerOptions: { | ||
| // ssr: { | ||
| // conditions: ["react-server"], | ||
| // }, | ||
| // }, | ||
| }; | ||
|
|
||
| export default framework; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| { | ||
| "name": "bun-framework-react", | ||
| "version": "0.0.0-canary.10", | ||
| "devDependencies": { | ||
| "@types/react": "^19.1.13", | ||
| "@types/react-dom": "^19.1.9" | ||
| }, | ||
| "exports": { | ||
| ".": "./index.ts", | ||
| "./package.json": "./package.json", | ||
| "./ssr.tsx": "./ssr.tsx", | ||
| "./server.tsx": "./server.tsx", | ||
| "./client.tsx": "./client.tsx", | ||
| "./*": "./src/components/*.tsx" | ||
| }, | ||
| "description": "React framework integration with RSC, for the Bun Rendering API", | ||
| "files": [ | ||
| "./vendor", | ||
| "./src", | ||
| "./*.ts", | ||
| "./*.tsx", | ||
| "./README.md" | ||
| ], | ||
| "keywords": [ | ||
| "bun", | ||
| "react", | ||
| "framework", | ||
| "bake" | ||
| ], | ||
| "type": "module", | ||
| "dependencies": { | ||
| "react": "0.0.0-experimental-a757cb76-20251002", | ||
| "react-dom": "0.0.0-experimental-a757cb76-20251002", | ||
| "react-refresh": "0.0.0-experimental-a757cb76-20251002" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add alt text to the image for accessibility.
The image is missing alternative text, which is important for accessibility and SEO.
Apply this diff to add descriptive alt text:
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
1-1: Images should have alternate text (alt text)
(MD045, no-alt-text)
🤖 Prompt for AI Agents