~repos /edge-city

#react#js#ssr

git clone https://pyrossh.dev/repos/edge-city.git

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


c121e198 Peter John

2 years ago
improve component
bun.lockb CHANGED
Binary file
components/Todo.astro DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- const { id, text } = Astro.props;
3
- const todos = [{ text: "123" }];
4
- ---
5
-
6
- <div>
7
- <p>
8
- {item.text}
9
- </p>
10
- </div>
11
-
12
- ---
13
- div {
14
- font-size: 20px;
15
- }
components/Todo.jsx ADDED
@@ -0,0 +1,9 @@
1
+ export default ({ id, text }) => {
2
+ return (
3
+ <div id={id}>
4
+ <p>
5
+ {text}
6
+ </p>
7
+ </div>
8
+ )
9
+ }
containers/TodoList.astro DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- const todos = [{ text: "123" }];
3
- ---
4
-
5
- <div className="todo-list">
6
- <h1>Todos</h1>
7
- <ul>
8
- {todos.map((item) => <li key={item.text}>{item.text}</li>)}
9
- </ul>
10
- </div>
containers/TodoList.jsx ADDED
@@ -0,0 +1,21 @@
1
+ import Todo from "@/components/Todo.jsx";
2
+
3
+ const todos = [
4
+ { id: '1', text: "123" },
5
+ { id: '2', text: "AEQ" }
6
+ ];
7
+
8
+ export default () => {
9
+ return (
10
+ <div className="todo-list">
11
+ <h1>Todos</h1>
12
+ <ul>
13
+ {todos.map((item) => (
14
+ <li key={item.text}>
15
+ <Todo id={item.id} text={item.text} />
16
+ </li>
17
+ ))}
18
+ </ul>
19
+ </div>
20
+ );
21
+ }
index.js CHANGED
@@ -1,17 +1,10 @@
1
- import './astroPlugin.js';
1
+ import './jsxPlugin.js';
2
2
  import path from 'path';
3
3
  import { SWRConfig } from 'swr';
4
4
  import { renderToReadableStream } from 'react-dom/server';
5
5
  import { RouterProvider } from './router.js';
6
6
  import packageJson from "./package.json";
7
7
 
