@alepha/react 0.7.5 → 0.7.7
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/dist/index.browser.d.ts +523 -0
- package/dist/index.browser.js +1041 -49
- package/dist/index.browser.js.map +1 -0
- package/dist/index.cjs +1288 -375
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +629 -0
- package/dist/index.d.ts +468 -559
- package/dist/index.js +1245 -354
- package/dist/index.js.map +1 -0
- package/package.json +12 -8
- package/src/descriptors/$page.ts +2 -47
- package/src/hooks/useClient.ts +3 -3
- package/src/index.ts +16 -4
- package/src/providers/BrowserRouterProvider.ts +3 -4
- package/src/providers/PageDescriptorProvider.ts +10 -57
- package/src/providers/ReactBrowserProvider.ts +3 -14
- package/src/providers/ReactServerProvider.ts +66 -58
- package/dist/index.browser.cjs +0 -75
- package/dist/useRouterState-BTmuHxkM.cjs +0 -1183
- package/dist/useRouterState-cCucJfTC.js +0 -1161
- package/src/providers/BrowserHeadProvider.ts +0 -43
- package/src/providers/ServerHeadProvider.ts +0 -91
|
@@ -12,13 +12,16 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
apiLinksResponseSchema,
|
|
14
14
|
type ServerHandler,
|
|
15
|
-
ServerLinksProvider,
|
|
16
15
|
ServerRouterProvider,
|
|
17
16
|
ServerTimingProvider,
|
|
18
17
|
} from "@alepha/server";
|
|
18
|
+
import { ServerLinksProvider } from "@alepha/server-links";
|
|
19
19
|
import { ServerStaticProvider } from "@alepha/server-static";
|
|
20
20
|
import { renderToString } from "react-dom/server";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
$page,
|
|
23
|
+
type PageDescriptorRenderOptions,
|
|
24
|
+
} from "../descriptors/$page.ts";
|
|
22
25
|
import {
|
|
23
26
|
PageDescriptorProvider,
|
|
24
27
|
type PageReactContext,
|
|
@@ -27,7 +30,6 @@ import {
|
|
|
27
30
|
type RouterState,
|
|
28
31
|
} from "./PageDescriptorProvider.ts";
|
|
29
32
|
import type { ReactHydrationState } from "./ReactBrowserProvider.ts";
|
|
30
|
-
import { ServerHeadProvider } from "./ServerHeadProvider.ts";
|
|
31
33
|
|
|
32
34
|
const envSchema = t.object({
|
|
33
35
|
REACT_SERVER_DIST: t.string({ default: "public" }),
|
|
@@ -50,7 +52,6 @@ export class ReactServerProvider {
|
|
|
50
52
|
protected readonly pageDescriptorProvider = $inject(PageDescriptorProvider);
|
|
51
53
|
protected readonly serverStaticProvider = $inject(ServerStaticProvider);
|
|
52
54
|
protected readonly serverRouterProvider = $inject(ServerRouterProvider);
|
|
53
|
-
protected readonly headProvider = $inject(ServerHeadProvider);
|
|
54
55
|
protected readonly serverTimingProvider = $inject(ServerTimingProvider);
|
|
55
56
|
protected readonly env = $inject(envSchema);
|
|
56
57
|
protected readonly ROOT_DIV_REGEX = new RegExp(
|
|
@@ -71,11 +72,7 @@ export class ReactServerProvider {
|
|
|
71
72
|
for (const { key, instance, value } of pages) {
|
|
72
73
|
const name = value[OPTIONS].name ?? key;
|
|
73
74
|
|
|
74
|
-
instance[key].
|
|
75
|
-
|
|
76
|
-
if (this.alepha.isTest()) {
|
|
77
|
-
instance[key].render = this.createRenderFunction(name);
|
|
78
|
-
}
|
|
75
|
+
instance[key].render = this.createRenderFunction(name);
|
|
79
76
|
}
|
|
80
77
|
|
|
81
78
|
// development mode
|
|
@@ -129,7 +126,10 @@ export class ReactServerProvider {
|
|
|
129
126
|
});
|
|
130
127
|
|
|
131
128
|
public get template() {
|
|
132
|
-
return
|
|
129
|
+
return (
|
|
130
|
+
this.alepha.state("ReactServerProvider.template") ??
|
|
131
|
+
"<!DOCTYPE html><html lang='en'><head></head><body></body></html>"
|
|
132
|
+
);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
protected async registerPages(templateLoader: TemplateLoader) {
|
|
@@ -193,12 +193,7 @@ export class ReactServerProvider {
|
|
|
193
193
|
* For testing purposes, creates a render function that can be used.
|
|
194
194
|
*/
|
|
195
195
|
protected createRenderFunction(name: string, withIndex = false) {
|
|
196
|
-
return async (
|
|
197
|
-
options: {
|
|
198
|
-
params?: Record<string, string>;
|
|
199
|
-
query?: Record<string, string>;
|
|
200
|
-
} = {},
|
|
201
|
-
) => {
|
|
196
|
+
return async (options: PageDescriptorRenderOptions = {}) => {
|
|
202
197
|
const page = this.pageDescriptorProvider.page(name);
|
|
203
198
|
const url = new URL(this.pageDescriptorProvider.url(name, options));
|
|
204
199
|
const context: PageRequest = {
|
|
@@ -209,12 +204,16 @@ export class ReactServerProvider {
|
|
|
209
204
|
onError: () => null,
|
|
210
205
|
};
|
|
211
206
|
|
|
207
|
+
await this.alepha.emit("react:server:render:begin", {
|
|
208
|
+
context,
|
|
209
|
+
});
|
|
210
|
+
|
|
212
211
|
const state = await this.pageDescriptorProvider.createLayers(
|
|
213
212
|
page,
|
|
214
213
|
context,
|
|
215
214
|
);
|
|
216
215
|
|
|
217
|
-
if (!withIndex) {
|
|
216
|
+
if (!withIndex && !options.html) {
|
|
218
217
|
return {
|
|
219
218
|
context,
|
|
220
219
|
html: renderToString(
|
|
@@ -223,10 +222,22 @@ export class ReactServerProvider {
|
|
|
223
222
|
};
|
|
224
223
|
}
|
|
225
224
|
|
|
226
|
-
|
|
225
|
+
const html = this.renderToHtml(
|
|
226
|
+
this.template ?? "",
|
|
227
|
+
state,
|
|
227
228
|
context,
|
|
228
|
-
|
|
229
|
+
options.hydration,
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const result = {
|
|
233
|
+
context,
|
|
234
|
+
state,
|
|
235
|
+
html,
|
|
229
236
|
};
|
|
237
|
+
|
|
238
|
+
await this.alepha.emit("react:server:render:end", result);
|
|
239
|
+
|
|
240
|
+
return result;
|
|
230
241
|
};
|
|
231
242
|
}
|
|
232
243
|
|
|
@@ -287,16 +298,10 @@ export class ReactServerProvider {
|
|
|
287
298
|
// return;
|
|
288
299
|
// }
|
|
289
300
|
|
|
290
|
-
await this.alepha.emit(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
pageRequest: context,
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
log: false,
|
|
298
|
-
},
|
|
299
|
-
);
|
|
301
|
+
await this.alepha.emit("react:server:render:begin", {
|
|
302
|
+
request: serverRequest,
|
|
303
|
+
context,
|
|
304
|
+
});
|
|
300
305
|
|
|
301
306
|
this.serverTimingProvider.beginTiming("createLayers");
|
|
302
307
|
|
|
@@ -327,6 +332,13 @@ export class ReactServerProvider {
|
|
|
327
332
|
|
|
328
333
|
const html = this.renderToHtml(template, state, context);
|
|
329
334
|
|
|
335
|
+
await this.alepha.emit("react:server:render:end", {
|
|
336
|
+
request: serverRequest,
|
|
337
|
+
context,
|
|
338
|
+
state,
|
|
339
|
+
html,
|
|
340
|
+
});
|
|
341
|
+
|
|
330
342
|
page.afterHandler?.(serverRequest);
|
|
331
343
|
|
|
332
344
|
return html;
|
|
@@ -337,6 +349,7 @@ export class ReactServerProvider {
|
|
|
337
349
|
template: string,
|
|
338
350
|
state: RouterState,
|
|
339
351
|
context: PageReactContext,
|
|
352
|
+
hydration = true,
|
|
340
353
|
) {
|
|
341
354
|
const element = this.pageDescriptorProvider.root(state, context);
|
|
342
355
|
|
|
@@ -352,41 +365,36 @@ export class ReactServerProvider {
|
|
|
352
365
|
|
|
353
366
|
this.serverTimingProvider.endTiming("renderToString");
|
|
354
367
|
|
|
355
|
-
const hydrationData: ReactHydrationState = {
|
|
356
|
-
links: context.links,
|
|
357
|
-
layers: state.layers.map((it) => ({
|
|
358
|
-
...it,
|
|
359
|
-
error: it.error
|
|
360
|
-
? {
|
|
361
|
-
...it.error,
|
|
362
|
-
name: it.error.name,
|
|
363
|
-
message: it.error.message,
|
|
364
|
-
stack: it.error.stack, // TODO: Hide stack in production ?
|
|
365
|
-
}
|
|
366
|
-
: undefined,
|
|
367
|
-
index: undefined,
|
|
368
|
-
path: undefined,
|
|
369
|
-
element: undefined,
|
|
370
|
-
})),
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
// create hydration data
|
|
374
|
-
const script = `<script>window.__ssr=${JSON.stringify(hydrationData)}</script>`;
|
|
375
|
-
|
|
376
368
|
const response = {
|
|
377
369
|
html: template,
|
|
378
370
|
};
|
|
379
371
|
|
|
380
|
-
|
|
381
|
-
|
|
372
|
+
if (hydration) {
|
|
373
|
+
const hydrationData: ReactHydrationState = {
|
|
374
|
+
links: context.links,
|
|
375
|
+
layers: state.layers.map((it) => ({
|
|
376
|
+
...it,
|
|
377
|
+
error: it.error
|
|
378
|
+
? {
|
|
379
|
+
...it.error,
|
|
380
|
+
name: it.error.name,
|
|
381
|
+
message: it.error.message,
|
|
382
|
+
stack: it.error.stack, // TODO: Hide stack in production ?
|
|
383
|
+
}
|
|
384
|
+
: undefined,
|
|
385
|
+
index: undefined,
|
|
386
|
+
path: undefined,
|
|
387
|
+
element: undefined,
|
|
388
|
+
route: undefined,
|
|
389
|
+
})),
|
|
390
|
+
};
|
|
382
391
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
response.html = this.headProvider.renderHead(response.html, context.head);
|
|
386
|
-
}
|
|
392
|
+
// create hydration data
|
|
393
|
+
const script = `<script>window.__ssr=${JSON.stringify(hydrationData)}</script>`;
|
|
387
394
|
|
|
388
|
-
|
|
389
|
-
|
|
395
|
+
// inject app into template
|
|
396
|
+
this.fillTemplate(response, app, script);
|
|
397
|
+
}
|
|
390
398
|
|
|
391
399
|
return response.html;
|
|
392
400
|
}
|
package/dist/index.browser.cjs
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var core = require('@alepha/core');
|
|
4
|
-
var useRouterState = require('./useRouterState-BTmuHxkM.cjs');
|
|
5
|
-
var client = require('react-dom/client');
|
|
6
|
-
require('react/jsx-runtime');
|
|
7
|
-
require('react');
|
|
8
|
-
require('@alepha/server');
|
|
9
|
-
require('@alepha/router');
|
|
10
|
-
|
|
11
|
-
const envSchema = core.t.object({
|
|
12
|
-
REACT_ROOT_ID: core.t.string({ default: "root" })
|
|
13
|
-
});
|
|
14
|
-
class ReactBrowserRenderer {
|
|
15
|
-
browserProvider = core.$inject(useRouterState.ReactBrowserProvider);
|
|
16
|
-
browserRouterProvider = core.$inject(useRouterState.BrowserRouterProvider);
|
|
17
|
-
env = core.$inject(envSchema);
|
|
18
|
-
log = core.$logger();
|
|
19
|
-
root;
|
|
20
|
-
getRootElement() {
|
|
21
|
-
const root = this.browserProvider.document.getElementById(
|
|
22
|
-
this.env.REACT_ROOT_ID
|
|
23
|
-
);
|
|
24
|
-
if (root) {
|
|
25
|
-
return root;
|
|
26
|
-
}
|
|
27
|
-
const div = this.browserProvider.document.createElement("div");
|
|
28
|
-
div.id = this.env.REACT_ROOT_ID;
|
|
29
|
-
this.browserProvider.document.body.prepend(div);
|
|
30
|
-
return div;
|
|
31
|
-
}
|
|
32
|
-
ready = core.$hook({
|
|
33
|
-
name: "react:browser:render",
|
|
34
|
-
handler: async ({ state, context, hydration }) => {
|
|
35
|
-
const element = this.browserRouterProvider.root(state, context);
|
|
36
|
-
if (hydration?.layers) {
|
|
37
|
-
this.root = client.hydrateRoot(this.getRootElement(), element);
|
|
38
|
-
this.log.info("Hydrated root element");
|
|
39
|
-
} else {
|
|
40
|
-
this.root ??= client.createRoot(this.getRootElement());
|
|
41
|
-
this.root.render(element);
|
|
42
|
-
this.log.info("Created root element");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
class AlephaReact {
|
|
49
|
-
name = "alepha.react";
|
|
50
|
-
$services = (alepha) => alepha.with(useRouterState.PageDescriptorProvider).with(useRouterState.ReactBrowserProvider).with(useRouterState.BrowserRouterProvider).with(ReactBrowserRenderer);
|
|
51
|
-
}
|
|
52
|
-
core.__bind(useRouterState.$page, AlephaReact);
|
|
53
|
-
|
|
54
|
-
exports.$page = useRouterState.$page;
|
|
55
|
-
exports.BrowserRouterProvider = useRouterState.BrowserRouterProvider;
|
|
56
|
-
exports.ClientOnly = useRouterState.ClientOnly;
|
|
57
|
-
exports.ErrorBoundary = useRouterState.ErrorBoundary;
|
|
58
|
-
exports.Link = useRouterState.Link;
|
|
59
|
-
exports.NestedView = useRouterState.NestedView;
|
|
60
|
-
exports.PageDescriptorProvider = useRouterState.PageDescriptorProvider;
|
|
61
|
-
exports.ReactBrowserProvider = useRouterState.ReactBrowserProvider;
|
|
62
|
-
exports.RedirectionError = useRouterState.RedirectionError;
|
|
63
|
-
exports.RouterContext = useRouterState.RouterContext;
|
|
64
|
-
exports.RouterHookApi = useRouterState.RouterHookApi;
|
|
65
|
-
exports.RouterLayerContext = useRouterState.RouterLayerContext;
|
|
66
|
-
exports.isPageRoute = useRouterState.isPageRoute;
|
|
67
|
-
exports.useActive = useRouterState.useActive;
|
|
68
|
-
exports.useAlepha = useRouterState.useAlepha;
|
|
69
|
-
exports.useClient = useRouterState.useClient;
|
|
70
|
-
exports.useInject = useRouterState.useInject;
|
|
71
|
-
exports.useQueryParams = useRouterState.useQueryParams;
|
|
72
|
-
exports.useRouter = useRouterState.useRouter;
|
|
73
|
-
exports.useRouterEvents = useRouterState.useRouterEvents;
|
|
74
|
-
exports.useRouterState = useRouterState.useRouterState;
|
|
75
|
-
exports.AlephaReact = AlephaReact;
|