~repos /edge-city

#react#js#ssr

git clone https://pyrossh.dev/repos/edge-city.git
Discussions: https://groups.google.com/g/rust-embed-devs

edge-city is a next level meta-framework for react that runs only on edge runtimes


7d46866a pyrossh

HEAD -> main

2 years ago
update app
example/src/components/Counter/Counter.jsx CHANGED
@@ -8,11 +8,11 @@ const Counter = () => {
8
8
  const decrement = () => setCount(count + 1);
9
9
  return (
10
10
  <div className="counter">
11
- <Button onClick={increment}>
11
+ <Button onPress={increment}>
12
12
  -
13
13
  </Button>
14
14
  <span className="count">{count}</span>
15
- <Button onClick={decrement}>
15
+ <Button onPress={decrement}>
16
16
  +
17
17
  </Button>
18
18
  </div>
example/src/pages/app.jsx CHANGED
@@ -1,15 +1,23 @@
1
+ import { Suspense } from "react";
1
2
  import { SSRProvider } from "react-aria";
3
+ import { HelmetProvider } from 'react-helmet-async';
4
+ import { usePage } from "edge-city/router";
2
5
  import Layout from "@/components/Layout/Layout";
3
6
  import "./normalize.css";
4
7
  import "./spectrum.css";
5
8
  import "./app.css";
6
9
 
7
- export default function App({ children }) {
10
+ export default function App({ helmetContext }) {
11
+ const Page = usePage();
8
12
  return (
13
+ <HelmetProvider context={helmetContext}>
9
- <SSRProvider>
14
+ <SSRProvider>
10
- <Layout>
15
+ <Layout>
16
+ <Suspense fallback={<p>Routing....</p>}>
11
- {children}
17
+ <Page />
18
+ </Suspense>
12
- </Layout>
19
+ </Layout>
13
- </SSRProvider>
20
+ </SSRProvider>
21
+ </HelmetProvider>
14
22
  );
15
23
  }
lib/bin/cli.js CHANGED
@@ -156,7 +156,7 @@ const bundlePages = async () => {
156
156
  build.onLoad({ filter: /\\*.page.jsx/, namespace: undefined }, (args) => {
157
157
  const data = fs.readFileSync(args.path);
158
158
  const newSrc = `
159
- import hydratePage from "edge-city/client/hydratePage";
159
+ import hydratePage from "edge-city/hydratePage";
160
160
  ${importAppComp}
161
161
 
162
162
  ${data.toString()}
lib/{client/hydratePage.js → hydratePage.js} RENAMED
@@ -3,7 +3,7 @@ import { hydrateRoot } from "react-dom/client";
3
3
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
4
  import { createBrowserHistory } from "history";
5
5
  import { createRouter } from "radix3";
6
- import { RouterProvider } from "../router";
6
+ import { state } from "./router";
7
7
  import routemap from '/routemap.json' assert {type: 'json'};
8
8
 
9
9
  const hydratePage = (App) => {
@@ -15,13 +15,13 @@ const hydratePage = (App) => {
15
15
  return acc;
16
16
  }, {}),
17
17
  });
18
- const root = document.getElementById("root");
19
- hydrateRoot(root, _jsx(RouterProvider, {
20
- history,
18
+ state.set({
21
19
  router,
22
- rpcContext: window._EDGE_DATA_ || {},
20
+ history,
23
21
  helmetContext: {},
24
- App,
25
- }));
22
+ })
23
+ const root = document.getElementById("root");
24
+ hydrateRoot(root, _jsx(App, { helmetContext: {} }));
26
25
  }
26
+
27
27
  export default hydratePage;
lib/index.js DELETED
@@ -1,29 +0,0 @@
1
- import React from "react";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { createBrowserHistory } from "history";
4
- import { createRouter } from "radix3";
5
- import routemap from '/routemap.json' assert {type: 'json'};
6
-
7
- export const isProd = () => process.env.NODE_ENV === "production";
8
- export const hydrateApp = async (App) => {
9
- if (!isProd()) {
10
- console.log("hydrating with", window._EDGE_DATA_);
11
- }
12
- const module = await import("react-dom/client");
13
- const history = createBrowserHistory();
14
- const router = createRouter({
15
- strictTrailingSlash: true,
16
- routes: Object.keys(routemap).reduce((acc, r) => {
17
- acc[r] = React.lazy(() => import(routemap[r]));
18
- return acc;
19
- }, {}),
20
- });
21
- const root = document.getElementById("root");
22
- module.default.hydrateRoot(root, _jsx(RouterProvider, {
23
- history,
24
- router,
25
- rpcContext: window._EDGE_DATA_ || {},
26
- helmetContext: {},
27
- App,
28
- }));
29
- }
lib/index.test.js DELETED
@@ -1,15 +0,0 @@
1
- describe('A thing', () => {
2
- it('should work', () => {
3
- expect(1).toEqual(1);
4
- });
5
-
6
- it('should be ok', () => {
7
- expect(1).toEqual(1);
8
- });
9
-
10
- describe('a nested thing', () => {
11
- it('should work', () => {
12
- expect(1).toEqual(1);
13
- });
14
- });
15
- });
lib/link.js CHANGED
@@ -20,7 +20,7 @@ const Link = (props) => {
20
20
  })
21
21
  }
22
22
 
23
- export const NavLink = ({ children, className, activeClassName, ...props }) => {
23
+ export const StyleLink = ({ children, className, activeClassName, ...props }) => {
24
24
  const { pathname } = useRouter();
25
25
  const classNames = pathname === props.href ? [activeClassName, className] : [className];
26
26
  return _jsx(Link, {
lib/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "edge-city",
3
3
  "version": "0.5.0",
4
4
  "type": "module",
5
- "main": "index.js",
5
+ "main": "client",
6
6
  "engines": {
7
7
  "node": ">= 20"
8
8
  },
lib/router.js CHANGED
@@ -1,14 +1,20 @@
1
1
  import {
2
- Suspense, createContext, useContext, useState, useEffect, useTransition, useCallback
2
+ useState, useEffect, useTransition
3
3
  } from "react";
4
4
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
5
- import { HelmetProvider } from 'react-helmet-async';
6
5
 
6
+ export let state = {
7
+ get: () => globalThis._EDGE_ROUTER_STATE_,
8
+ set: (v) => {
9
+ globalThis._EDGE_ROUTER_STATE_ = v;
10
+ },
11
+ }
12
+
7
- export const RouterContext = createContext(undefined);
13
+ export const usePage = () => {
8
- export const RouterProvider = ({ router, history, helmetContext, App }) => {
14
+ const { history, router } = state.get();
9
15
  const [_, startTransition] = useTransition();
10
16
  const [pathname, setPathname] = useState(history.location.pathname);
11
- const page = router.lookup(pathname) || router.lookup("/_404");
17
+ const Page = router.lookup(pathname) || router.lookup("/_404");
12
18
  useEffect(() => {
13
19
  return history.listen(({ location }) => {
14
20
  // this causes 2 renders to happen but stops jitter or flash due to React.lazy
@@ -17,25 +23,11 @@ export const RouterProvider = ({ router, history, helmetContext, App }) => {
17
23
  })
18
24
  });
19
25
  }, []);
20
- return _jsx(RouterContext.Provider, {
21
- value: {
26
+ return Page;
22
- history,
23
- params: page.params || {},
24
- },
25
- children: _jsx(Suspense, {
26
- fallback: _jsx("div", {}, "Routing...."),
27
- children: _jsx(HelmetProvider, {
28
- context: helmetContext,
29
- children: _jsx(App, {
30
- children: _jsx(page, {}),
31
- })
32
- }),
33
- }),
34
- })
35
27
  }
36
28
 
37
29
  export const useRouter = () => {
38
- const { history, params } = useContext(RouterContext);
30
+ const { history, params } = state.get();
39
31
  return {
40
32
  pathname: history.location.pathname,
41
33
  query: new URLSearchParams(history.location.search),
lib/server/renderPage.js CHANGED
@@ -5,7 +5,7 @@ import { createRouter } from "radix3";
5
5
  import { renderToReadableStream } from "react-dom/server";
6
6
  import isbot from "isbot";
7
7
  import routemap from '/routemap.json' assert {type: 'json'};
8
- import { RouterProvider } from "../router";
8
+ import { state } from "../router";
9
9
 
10
10
  const stringToStream = (str) => {
11
11
  return new ReadableStream({
@@ -116,6 +116,11 @@ const renderPage = async (Page, App, req) => {
116
116
  const jsScript = url.pathname === "/" ? "/index" : url.pathname;
117
117
  const helmetContext = {};
118
118
  globalThis._EDGE_DATA_ = { data: {}, subs: {} };
119
+ state.set({
120
+ router,
121
+ history,
122
+ helmetContext,
123
+ })
119
124
  const stream = await render(
120
125
  _jsxs("html", {
121
126
  lang: "en",
@@ -129,16 +134,9 @@ const renderPage = async (Page, App, req) => {
129
134
  ]
130
135
  }),
131
136
  _jsx("body", {
132
- children: _jsxs("div", {
137
+ children: _jsx("div", {
133
138
  id: "root",
134
- children: [
135
- _jsx(RouterProvider, {
136
- history,
137
- router,
138
- helmetContext,
139
+ children: _jsx(App, { helmetContext }),
139
- App,
140
- }),
141
- ]
142
140
  })
143
141
  })]
144
142
  }), {