~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


072de503 pyrossh

2 years ago
use fse
cli.js CHANGED
@@ -4,6 +4,7 @@ import { hideBin } from 'yargs/helpers'
4
4
  import esbuild from 'esbuild';
5
5
  import resolve from 'esbuild-plugin-resolve';
6
6
  import fs from "fs";
7
+ import fse from "fs-extra";
7
8
  import path from 'path';
8
9
  import walkdir from 'walkdir';
9
10
  import postcss from "postcss"
@@ -14,7 +15,8 @@ import bytes from 'bytes';
14
15
  import pc from 'picocolors';
15
16
  import ms from 'ms';
16
17
 
18
+ let isProd = false;
17
- const isProd = process.env.NODE_ENV === "production";
19
+ const inputStaticDir = path.join(process.cwd(), "static");
18
20
  const buildDir = path.join(process.cwd(), "build");
19
21
  const staticDir = path.join(buildDir, "static");
20
22
 
@@ -50,6 +52,8 @@ const bundleJs = async ({ entryPoints, outfile, ...options }, plg) => {
50
52
  plugins: [
51
53
  resolve({
52
54
  "/routemap.json": `${staticDir}/routemap.json`,
55
+ "@/_404/page": `${process.cwd()}/pages/_404/page.jsx`,
56
+ "@/_500/page": `${process.cwd()}/pages/_500/page.jsx`,
53
57
  }),
54
58
  plg,
55
59
  ]
@@ -87,6 +91,9 @@ const bundlePages = async () => {
87
91
  const data = fs.readFileSync(args.path);
88
92
  const newSrc = `
89
93
  import { renderPage } from "edge-city";
94
+ import NotFoundPage from "@/_404/page";
95
+ import ErrorPage from "@/_500/page";
96
+
90
97
  ${data.toString()}
91
98
 
92
99
  export function onRequest(context) {
@@ -159,7 +166,7 @@ const bundleServices = async () => {
159
166
  const services = walkdir.sync(path.join(process.cwd(), "services"))
160
167
  .filter((s) => s.includes(".service.js"));
161
168
  for (const s of services) {
162
- const dest = s.replace(process.cwd(), "").replace("/services", "").replace(".service.js", "")
169
+ const dest = s.replace(process.cwd(), "").replace("/services", "").replace(".service.js", "");
163
170
  const pkg = await import(s);
164
171
  for (const p of Object.keys(pkg)) {
165
172
  const buildStart = Date.now();
@@ -200,7 +207,7 @@ const bundleServices = async () => {
200
207
  });
201
208
  }
202
209
  })
203
- ensureDir(`build/functions/_rpc${dest}`)
210
+ fse.ensureDirSync(`build/functions/_rpc${dest}`)
204
211
  const outfile = `build/functions/_rpc${dest}/${p}.js`;
205
212
  fs.writeFileSync(outfile, result.outputFiles[0].contents);
206
213
  recordSize(buildStart, outfile);
@@ -214,32 +221,25 @@ const bundleCss = async () => {
214
221
  postcssCustomMedia(),
215
222
  postcssNesting,
216
223
  ]).process(generatedCss, { from: "app.css", to: "app.css" });
217
- ensureDir(`build/static/css`)
224
+ fse.ensureDirSync(`build/static/css`)
218
225
  fs.writeFileSync(`${process.cwd()}/build/static/css/app.css`, result.toString());
219
226
  }
220
227
 
228
+ const build = async (platform, setProd) => {
229
+ fse.removeSync(buildDir);
221
- const ensureDir = (d) => {
230
+ fse.ensureDirSync(buildDir);
222
- if (!fs.existsSync(d)) {
231
+ fse.ensureDirSync(staticDir);
223
- fs.mkdirSync(d, { recursive: true });
232
+ fse.copySync(inputStaticDir, staticDir);
224
- }
225
- }
226
-
227
- const cleanDir = (d) => {
228
- if (fs.existsSync(d)) {
233
+ if (setProd) {
229
- fs.rmSync(d, { recursive: true });
234
+ process.env.NODE_ENV = "production";
235
+ isProd = true;
230
236
  }
231
- }
232
- const createDirs = () => {
233
- cleanDir(buildDir);
234
- ensureDir(buildDir);
235
- ensureDir(staticDir);
236
- }
237
-
238
- const build = async () => {
239
- createDirs();
240
237
  await bundlePages();
241
- // await bundleServices();
238
+ await bundleServices();
242
239
  await bundleCss();
240
+ if (platform === "cloudflare") {
241
+ // create _routes.json for cloudflare which only includes the pages and services
242
+ }
243
243
  }
244
244
 
245
245
  yargs(hideBin(process.argv))
@@ -253,7 +253,7 @@ yargs(hideBin(process.argv))
253
253
  })
254
254
  .demandOption("p")
255
255
  }, ({ platform }) => {
256
- build(platform);
256
+ build(platform, true);
257
257
  })
258
258
  .command('dev', 'run the dev server', (y) => {
259
259
  y.option('platform', {
@@ -263,7 +263,7 @@ yargs(hideBin(process.argv))
263
263
  choices: ['cloudflare', 'vercel']
264
264
  })
265
265
  }, ({ platform }) => {
266
- build(platform);
266
+ build(platform, false);
267
267
  })
268
268
  .demandCommand(1)
269
269
  .parse()
example/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "type": "module",
4
4
  "scripts": {
5
5
  "dev": "edge-city dev -p cloudflare",
6
- "build:prod": " edge-city build -p cloudflare",
6
+ "build": " edge-city build -p cloudflare",
7
7
  "test": "jest",
8
8
  "test-e2e": "playwright test"
9
9
  },
example/pages/_404/page.css CHANGED
@@ -6,7 +6,6 @@
6
6
  color: #000;
7
7
  background: #fff;
8
8
  font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif;
9
- height: 100vh;
10
9
  text-align: center;
11
10
 
12
11
  & h1 {
example/pages/_404/page.jsx CHANGED
@@ -1,18 +1,21 @@
1
1
  import React from 'react';
2
2
  import { Helmet } from 'react-helmet-async';
3
+ import Layout from '@/components/Layout/Layout';
3
4
  import "./page.css";
4
5
 
5
6
  const Page = () => {
6
7
  return (
8
+ <Layout>
7
- <div className="notfound-page">
9
+ <div className="notfound-page">
8
- <Helmet>
10
+ <Helmet>
9
- <title>Page not found</title>
11
+ <title>Page not found</title>
10
- </Helmet>
12
+ </Helmet>
11
- <h1>404 - Page not found</h1>
13
+ <h1>404 - Page not found</h1>
12
- <div className="content">
14
+ <div className="content">
13
- <h2>This page could not be found</h2>
15
+ <h2>This page could not be found</h2>
16
+ </div>
14
17
  </div>
15
- </div>
18
+ </Layout>
16
19
  )
17
20
  }
18
21
 
example/pages/_500/page.jsx CHANGED
@@ -1,18 +1,21 @@
1
1
  import React from 'react';
2
2
  import { Helmet } from 'react-helmet-async';
3
+ import Layout from '@/components/Layout/Layout';
3
4
  import "./page.css";
4
5
 
5
6
  const Page = () => {
6
7
  return (
8
+ <Layout>
7
- <div className="err-page">
9
+ <div className="err-page">
8
- <Helmet>
10
+ <Helmet>
9
- <title>Oop's Something went wrong</title>
11
+ <title>Oop's Something went wrong</title>
10
- </Helmet>
12
+ </Helmet>
11
- <h1>Oop's Something went wrong</h1>
13
+ <h1>Oop's Something went wrong</h1>
12
- <div className="content">
14
+ <div className="content">
13
- <h2>Internal Server Error</h2>
15
+ <h2>Internal Server Error</h2>
16
+ </div>
14
17
  </div>
15
- </div>
18
+ </Layout>
16
19
  )
17
20
  }
18
21
 
index.js CHANGED
@@ -125,7 +125,7 @@ export const RouterContext = createContext(undefined);
125
125
  const getMatch = (router, pathname) => {
126
126
  const matchedPage = router.lookup(pathname);
127
127
  if (!matchedPage) {
128
- return router.lookup("/js/_404.js")
128
+ return router.lookup("/_404")
129
129
  }
130
130
  return matchedPage;
131
131
  }
@@ -250,6 +250,14 @@ export const renderPage = async (PageComponent, req) => {
250
250
  const history = createMemoryHistory({
251
251
  initialEntries: [url.pathname + url.search],
252
252
  });
253
+ const router = createRouter({
254
+ strictTrailingSlash: true,
255
+ routes: Object.keys(routemap).reduce((acc, r) => {
256
+ acc[r] = r;
257
+ return acc;
258
+ }, {}),
259
+ });
260
+ const AppPage = router.lookup(url.pathname) ? PageComponent : NotFoundPage;
253
261
  const jsScript = url.pathname === "/" ? "index" : url.pathname;
254
262
  const helmetContext = {}
255
263
  const stream = await renderToReadableStream(
@@ -271,7 +279,7 @@ export const renderPage = async (PageComponent, req) => {
271
279
  router: null,
272
280
  rpcCache: {},
273
281
  helmetContext,
274
- PageComponent,
282
+ PageComponent: AppPage,
275
283
  }), _jsx(_Fragment, {
276
284
  children: _jsx("script", {
277
285
  type: "module",
package.json CHANGED
@@ -20,6 +20,7 @@
20
20
  "esbuild": "0.17.19",
21
21
  "yargs": "17.7.2",
22
22
  "mime-types": "2.1.35",
23
+ "fs-extra": "11.1.1",
23
24
  "ms": "2.1.3",
24
25
  "picocolors": "1.0.0",
25
26
  "postcss": "^8.4.21",
pnpm-lock.yaml CHANGED
@@ -41,6 +41,9 @@ importers:
41
41
  esbuild-plugin-resolve:
42
42
  specifier: 2.0.0
43
43
  version: 2.0.0
44
+ fs-extra:
45
+ specifier: 11.1.1
46
+ version: 11.1.1
44
47
  jest:
45
48
  specifier: 29.5.0
46
49
  version: 29.5.0
@@ -69,6 +72,12 @@ importers:
69
72
  specifier: 17.7.2
70
73
  version: 17.7.2
71
74
 
75
+ docs:
76
+ dependencies:
77
+ '@markdoc/markdoc':
78
+ specifier: 0.2.2
79
+ version: 0.2.2(react@18.2.0)
80
+
72
81
  example:
73
82
  dependencies:
74
83
  '@neondatabase/serverless':
@@ -2107,6 +2116,23 @@ packages:
2107
2116
  '@jridgewell/sourcemap-codec': 1.4.14
2108
2117
  dev: true
2109
2118
 
2119
+ /@markdoc/markdoc@0.2.2(react@18.2.0):
2120
+ resolution: {integrity: sha512-0TiD9jmA5h5znN4lxo7HECAu3WieU5g5vUsfByeucrdR/x88hEilpt16EydFyJwJddQ/3w5HQgW7Ovy62r4cyw==}
2121
+ engines: {node: '>=14.7.0'}
2122
+ peerDependencies:
2123
+ '@types/react': '*'
2124
+ react: '*'
2125
+ peerDependenciesMeta:
2126
+ '@types/react':
2127
+ optional: true
2128
+ react:
2129
+ optional: true
2130
+ dependencies:
2131
+ react: 18.2.0
2132
+ optionalDependencies:
2133
+ '@types/markdown-it': 12.2.3
2134
+ dev: false
2135
+
2110
2136
  /@neondatabase/serverless@0.2.9:
2111
2137
  resolution: {integrity: sha512-fp7gXG8rt+uP+UT2ReGoCrf8GYb25Tv6xklDtZEoe8XKkBtVyZO+sii5oLNRwhvTLkqt7FX49MBCh3Est9b2KQ==}
2112
2138
  dev: false
@@ -3434,6 +3460,25 @@ packages:
3434
3460
  resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
3435
3461
  dev: true
3436
3462
 
3463
+ /@types/linkify-it@3.0.2:
3464
+ resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
3465
+ dev: false
3466
+ optional: true
3467
+
3468
+ /@types/markdown-it@12.2.3:
3469
+ resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
3470
+ requiresBuild: true
3471
+ dependencies:
3472
+ '@types/linkify-it': 3.0.2
3473
+ '@types/mdurl': 1.0.2
3474
+ dev: false
3475
+ optional: true
3476
+
3477
+ /@types/mdurl@1.0.2:
3478
+ resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
3479
+ dev: false
3480
+ optional: true
3481
+
3437
3482
  /@types/node@20.2.1:
3438
3483
  resolution: {integrity: sha512-DqJociPbZP1lbZ5SQPk4oag6W7AyaGMO6gSfRwq3PWl4PXTwJpRQJhDq4W0kzrg3w6tJ1SwlvGZ5uKFHY13LIg==}
3439
3484
  dev: true
@@ -4893,6 +4938,15 @@ packages:
4893
4938
  resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
4894
4939
  dev: true
4895
4940
 
4941
+ /fs-extra@11.1.1:
4942
+ resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==}
4943
+ engines: {node: '>=14.14'}
4944
+ dependencies:
4945
+ graceful-fs: 4.2.11
4946
+ jsonfile: 6.1.0
4947
+ universalify: 2.0.0
4948
+ dev: true
4949
+
4896
4950
  /fs.realpath@1.0.0:
4897
4951
  resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
4898
4952
  dev: true
@@ -5842,6 +5896,14 @@ packages:
5842
5896
  hasBin: true
5843
5897
  dev: true
5844
5898
 
5899
+ /jsonfile@6.1.0:
5900
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
5901
+ dependencies:
5902
+ universalify: 2.0.0
5903
+ optionalDependencies:
5904
+ graceful-fs: 4.2.11
5905
+ dev: true
5906
+
5845
5907
  /jsx-ast-utils@3.3.3:
5846
5908
  resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
5847
5909
  engines: {node: '>=4.0'}
@@ -6939,6 +7001,11 @@ packages:
6939
7001
  engines: {node: '>=4'}
6940
7002
  dev: true
6941
7003
 
7004
+ /universalify@2.0.0:
7005
+ resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
7006
+ engines: {node: '>= 10.0.0'}
7007
+ dev: true
7008
+
6942
7009
  /update-browserslist-db@1.0.11(browserslist@4.21.5):
6943
7010
  resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
6944
7011
  hasBin: true
pnpm-workspace.yaml CHANGED
@@ -1,3 +1,4 @@
1
1
  packages:
2
2
  - "./"
3
3
  - "example"
4
+ - "docs"