@webtypen/webframez-react 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -21
- package/bin/webframez-react.mjs +158 -0
- package/defaults/tsconfig.server.json +51 -0
- package/defaults/webpack.client.cjs +61 -0
- package/defaults/webpack.server.cjs +33 -0
- package/dist/http.cjs +15 -0
- package/dist/http.js +15 -0
- package/dist/index.cjs +15 -0
- package/dist/index.js +15 -0
- package/dist/webframez-core.cjs +15 -0
- package/dist/webframez-core.js +15 -0
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
React Server Components (RSC) extension for `@webtypen/webframez-core`.
|
|
4
4
|
|
|
5
5
|
`webframez-react` provides:
|
|
6
|
+
|
|
6
7
|
- seamless `webframez-core` integration via `initWebframezReact(Route)`
|
|
7
8
|
- file-based routing for `pages/**/index.tsx`
|
|
8
9
|
- layout/error handling with `RouteChildren`
|
|
@@ -19,28 +20,135 @@ React Server Components (RSC) extension for `@webtypen/webframez-core`.
|
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
22
|
npm i @webtypen/webframez-react @webtypen/webframez-core react react-dom react-server-dom-webpack
|
|
23
|
+
npm i -D typescript webpack webpack-cli ts-loader
|
|
22
24
|
```
|
|
23
25
|
|
|
24
26
|
## Quick Start with webframez-core
|
|
25
27
|
|
|
26
28
|
```ts
|
|
27
29
|
// server.ts
|
|
28
|
-
import {
|
|
30
|
+
import { BaseKernelWeb, Route, WebApplication } from "@webtypen/webframez-core";
|
|
29
31
|
import { initWebframezReact } from "@webtypen/webframez-react/webframez-core";
|
|
30
32
|
|
|
33
|
+
class Kernel extends BaseKernelWeb {
|
|
34
|
+
static controller = {};
|
|
35
|
+
static middleware = {};
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
initWebframezReact(Route);
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
const app = new WebApplication();
|
|
41
|
+
app.boot({
|
|
42
|
+
kernel: Kernel,
|
|
43
|
+
routesFunction: () => {
|
|
44
|
+
Route.renderReact("/react", {
|
|
45
|
+
distRootDir: `${process.cwd()}/dist`,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
35
48
|
});
|
|
36
|
-
|
|
37
|
-
WebApplication.boot();
|
|
38
49
|
```
|
|
39
50
|
|
|
40
51
|
Notes:
|
|
52
|
+
|
|
41
53
|
- `"/react"` is automatically registered as a catch-all route (`/react/*`).
|
|
42
54
|
- `basePath`, `assetsPrefix`, `rscPath`, and `clientScriptUrl` are derived automatically from the mount path.
|
|
43
55
|
|
|
56
|
+
## Add to an Existing webframez-core Project
|
|
57
|
+
|
|
58
|
+
If you already have a running `@webtypen/webframez-core` app, this is the smallest setup to mount React and return a first JSX page.
|
|
59
|
+
|
|
60
|
+
1. Install dependencies:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm i @webtypen/webframez-react react react-dom react-server-dom-webpack
|
|
64
|
+
npm i -D typescript webpack webpack-cli ts-loader
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
2. Extend `Route` and mount React inside your existing `routesFunction`:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// server.ts
|
|
71
|
+
import path from "node:path";
|
|
72
|
+
import { BaseKernelWeb, Route, WebApplication } from "@webtypen/webframez-core";
|
|
73
|
+
import { initWebframezReact } from "@webtypen/webframez-react/webframez-core";
|
|
74
|
+
|
|
75
|
+
class Kernel extends BaseKernelWeb {
|
|
76
|
+
static controller = {};
|
|
77
|
+
static middleware = {};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
initWebframezReact(Route);
|
|
81
|
+
|
|
82
|
+
const app = new WebApplication();
|
|
83
|
+
app.boot({
|
|
84
|
+
kernel: Kernel,
|
|
85
|
+
port: 3000,
|
|
86
|
+
routesFunction: () => {
|
|
87
|
+
// Your existing core routes can stay here.
|
|
88
|
+
Route.renderReact("/app", {
|
|
89
|
+
distRootDir: path.resolve(process.cwd(), "dist"),
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
3. Create a minimal file-router page setup:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// pages/layout.tsx
|
|
99
|
+
"use server";
|
|
100
|
+
|
|
101
|
+
import React from "react";
|
|
102
|
+
import { RouteChildren } from "@webtypen/webframez-react/router";
|
|
103
|
+
|
|
104
|
+
export default function Layout() {
|
|
105
|
+
return (
|
|
106
|
+
<main>
|
|
107
|
+
<RouteChildren />
|
|
108
|
+
</main>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
// pages/index.tsx
|
|
115
|
+
"use server";
|
|
116
|
+
|
|
117
|
+
import React from "react";
|
|
118
|
+
|
|
119
|
+
export default function HomePage() {
|
|
120
|
+
return <h1>Hello from webframez-react + JSX</h1>;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
4. Create the client entry:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
// src/client.tsx
|
|
128
|
+
import { mountWebframezClient } from "@webtypen/webframez-react/client";
|
|
129
|
+
|
|
130
|
+
mountWebframezClient();
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
5. Add build scripts (with automatic config fallback):
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"scripts": {
|
|
138
|
+
"build:server": "webframez-react build:server",
|
|
139
|
+
"build:client": "webframez-react build:client",
|
|
140
|
+
"build": "npm run build:server && npm run build:client",
|
|
141
|
+
"watch:server": "webframez-react watch:server",
|
|
142
|
+
"watch:client": "webframez-react watch:client",
|
|
143
|
+
"serve:watch": "node --watch --conditions react-server start-server.cjs",
|
|
144
|
+
"watch": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'",
|
|
145
|
+
"dev": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
After build, your first page is available at `http://localhost:3000/app`.
|
|
151
|
+
|
|
44
152
|
## Page Structure (File-Based Routing)
|
|
45
153
|
|
|
46
154
|
Example:
|
|
@@ -60,7 +168,7 @@ pages/
|
|
|
60
168
|
"use server";
|
|
61
169
|
|
|
62
170
|
import React from "react";
|
|
63
|
-
import { RouteChildren } from "webframez-react/router";
|
|
171
|
+
import { RouteChildren } from "@webtypen/webframez-react/router";
|
|
64
172
|
|
|
65
173
|
export default function Layout() {
|
|
66
174
|
return (
|
|
@@ -81,7 +189,7 @@ Every server page gets `abort()` via `RouteContext`.
|
|
|
81
189
|
```tsx
|
|
82
190
|
"use server";
|
|
83
191
|
|
|
84
|
-
import type { PageProps } from "webframez-react/types";
|
|
192
|
+
import type { PageProps } from "@webtypen/webframez-react/types";
|
|
85
193
|
|
|
86
194
|
export default function AccountPage({ params, abort }: PageProps) {
|
|
87
195
|
if (params.username !== "jane") {
|
|
@@ -97,6 +205,7 @@ export default function AccountPage({ params, abort }: PageProps) {
|
|
|
97
205
|
```
|
|
98
206
|
|
|
99
207
|
Behavior:
|
|
208
|
+
|
|
100
209
|
- default without options: `404` + `"Page not found"`
|
|
101
210
|
- rendered through `pages/errors.tsx` (same behavior as unmatched routes)
|
|
102
211
|
- `pathname` is provided automatically by context
|
|
@@ -106,7 +215,7 @@ Behavior:
|
|
|
106
215
|
|
|
107
216
|
```tsx
|
|
108
217
|
// src/client.tsx
|
|
109
|
-
import { mountWebframezClient } from "webframez-react/client";
|
|
218
|
+
import { mountWebframezClient } from "@webtypen/webframez-react/client";
|
|
110
219
|
|
|
111
220
|
mountWebframezClient();
|
|
112
221
|
```
|
|
@@ -126,7 +235,7 @@ mountWebframezClient({
|
|
|
126
235
|
"use client";
|
|
127
236
|
|
|
128
237
|
import React from "react";
|
|
129
|
-
import { Link, Redirect } from "webframez-react/navigation";
|
|
238
|
+
import { Link, Redirect } from "@webtypen/webframez-react/navigation";
|
|
130
239
|
|
|
131
240
|
export function Nav() {
|
|
132
241
|
return (
|
|
@@ -147,6 +256,7 @@ export function Guard({ loggedIn }: { loggedIn: boolean }) {
|
|
|
147
256
|
```
|
|
148
257
|
|
|
149
258
|
Note:
|
|
259
|
+
|
|
150
260
|
- `Link` and `Redirect` automatically use the basename from `Route.renderReact()`.
|
|
151
261
|
- You can override it per usage via `basename`.
|
|
152
262
|
|
|
@@ -156,7 +266,7 @@ Note:
|
|
|
156
266
|
"use client";
|
|
157
267
|
|
|
158
268
|
import React from "react";
|
|
159
|
-
import { useCookie, useRouter } from "webframez-react/client";
|
|
269
|
+
import { useCookie, useRouter } from "@webtypen/webframez-react/client";
|
|
160
270
|
|
|
161
271
|
export default function LoginAction() {
|
|
162
272
|
const cookie = useCookie();
|
|
@@ -177,17 +287,17 @@ export default function LoginAction() {
|
|
|
177
287
|
|
|
178
288
|
## Public Entrypoints
|
|
179
289
|
|
|
180
|
-
-
|
|
290
|
+
- `@webtypen/webframez-react`
|
|
181
291
|
- `createNodeRequestHandler`, `createFileRouter`, `createHTMLShell`, `sendRSC`, `createRSCHandler`
|
|
182
|
-
-
|
|
292
|
+
- `@webtypen/webframez-react/webframez-core`
|
|
183
293
|
- `initWebframezReact`
|
|
184
|
-
-
|
|
294
|
+
- `@webtypen/webframez-react/router`
|
|
185
295
|
- `RouteChildren`
|
|
186
|
-
-
|
|
296
|
+
- `@webtypen/webframez-react/client`
|
|
187
297
|
- `mountWebframezClient`, `useRouter`, `useCookie`
|
|
188
|
-
-
|
|
298
|
+
- `@webtypen/webframez-react/navigation`
|
|
189
299
|
- `Link`, `Redirect`
|
|
190
|
-
-
|
|
300
|
+
- `@webtypen/webframez-react/types`
|
|
191
301
|
- all public types (`RouteContext`, `PageProps`, `ErrorPageProps`, ...)
|
|
192
302
|
|
|
193
303
|
## package.json Scripts
|
|
@@ -197,22 +307,31 @@ Example scripts for a `webframez-react` app:
|
|
|
197
307
|
```json
|
|
198
308
|
{
|
|
199
309
|
"scripts": {
|
|
200
|
-
"build:server": "
|
|
201
|
-
"build:client": "
|
|
310
|
+
"build:server": "webframez-react build:server",
|
|
311
|
+
"build:client": "webframez-react build:client",
|
|
202
312
|
"build": "npm run build:server && npm run build:client",
|
|
203
313
|
"start": "node --conditions react-server start-server.cjs",
|
|
204
|
-
"watch:server": "
|
|
205
|
-
"watch:client": "
|
|
314
|
+
"watch:server": "webframez-react watch:server",
|
|
315
|
+
"watch:client": "webframez-react watch:client",
|
|
206
316
|
"serve:watch": "node --watch --conditions react-server start-server.cjs",
|
|
317
|
+
"watch": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'",
|
|
207
318
|
"dev": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'"
|
|
208
319
|
}
|
|
209
320
|
}
|
|
210
321
|
```
|
|
211
322
|
|
|
212
323
|
Notes:
|
|
324
|
+
|
|
325
|
+
- `webframez-react` CLI first checks project overrides and falls back to package defaults:
|
|
326
|
+
- `tsconfig.server.json`
|
|
327
|
+
- `webpack.client.cjs`
|
|
328
|
+
- `webpack.server.cjs`
|
|
329
|
+
- `webpack.server.cjs` is optional. Default flow compiles server with `tsc`. Use webpack-server only if you explicitly want a bundled server build:
|
|
330
|
+
- `webframez-react build:server:webpack`
|
|
331
|
+
- `webframez-react watch:server:webpack`
|
|
213
332
|
- `build` compiles server output (`pages`, `server.ts`) and client output (`client.tsx` bundle + RSC manifests).
|
|
214
333
|
- `start` runs the built app in React Server mode.
|
|
215
|
-
- `dev`
|
|
334
|
+
- `watch` and `dev` run the same full watch pipeline and restart Node automatically on server output changes.
|
|
216
335
|
|
|
217
336
|
## Build
|
|
218
337
|
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const binFilePath = fileURLToPath(import.meta.url);
|
|
9
|
+
const packageRoot = path.resolve(path.dirname(binFilePath), "..");
|
|
10
|
+
const projectRoot = process.cwd();
|
|
11
|
+
|
|
12
|
+
const command = process.argv[2];
|
|
13
|
+
const passthroughStart = process.argv[3] === "--" ? 4 : 3;
|
|
14
|
+
const passthroughArgs = process.argv.slice(passthroughStart);
|
|
15
|
+
|
|
16
|
+
function printHelp() {
|
|
17
|
+
console.log(
|
|
18
|
+
[
|
|
19
|
+
"webframez-react CLI",
|
|
20
|
+
"",
|
|
21
|
+
"Usage:",
|
|
22
|
+
" webframez-react build:server",
|
|
23
|
+
" webframez-react watch:server",
|
|
24
|
+
" webframez-react build:client",
|
|
25
|
+
" webframez-react watch:client",
|
|
26
|
+
" webframez-react build:server:webpack",
|
|
27
|
+
" webframez-react watch:server:webpack",
|
|
28
|
+
"",
|
|
29
|
+
"Config fallback order:",
|
|
30
|
+
" 1) project root override file",
|
|
31
|
+
" 2) package default in @webtypen/webframez-react/defaults",
|
|
32
|
+
"",
|
|
33
|
+
"Override file names:",
|
|
34
|
+
" - tsconfig.server.json",
|
|
35
|
+
" - webpack.client.cjs",
|
|
36
|
+
" - webpack.server.cjs",
|
|
37
|
+
].join("\n"),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function hasFlag(flag) {
|
|
42
|
+
return passthroughArgs.includes(flag);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolveConfig(localFileName, fallbackFileName) {
|
|
46
|
+
const localPath = path.resolve(projectRoot, localFileName);
|
|
47
|
+
if (fs.existsSync(localPath)) {
|
|
48
|
+
return {
|
|
49
|
+
path: localPath,
|
|
50
|
+
source: "project",
|
|
51
|
+
name: localFileName,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
path: path.resolve(packageRoot, "defaults", fallbackFileName),
|
|
57
|
+
source: "package",
|
|
58
|
+
name: fallbackFileName,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function resolveBinary(name) {
|
|
63
|
+
const extension = process.platform === "win32" ? ".cmd" : "";
|
|
64
|
+
const localBinary = path.resolve(projectRoot, "node_modules", ".bin", `${name}${extension}`);
|
|
65
|
+
if (fs.existsSync(localBinary)) {
|
|
66
|
+
return localBinary;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return name;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function run(binaryName, args) {
|
|
73
|
+
const binary = resolveBinary(binaryName);
|
|
74
|
+
|
|
75
|
+
return new Promise((resolve, reject) => {
|
|
76
|
+
const child = spawn(binary, args, {
|
|
77
|
+
cwd: projectRoot,
|
|
78
|
+
stdio: "inherit",
|
|
79
|
+
shell: false,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
child.on("error", (error) => {
|
|
83
|
+
reject(error);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
child.on("close", (code) => {
|
|
87
|
+
resolve(code || 0);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function main() {
|
|
93
|
+
if (!command || command === "--help" || command === "-h") {
|
|
94
|
+
printHelp();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (command === "build:server" || command === "watch:server") {
|
|
99
|
+
const config = resolveConfig("tsconfig.server.json", "tsconfig.server.json");
|
|
100
|
+
console.log(`[webframez-react] tsc config (${config.source}): ${config.path}`);
|
|
101
|
+
|
|
102
|
+
const args = ["-p", config.path, ...passthroughArgs];
|
|
103
|
+
if (command === "watch:server") {
|
|
104
|
+
if (!hasFlag("--watch")) {
|
|
105
|
+
args.push("--watch");
|
|
106
|
+
}
|
|
107
|
+
if (!hasFlag("--preserveWatchOutput")) {
|
|
108
|
+
args.push("--preserveWatchOutput");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const code = await run("tsc", args);
|
|
113
|
+
process.exit(code);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (command === "build:client" || command === "watch:client") {
|
|
118
|
+
const config = resolveConfig("webpack.client.cjs", "webpack.client.cjs");
|
|
119
|
+
console.log(`[webframez-react] webpack config (${config.source}): ${config.path}`);
|
|
120
|
+
|
|
121
|
+
const args = ["--config", config.path, ...passthroughArgs];
|
|
122
|
+
if (command === "watch:client" && !hasFlag("--watch")) {
|
|
123
|
+
args.push("--watch");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const code = await run("webpack", args);
|
|
127
|
+
process.exit(code);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (command === "build:server:webpack" || command === "watch:server:webpack") {
|
|
132
|
+
const config = resolveConfig("webpack.server.cjs", "webpack.server.cjs");
|
|
133
|
+
console.log(`[webframez-react] webpack server config (${config.source}): ${config.path}`);
|
|
134
|
+
|
|
135
|
+
const args = ["--config", config.path, ...passthroughArgs];
|
|
136
|
+
if (command === "watch:server:webpack" && !hasFlag("--watch")) {
|
|
137
|
+
args.push("--watch");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const code = await run("webpack", args);
|
|
141
|
+
process.exit(code);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
console.error(`[webframez-react] Unknown command: ${command}`);
|
|
146
|
+
printHelp();
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
main().catch((error) => {
|
|
151
|
+
console.error("[webframez-react] Build command failed.");
|
|
152
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
153
|
+
console.error(String(error.message));
|
|
154
|
+
} else {
|
|
155
|
+
console.error(error);
|
|
156
|
+
}
|
|
157
|
+
process.exit(1);
|
|
158
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"baseUrl": ".",
|
|
7
|
+
"paths": {
|
|
8
|
+
"@webtypen/webframez-react/types": [
|
|
9
|
+
"./node_modules/@webtypen/webframez-react/dist/types.d.ts"
|
|
10
|
+
],
|
|
11
|
+
"@webtypen/webframez-react/router": [
|
|
12
|
+
"./node_modules/@webtypen/webframez-react/dist/router.d.ts"
|
|
13
|
+
],
|
|
14
|
+
"@webtypen/webframez-react/client": [
|
|
15
|
+
"./node_modules/@webtypen/webframez-react/dist/client.d.ts"
|
|
16
|
+
],
|
|
17
|
+
"@webtypen/webframez-react/navigation": [
|
|
18
|
+
"./node_modules/@webtypen/webframez-react/dist/navigation.d.ts"
|
|
19
|
+
],
|
|
20
|
+
"webframez-react/types": [
|
|
21
|
+
"./node_modules/@webtypen/webframez-react/dist/types.d.ts"
|
|
22
|
+
],
|
|
23
|
+
"webframez-react/router": [
|
|
24
|
+
"./node_modules/@webtypen/webframez-react/dist/router.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"webframez-react/client": [
|
|
27
|
+
"./node_modules/@webtypen/webframez-react/dist/client.d.ts"
|
|
28
|
+
],
|
|
29
|
+
"webframez-react/navigation": [
|
|
30
|
+
"./node_modules/@webtypen/webframez-react/dist/navigation.d.ts"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"jsx": "react-jsx",
|
|
34
|
+
"strict": true,
|
|
35
|
+
"esModuleInterop": true,
|
|
36
|
+
"skipLibCheck": true,
|
|
37
|
+
"outDir": "dist",
|
|
38
|
+
"rootDir": "."
|
|
39
|
+
},
|
|
40
|
+
"include": [
|
|
41
|
+
"src/server.ts",
|
|
42
|
+
"src/components/**/*.tsx",
|
|
43
|
+
"pages/**/*.tsx",
|
|
44
|
+
"src/types.d.ts"
|
|
45
|
+
],
|
|
46
|
+
"exclude": [
|
|
47
|
+
"src/client.tsx",
|
|
48
|
+
"dist",
|
|
49
|
+
"node_modules"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const ReactFlightWebpackPlugin = require("react-server-dom-webpack/plugin");
|
|
3
|
+
|
|
4
|
+
const projectRoot = process.cwd();
|
|
5
|
+
const frameworkDistDir = path.resolve(__dirname, "..", "dist");
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
mode: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
9
|
+
entry: {
|
|
10
|
+
client: path.resolve(projectRoot, "src/client.tsx"),
|
|
11
|
+
},
|
|
12
|
+
output: {
|
|
13
|
+
path: path.resolve(projectRoot, "dist"),
|
|
14
|
+
filename: "[name].js",
|
|
15
|
+
chunkFilename: "chunks/[name]-[contenthash].js",
|
|
16
|
+
publicPath: "auto",
|
|
17
|
+
},
|
|
18
|
+
resolve: {
|
|
19
|
+
extensions: [".tsx", ".ts", ".js"],
|
|
20
|
+
},
|
|
21
|
+
module: {
|
|
22
|
+
rules: [
|
|
23
|
+
{
|
|
24
|
+
test: /\.[tj]sx?$/,
|
|
25
|
+
exclude: /node_modules/,
|
|
26
|
+
use: {
|
|
27
|
+
loader: "ts-loader",
|
|
28
|
+
options: {
|
|
29
|
+
transpileOnly: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
optimization: {
|
|
36
|
+
splitChunks: false,
|
|
37
|
+
runtimeChunk: false,
|
|
38
|
+
},
|
|
39
|
+
plugins: [
|
|
40
|
+
new ReactFlightWebpackPlugin({
|
|
41
|
+
isServer: false,
|
|
42
|
+
clientReferences: [
|
|
43
|
+
{
|
|
44
|
+
directory: path.resolve(projectRoot, "dist/pages"),
|
|
45
|
+
recursive: true,
|
|
46
|
+
include: /\.js$/,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
directory: path.resolve(projectRoot, "dist/src/components"),
|
|
50
|
+
recursive: true,
|
|
51
|
+
include: /\.js$/,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
directory: frameworkDistDir,
|
|
55
|
+
recursive: false,
|
|
56
|
+
include: /navigation\.(js|cjs)$/,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
}),
|
|
60
|
+
],
|
|
61
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
const projectRoot = process.cwd();
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
mode: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
7
|
+
target: "node",
|
|
8
|
+
entry: path.resolve(projectRoot, "src/server.ts"),
|
|
9
|
+
output: {
|
|
10
|
+
path: path.resolve(projectRoot, "dist"),
|
|
11
|
+
filename: "server.cjs",
|
|
12
|
+
libraryTarget: "commonjs2",
|
|
13
|
+
},
|
|
14
|
+
resolve: {
|
|
15
|
+
extensions: [".tsx", ".ts", ".js"],
|
|
16
|
+
conditionNames: ["react-server", "node", "import", "require", "default"],
|
|
17
|
+
},
|
|
18
|
+
module: {
|
|
19
|
+
rules: [
|
|
20
|
+
{
|
|
21
|
+
test: /\.[tj]sx?$/,
|
|
22
|
+
exclude: /node_modules/,
|
|
23
|
+
use: {
|
|
24
|
+
loader: "ts-loader",
|
|
25
|
+
options: {
|
|
26
|
+
transpileOnly: true,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
externalsPresets: { node: true },
|
|
33
|
+
};
|
package/dist/http.cjs
CHANGED
|
@@ -493,8 +493,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
493
493
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
494
494
|
const script = `
|
|
495
495
|
const path = require("node:path");
|
|
496
|
+
const Module = require("node:module");
|
|
496
497
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
497
498
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
499
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
500
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
501
|
+
const forcedResolutions = new Map([
|
|
502
|
+
["react", appRequire.resolve("react")],
|
|
503
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
504
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
505
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
506
|
+
]);
|
|
507
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
508
|
+
if (forcedResolutions.has(request)) {
|
|
509
|
+
return forcedResolutions.get(request);
|
|
510
|
+
}
|
|
511
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
512
|
+
};
|
|
498
513
|
const { createFileRouter } = require("webframez-react/router");
|
|
499
514
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
500
515
|
paths: [process.cwd(), input.pagesDir]
|
package/dist/http.js
CHANGED
|
@@ -468,8 +468,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
468
468
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
469
469
|
const script = `
|
|
470
470
|
const path = require("node:path");
|
|
471
|
+
const Module = require("node:module");
|
|
471
472
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
472
473
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
474
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
475
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
476
|
+
const forcedResolutions = new Map([
|
|
477
|
+
["react", appRequire.resolve("react")],
|
|
478
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
479
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
480
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
481
|
+
]);
|
|
482
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
483
|
+
if (forcedResolutions.has(request)) {
|
|
484
|
+
return forcedResolutions.get(request);
|
|
485
|
+
}
|
|
486
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
487
|
+
};
|
|
473
488
|
const { createFileRouter } = require("webframez-react/router");
|
|
474
489
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
475
490
|
paths: [process.cwd(), input.pagesDir]
|
package/dist/index.cjs
CHANGED
|
@@ -530,8 +530,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
530
530
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
531
531
|
const script = `
|
|
532
532
|
const path = require("node:path");
|
|
533
|
+
const Module = require("node:module");
|
|
533
534
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
534
535
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
536
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
537
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
538
|
+
const forcedResolutions = new Map([
|
|
539
|
+
["react", appRequire.resolve("react")],
|
|
540
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
541
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
542
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
543
|
+
]);
|
|
544
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
545
|
+
if (forcedResolutions.has(request)) {
|
|
546
|
+
return forcedResolutions.get(request);
|
|
547
|
+
}
|
|
548
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
549
|
+
};
|
|
535
550
|
const { createFileRouter } = require("webframez-react/router");
|
|
536
551
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
537
552
|
paths: [process.cwd(), input.pagesDir]
|
package/dist/index.js
CHANGED
|
@@ -494,8 +494,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
494
494
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
495
495
|
const script = `
|
|
496
496
|
const path = require("node:path");
|
|
497
|
+
const Module = require("node:module");
|
|
497
498
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
498
499
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
500
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
501
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
502
|
+
const forcedResolutions = new Map([
|
|
503
|
+
["react", appRequire.resolve("react")],
|
|
504
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
505
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
506
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
507
|
+
]);
|
|
508
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
509
|
+
if (forcedResolutions.has(request)) {
|
|
510
|
+
return forcedResolutions.get(request);
|
|
511
|
+
}
|
|
512
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
513
|
+
};
|
|
499
514
|
const { createFileRouter } = require("webframez-react/router");
|
|
500
515
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
501
516
|
paths: [process.cwd(), input.pagesDir]
|
package/dist/webframez-core.cjs
CHANGED
|
@@ -496,8 +496,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
496
496
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
497
497
|
const script = `
|
|
498
498
|
const path = require("node:path");
|
|
499
|
+
const Module = require("node:module");
|
|
499
500
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
500
501
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
502
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
503
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
504
|
+
const forcedResolutions = new Map([
|
|
505
|
+
["react", appRequire.resolve("react")],
|
|
506
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
507
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
508
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
509
|
+
]);
|
|
510
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
511
|
+
if (forcedResolutions.has(request)) {
|
|
512
|
+
return forcedResolutions.get(request);
|
|
513
|
+
}
|
|
514
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
515
|
+
};
|
|
501
516
|
const { createFileRouter } = require("webframez-react/router");
|
|
502
517
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
503
518
|
paths: [process.cwd(), input.pagesDir]
|
package/dist/webframez-core.js
CHANGED
|
@@ -468,8 +468,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
468
468
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
469
469
|
const script = `
|
|
470
470
|
const path = require("node:path");
|
|
471
|
+
const Module = require("node:module");
|
|
471
472
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
472
473
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
474
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
475
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
476
|
+
const forcedResolutions = new Map([
|
|
477
|
+
["react", appRequire.resolve("react")],
|
|
478
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
479
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
480
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
481
|
+
]);
|
|
482
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
483
|
+
if (forcedResolutions.has(request)) {
|
|
484
|
+
return forcedResolutions.get(request);
|
|
485
|
+
}
|
|
486
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
487
|
+
};
|
|
473
488
|
const { createFileRouter } = require("webframez-react/router");
|
|
474
489
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
475
490
|
paths: [process.cwd(), input.pagesDir]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webtypen/webframez-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "TypeScript React RSC addition for @webtypen/webframez-core",
|
|
5
5
|
"homepage": "https://webtypen.de/",
|
|
6
6
|
"author": {
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"main": "./dist/index.cjs",
|
|
20
20
|
"module": "./dist/index.js",
|
|
21
21
|
"types": "./dist/index.d.ts",
|
|
22
|
+
"bin": {
|
|
23
|
+
"webframez-react": "./bin/webframez-react.mjs"
|
|
24
|
+
},
|
|
22
25
|
"exports": {
|
|
23
26
|
".": {
|
|
24
27
|
"types": "./dist/index.d.ts",
|
|
@@ -54,10 +57,16 @@
|
|
|
54
57
|
"types": "./dist/webframez-core.d.ts",
|
|
55
58
|
"import": "./dist/webframez-core.js",
|
|
56
59
|
"require": "./dist/webframez-core.cjs"
|
|
57
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"./defaults/webpack.client": "./defaults/webpack.client.cjs",
|
|
62
|
+
"./defaults/webpack.server": "./defaults/webpack.server.cjs",
|
|
63
|
+
"./defaults/tsconfig.server": "./defaults/tsconfig.server.json",
|
|
64
|
+
"./cli": "./bin/webframez-react.mjs"
|
|
58
65
|
},
|
|
59
66
|
"files": [
|
|
60
|
-
"dist"
|
|
67
|
+
"dist",
|
|
68
|
+
"defaults",
|
|
69
|
+
"bin"
|
|
61
70
|
],
|
|
62
71
|
"scripts": {
|
|
63
72
|
"clean": "rm -rf dist",
|