8
- const router = new Bun.FileSystemRouter({
9
- style: "nextjs",
10
- dir: "./routes",
11
- origin: "https://mydomain.com",
12
- assetPrefix: "./public"
13
- });
14
-
15
8
  const transpiler = new Bun.Transpiler({
16
9
  loader: "jsx",
17
10
  autoImportJSX: true,
@@ -29,7 +22,6 @@ const deps = Object.keys(packageJson.dependencies).reduce((acc, dep) => {
29
22
  }, {})
30
23
 
31
24
  const renderPage = async (filePath, url, params) => {
32
- const file = path.basename(url.pathname).replace("astro", "js") + "index.js";
33
25
  const query = {};
34
26
  for (const key of url.searchParams.keys()) {
35
27
  query[key] = url.searchParams.get(key);
@@ -39,13 +31,13 @@ const renderPage = async (filePath, url, params) => {
39
31
  params: params,
40
32
  pathname: url.pathname,
41
33
  }
34
+ console.log('filePath', filePath);
42
35
  const routeImport = await import(filePath);
43
36
  const Page = routeImport.default;
44
37
  const stream = await renderToReadableStream(
45
38
  <html lang="en">
46
39
  <head>
47
- {/* {routeImport.head()} */}
48
- <link rel="stylesheet" href="/routes/index.css" />
40
+ <link rel="stylesheet" href="/pages/index.css" />
49
41
  <script id="initial_route_context" type='application/json' dangerouslySetInnerHTML={{
50
42
  __html: JSON.stringify(initialRouteValue)
51
43
  }} />
@@ -57,9 +49,9 @@ const renderPage = async (filePath, url, params) => {
57
49
  "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?dev",
58
50
  "react/jsx-dev-runtime": "https://esm.sh/react@18.2.0/jsx-dev-runtime?dev",
59
51
  "@/router.js": "/assets/js/src/router.js",
60
- "@/routes/index.js": "/routes/index.js",
52
+ "@/pages/index.jsx": "/pages/index.js",
61
- "@/components/Todo.astro": "/components/Todo.js",
53
+ "@/components/Todo.jsx": "/components/Todo.js",
62
- "@/containers/TodoList.astro": "/containers/TodoList.js"
54
+ "@/containers/TodoList.jsx": "/containers/TodoList.js"
63
55
  }
64
56
  }
65
57
  )
@@ -72,7 +64,7 @@ const renderPage = async (filePath, url, params) => {
72
64
  import { hydrateRoot } from 'react-dom/client';
73
65
  import { SWRConfig } from 'swr';
74
66
  import {RouterProvider} from "@/router.js";
75
- import Page from "@/routes/${file}";
67
+ import Page from "@/pages/index.jsx";
76
68
 
77
69
  const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
78
70
  const root = hydrateRoot(document.getElementById("root"), $jsx(SWRConfig, {
@@ -103,29 +95,6 @@ const renderPage = async (filePath, url, params) => {
103
95
  });
104
96
  }
105
97
 
106
- // const renderBootstrap = async (url) => {
107
- // const folder = path.dirname(url.pathname);
108
- // const file = path.basename(url.pathname).replace("astro", "js");
109
- // const result = await transpiler.transform(`
110
- // import { hydrateRoot } from 'react-dom/client';
111
- // import {RouterProvider} from "@/router.js";
112
- // import Page from "@/routes/${file}";
113
-
114
- // const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
115
- // const root = hydrateRoot(document.getElementById('root'), (
116
- // <RouterProvider value={initialRouteValue}>
117
- // <Page />
118
- // </RouterProvider>
119
- // ));
120
- // `);
121
- // return new Response(result, {
122
- // headers: {
123
- // 'Content-Type': 'application/javascript',
124
- // },
125
- // status: 200,
126
- // });
127
- // }
128
-
129
98
  const renderJs = async (url) => {
130
99
  const localFile = url.pathname.replace("/assets/js/", "").replace("src/", "");
131
100
  const src = await Bun.file(localFile).text();
@@ -158,7 +127,7 @@ export default {
158
127
  async fetch(req) {
159
128
  const url = new URL(req.url);
160
129
  console.log(req.method, url.pathname)
161
- if (url.pathname.includes("/components/") || url.pathname.includes("/containers/") || url.pathname.includes("/routes/")) {
130
+ if (url.pathname.includes("/components/") || url.pathname.includes("/containers/") || url.pathname.includes("/pages/")) {
162
131
  return sendFile(url);
163
132
  }
164
133
  if (url.pathname.includes("/assets/js")) {
@@ -173,7 +142,7 @@ export default {
173
142
  status: 404,
174
143
  });
175
144
  }
176
- return renderPage("./routes/index.astro", url, {});
145
+ return renderPage("./pages/index.jsx", url, {});
177
146
  // const route = router.match(url.pathname);
178
147
  // if (route) {
179
148
  // return renderPage(route, url);
index.test.js DELETED
@@ -1,11 +0,0 @@
1
- import { expect, test } from "bun:test";
2
-
3
- describe("arithmetic", () => {
4
- test("2 + 2", () => {
5
- expect(2 + 2).toBe(4);
6
- });
7
-
8
- test("2 * 2", () => {
9
- expect(2 * 2).toBe(4);
10
- });
11
- });
astroPlugin.js → jsxPlugin.js RENAMED
@@ -14,43 +14,30 @@ const transpiler = new Bun.Transpiler({
14
14
  });
15
15
 
16
16
  plugin({
17
- name: "Astro",
17
+ name: "JsxPlugin",
18
18
  async setup(build) {
19
- build.onLoad({ filter: /\.astro$/ }, async (args) => {
19
+ build.onLoad({ filter: /\.jsx$/ }, async (args) => {
20
20
  const folder = path.dirname(args.path).replace(process.cwd(), "");
21
- const filename = path.basename(args.path).replace("astro", "js");
21
+ const filename = path.basename(args.path).replace("jsx", "js");
22
+ const cssFile = args.path.replace("jsx", "css");
22
23
  const outputFolder = path.join(process.cwd(), ".cache", folder);
23
24
  const outputFile = path.join(outputFolder, filename);
24
- const text = readFileSync(args.path, "utf8");
25
+ const jsxCode = readFileSync(args.path, "utf8");
25
- const [_, js, html, css] = text.split("---");
26
- const imports = js.split("\n").filter((line) => line.startsWith("import")).join("\n");
27
- const body = js.split("\n").filter((line) => !line.startsWith("import")).join("\n");
28
- const tpl = `
29
- ${imports}
30
-
31
- export default () => {
32
- ${body}
33
-
34
- return (
35
- ${html}
36
- );
37
- }
38
- `;
39
- // console.log('tpl', tpl);
40
- const code = await transpiler.transform(tpl);
26
+ const code = await transpiler.transform(jsxCode);
41
27
  // console.log('code', code);
42
28
  if (!existsSync(outputFolder)) {
43
29
  mkdirSync(outputFolder);
44
30
  }
45
31
  writeFileSync(outputFile, code);
46
- if (css) {
32
+ if (existsSync(cssFile)) {
33
+ const cssText = readFileSync(cssFile, "utf-8");
47
34
  const result = postcss([
48
35
  autoprefixer(),
49
36
  postcssCustomMedia(),
50
37
  // postcssNormalize({ browsers: 'last 2 versions' }),
51
- postcssNesting(),
38
+ postcssNesting,
52
- ]).process(css, { from: 'src/app.css', to: 'dest/app.css' });
39
+ ]).process(cssText);
53
- writeFileSync(path.join(outputFolder, filename.replace("js", "css")), result.css);
40
+ writeFileSync(outputFile.replace("js", "css"), result.css);
54
41
  }
55
42
  const src = await import(outputFile);
56
43
  return {
package.json CHANGED
@@ -10,6 +10,7 @@
10
10
  "bun-types": "^0.5.0"
11
11
  },
12
12
  "dependencies": {
13
+ "@blueprintjs/core": "^4.17.6",
13
14
  "autoprefixer": "^10.4.14",
14
15
  "postcss": "^8.4.21",
15
16
  "postcss-custom-media": "^9.1.2",
pages/index.css ADDED
@@ -0,0 +1,11 @@
1
+ .home-page {
2
+ padding: 10px;
3
+ background-color: turquoise;
4
+
5
+ & .count {
6
+ color: black;
7
+ padding: 40px;
8
+ font-size: 30px;
9
+ font-weight: 600;
10
+ }
11
+ }
pages/index.jsx ADDED
@@ -0,0 +1,27 @@
1
+ import { useState } from "react";
2
+ import { useRouter } from "@/router.js";
3
+ import TodoList from "@/containers/TodoList.jsx";
4
+ // import "./index.css";
5
+
6
+ export default () => {
7
+ const router = useRouter();
8
+ const [count, setCount] = useState(5);
9
+ // const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
10
+ return (
11
+ <div className="home-page">
12
+ <div>
13
+ <p>
14
+ Hello from server path 123: {router.pathname}
15
+ </p>
16
+ <TodoList />
17
+ <div>
18
+ <button onClick={() => setCount(count - 1)}>-</button>
19
+ <span className="count">
20
+ {count}
21
+ </span>
22
+ <button onClick={() => setCount(count + 1)}>+</button>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ )
27
+ }
routes/index.astro DELETED
@@ -1,34 +0,0 @@
1
- import { useState } from "react";
2
- import { useRouter } from "@/router.js";
3
- import TodoList from "@/containers/TodoList.astro";
4
-
5
- const router = useRouter();
6
- const [count, setCount] = useState(5);
7
-
8
- return (
9
- <div>
10
- <div>
11
- <p>
12
- Hello from server path 123: {router.pathname}
13
- </p>
14
- <TodoList />
15
- <div>
16
- <button onClick={() => setCount(count - 1)}>-</button>
17
- <span>
18
- {count}
19
- </span>
20
- <button onClick={() => setCount(count + 1)}>+</button>
21
- </div>
22
- </div>
23
- </div>
24
- )
25
-
26
- ---
27
- div {
28
- padding: 10px;
29
- background-color: yellow;
30
-
31
- & span {
32
- color: black;
33
- }
34
- }
routes/index.css DELETED
@@ -1,11 +0,0 @@
1
- div {
2
- padding: 10px;
3
- background - color: turquoise;
4
-
5
- & span {
6
- color: black;
7
- padding: 40px;
8
- font - size: 30px;
9
- font - weight: 600;
10
- }
11
- }
routes/index.jsx DELETED
@@ -1,27 +0,0 @@
1
- import { useState } from "react";
2
- import { useRouter } from "@/router.js";
3
- import TodoList from "@/containers/TodoList.astro";
4
- import "index.css";
5
-
6
- const { name, title } = props;
7
- const router = useRouter();
8
- const [count, setCount] = useState(5);
9
- // const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
10
-
11
- return (
12
- <div className="container">
13
- <div>
14
- <p>
15
- Hello from server path 123: {router.pathname}
16
- </p>
17
- <TodoList />
18
- <div>
19
- <button onClick={() => setCount(count - 1)}>-</button>
20
- <span>
21
- {count}
22
- </span>
23
- <button onClick={() => setCount(count + 1)}>+</button>
24
- </div>
25
- </div>
26
- </div>
27
- );
routes/layout.astro DELETED
File without changes
routes/page.jsx DELETED
@@ -1,25 +0,0 @@
1
- <!--js-->
2
- import { useState } from "react";
3
- import { useRouter } from "@/router.js";
4
- import TodoList from "@/containers/TodoList.astro";
5
-
6
- const router = useRouter();
7
- const [count, setCount] = useState(5);
8
- // const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
9
-
10
- <!--jsx-->
11
- <div>
12
- <div>
13
- <p>
14
- Hello from server path 123: {router.pathname}
15
- </p>
16
- <TodoList />
17
- <div>
18
- <button onClick={() => setCount(count - 1)}>-</button>
19
- <span>
20
- {count}
21
- </span>
22
- <button onClick={() => setCount(count + 1)}>+</button>
23
- </div>
24
- </div>
25
- </div>