@bleedingdev/modern-js-renderer-octane 3.9.3-ultramodern.1 → 3.9.3-ultramodern.11
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/cjs/client.js +56 -6
- package/dist/cjs/entry-application.js +7 -2
- package/dist/cjs/entry-client.js +3 -0
- package/dist/cjs/entry-server.js +13 -5
- package/dist/cjs/federation.js +108 -6
- package/dist/cjs/i18n/I18nProvider.js +6 -14
- package/dist/cjs/i18n/LocalizedLink.js +24 -33
- package/dist/cjs/i18n/index.js +0 -3
- package/dist/cjs/i18n-external-snapshot.js +645 -0
- package/dist/cjs/index.js +4 -4
- package/dist/cjs/manifest.js +2 -2
- package/dist/cjs/plugin/compiler.js +2 -5
- package/dist/cjs/plugin/create.js +27 -26
- package/dist/cjs/plugin/index.js +2 -2
- package/dist/cjs/plugin/profile.js +12 -10
- package/dist/cjs/router-client.js +1 -1
- package/dist/cjs/router-external-snapshot.js +291 -0
- package/dist/cjs/router-handler.js +11 -8
- package/dist/cjs/router-server.js +3 -11
- package/dist/cjs/router.js +1 -1
- package/dist/cjs/routes.js +20 -17
- package/dist/cjs/server.js +28 -7
- package/dist/cjs/worker-federation-context.js +63 -0
- package/dist/cjs/worker-federation-contexts.js +97 -0
- package/dist/cjs/worker-federation.js +97 -0
- package/dist/esm/client.mjs +56 -6
- package/dist/esm/entry-application.mjs +7 -2
- package/dist/esm/entry-client.mjs +3 -0
- package/dist/esm/entry-server.mjs +11 -6
- package/dist/esm/federation.mjs +110 -8
- package/dist/esm/i18n/I18nProvider.mjs +7 -15
- package/dist/esm/i18n/LocalizedLink.mjs +24 -30
- package/dist/esm/i18n/index.mjs +1 -1
- package/dist/esm/i18n-external-snapshot.mjs +576 -0
- package/dist/esm/index.mjs +4 -4
- package/dist/esm/manifest.mjs +2 -2
- package/dist/esm/router-client.mjs +1 -1
- package/dist/esm/router-external-snapshot.mjs +244 -0
- package/dist/esm/router-handler.mjs +11 -8
- package/dist/esm/router-server.mjs +0 -1
- package/dist/esm/router.mjs +2 -2
- package/dist/esm/routes.mjs +18 -18
- package/dist/esm/server.mjs +24 -3
- package/dist/esm/worker-federation-context.mjs +19 -0
- package/dist/esm/worker-federation-contexts.mjs +47 -0
- package/dist/esm/worker-federation.mjs +59 -0
- package/dist/esm-node/manifest.mjs +2 -2
- package/dist/esm-node/plugin/compiler.mjs +2 -5
- package/dist/esm-node/plugin/create.mjs +27 -26
- package/dist/esm-node/plugin/index.mjs +2 -2
- package/dist/esm-node/plugin/profile.mjs +12 -10
- package/dist/types/client.d.ts +5 -1
- package/dist/types/entry-client.d.ts +2 -0
- package/dist/types/entry-server.d.ts +4 -1
- package/dist/types/federation.d.ts +2 -0
- package/dist/types/i18n/LocalizedLink.d.ts +5 -32
- package/dist/types/i18n/context.d.ts +1 -1
- package/dist/types/i18n/index.d.ts +1 -1
- package/dist/types/i18n-external-snapshot.d.ts +43 -0
- package/dist/types/index.d.ts +4 -4
- package/dist/types/manifest.d.ts +2 -2
- package/dist/types/router-external-snapshot.d.ts +10 -0
- package/dist/types/router-server.d.ts +0 -2
- package/dist/types/routes.d.ts +2 -0
- package/dist/types/server.d.ts +6 -0
- package/dist/types/worker-federation-context.d.ts +34 -0
- package/dist/types/worker-federation-contexts.d.ts +25 -0
- package/dist/types/worker-federation.d.ts +20 -0
- package/package.json +84 -22
- package/src/client.ts +99 -16
- package/src/entry-application.ts +7 -3
- package/src/entry-client.ts +10 -0
- package/src/entry-server.ts +20 -9
- package/src/federation.ts +164 -15
- package/src/i18n/I18nProvider.ts +11 -20
- package/src/i18n/LocalizedLink.ts +46 -72
- package/src/i18n/context.ts +1 -1
- package/src/i18n/index.ts +1 -5
- package/src/i18n-external-snapshot.ts +803 -0
- package/src/index.ts +4 -4
- package/src/manifest.ts +2 -2
- package/src/plugin/compiler-manifest.cjs +27 -1
- package/src/plugin/compiler.ts +6 -14
- package/src/plugin/create.ts +27 -26
- package/src/plugin/index.ts +4 -2
- package/src/plugin/profile.ts +14 -10
- package/src/router-client.ts +1 -1
- package/src/router-external-snapshot.ts +363 -0
- package/src/router-handler.ts +11 -8
- package/src/router-server.ts +0 -2
- package/src/router.ts +2 -2
- package/src/routes.ts +37 -26
- package/src/server.ts +45 -5
- package/src/worker-federation-context.ts +51 -0
- package/src/worker-federation-contexts.ts +91 -0
- package/src/worker-federation.ts +120 -0
- package/dist/cjs/router-injection.js +0 -139
- package/dist/esm/router-injection.mjs +0 -101
- package/dist/types/router-injection.d.ts +0 -8
- package/src/router-injection.ts +0 -145
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bleedingdev/modern-js-renderer-octane",
|
|
3
|
-
"version": "3.9.3-ultramodern.
|
|
3
|
+
"version": "3.9.3-ultramodern.11",
|
|
4
4
|
"description": "UltraModern native Octane application adapter.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -143,29 +143,61 @@
|
|
|
143
143
|
"default": "./dist/cjs/plugin/index.js"
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
|
-
"./package.json": "./package.json"
|
|
146
|
+
"./package.json": "./package.json",
|
|
147
|
+
"./router-external-snapshot": {
|
|
148
|
+
"import": {
|
|
149
|
+
"types": "./dist/types/router-external-snapshot.d.ts",
|
|
150
|
+
"default": "./dist/esm/router-external-snapshot.mjs"
|
|
151
|
+
},
|
|
152
|
+
"require": {
|
|
153
|
+
"types": "./dist/types/router-external-snapshot.d.ts",
|
|
154
|
+
"default": "./dist/cjs/router-external-snapshot.js"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"./i18n-external-snapshot": {
|
|
158
|
+
"import": {
|
|
159
|
+
"types": "./dist/types/i18n-external-snapshot.d.ts",
|
|
160
|
+
"default": "./dist/esm/i18n-external-snapshot.mjs"
|
|
161
|
+
},
|
|
162
|
+
"require": {
|
|
163
|
+
"types": "./dist/types/i18n-external-snapshot.d.ts",
|
|
164
|
+
"default": "./dist/cjs/i18n-external-snapshot.js"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"./worker-federation-contexts": {
|
|
168
|
+
"import": {
|
|
169
|
+
"types": "./dist/types/worker-federation-contexts.d.ts",
|
|
170
|
+
"default": "./dist/esm/worker-federation-contexts.mjs"
|
|
171
|
+
},
|
|
172
|
+
"require": {
|
|
173
|
+
"types": "./dist/types/worker-federation-contexts.d.ts",
|
|
174
|
+
"default": "./dist/cjs/worker-federation-contexts.js"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
147
177
|
},
|
|
148
178
|
"bin": {
|
|
149
179
|
"octane-tsc": "bin/octane-tsc.mjs"
|
|
150
180
|
},
|
|
151
181
|
"engines": {
|
|
152
|
-
"node": ">=26.
|
|
182
|
+
"node": ">=26.12.0"
|
|
153
183
|
},
|
|
154
184
|
"dependencies": {
|
|
155
|
-
"@modern-js/renderer-core": "npm:@bleedingdev/modern-js-renderer-core@3.9.3-ultramodern.
|
|
185
|
+
"@modern-js/renderer-core": "npm:@bleedingdev/modern-js-renderer-core@3.9.3-ultramodern.11",
|
|
156
186
|
"@volar/language-core": "2.4.28",
|
|
157
187
|
"jsonc-parser": "3.3.1",
|
|
158
|
-
"seroval": "1.6.
|
|
159
|
-
"seroval-plugins": "1.6.
|
|
188
|
+
"seroval": "1.6.9",
|
|
189
|
+
"seroval-plugins": "1.6.9",
|
|
160
190
|
"typescript": "7.0.2"
|
|
161
191
|
},
|
|
162
192
|
"peerDependencies": {
|
|
163
|
-
"@modern-js/i18n-runtime-extensions": "3.9.3-ultramodern.
|
|
164
|
-
"@octanejs/rspack-plugin": "0.
|
|
165
|
-
"@octanejs/tanstack-router": "0.
|
|
166
|
-
"@rsbuild/core": "2.2.
|
|
193
|
+
"@modern-js/i18n-runtime-extensions": "3.9.3-ultramodern.11",
|
|
194
|
+
"@octanejs/rspack-plugin": "0.2.4",
|
|
195
|
+
"@octanejs/tanstack-router": "0.2.10",
|
|
196
|
+
"@rsbuild/core": "2.2.13",
|
|
197
|
+
"@tanstack/router-core": "1.171.38",
|
|
198
|
+
"@tsrx/oxc": "0.20.0",
|
|
167
199
|
"i18next": ">=25.7.4",
|
|
168
|
-
"octane": "0.
|
|
200
|
+
"octane": "0.13.8"
|
|
169
201
|
},
|
|
170
202
|
"peerDependenciesMeta": {
|
|
171
203
|
"@modern-js/i18n-runtime-extensions": {
|
|
@@ -180,6 +212,9 @@
|
|
|
180
212
|
"@rsbuild/core": {
|
|
181
213
|
"optional": true
|
|
182
214
|
},
|
|
215
|
+
"@tsrx/oxc": {
|
|
216
|
+
"optional": true
|
|
217
|
+
},
|
|
183
218
|
"i18next": {
|
|
184
219
|
"optional": true
|
|
185
220
|
},
|
|
@@ -188,22 +223,52 @@
|
|
|
188
223
|
}
|
|
189
224
|
},
|
|
190
225
|
"devDependencies": {
|
|
191
|
-
"@modern-js/i18n-runtime-extensions": "npm:@bleedingdev/modern-js-i18n-runtime-extensions@3.9.3-ultramodern.
|
|
192
|
-
"@modern-js/tsconfig": "npm:@bleedingdev/modern-js-tsconfig@3.9.3-ultramodern.
|
|
193
|
-
"@octanejs/rspack-plugin": "0.
|
|
194
|
-
"@octanejs/tanstack-router": "https://github.com/
|
|
195
|
-
"@rsbuild/core": "2.2.
|
|
226
|
+
"@modern-js/i18n-runtime-extensions": "npm:@bleedingdev/modern-js-i18n-runtime-extensions@3.9.3-ultramodern.11",
|
|
227
|
+
"@modern-js/tsconfig": "npm:@bleedingdev/modern-js-tsconfig@3.9.3-ultramodern.11",
|
|
228
|
+
"@octanejs/rspack-plugin": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-2383d2ab1e70/octanejs-rspack-plugin-0.2.4.tgz",
|
|
229
|
+
"@octanejs/tanstack-router": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-2383d2ab1e70/octanejs-tanstack-router-0.2.10.tgz",
|
|
230
|
+
"@rsbuild/core": "2.2.13",
|
|
196
231
|
"@rslib/core": "1.0.3",
|
|
197
232
|
"@scripts/rstest-config": "2.66.0",
|
|
198
|
-
"@
|
|
199
|
-
"
|
|
200
|
-
"
|
|
233
|
+
"@tanstack/router-core": "https://github.com/BleedingDev/router/releases/download/ultramodern-router-core-585d3233f7f5/tanstack-router-core-1.171.38.tgz",
|
|
234
|
+
"@tsrx/oxc": "0.20.0",
|
|
235
|
+
"@types/jsdom": "27.0.0",
|
|
236
|
+
"@types/node": "^26.6.5",
|
|
237
|
+
"happy-dom": "^21.0.4",
|
|
238
|
+
"i18next": "26.4.6",
|
|
239
|
+
"jsdom": "30.0.1",
|
|
240
|
+
"octane": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-2383d2ab1e70/octane-0.13.8.tgz",
|
|
201
241
|
"typescript": "7.0.2"
|
|
202
242
|
},
|
|
203
243
|
"sideEffects": false,
|
|
204
244
|
"publishConfig": {
|
|
205
245
|
"access": "public"
|
|
206
246
|
},
|
|
247
|
+
"ultramodern": {
|
|
248
|
+
"nativeArtifacts": {
|
|
249
|
+
"octane": {
|
|
250
|
+
"request": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-2383d2ab1e70/octane-0.13.8.tgz",
|
|
251
|
+
"version": "0.13.8",
|
|
252
|
+
"integrity": "sha512-ryNxtzX4pwMVHNhWyEYG8VnpRUByWUDhtVDpYlQkeqipTSF7s8cP86CzBl/miNCruE48D27mnR7E8UW6V1fEnA=="
|
|
253
|
+
},
|
|
254
|
+
"@octanejs/tanstack-router": {
|
|
255
|
+
"request": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-2383d2ab1e70/octanejs-tanstack-router-0.2.10.tgz",
|
|
256
|
+
"version": "0.2.10",
|
|
257
|
+
"integrity": "sha512-wdnPhVZSQqZg2DDllUyz4RZufn7I0GEnPKrb/CB21Z8JYKnunAtZn41Dma/+xhg5xvN/USnIg9Eyyf2nbJgxMQ=="
|
|
258
|
+
},
|
|
259
|
+
"@octanejs/rspack-plugin": {
|
|
260
|
+
"request": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-2383d2ab1e70/octanejs-rspack-plugin-0.2.4.tgz",
|
|
261
|
+
"version": "0.2.4",
|
|
262
|
+
"integrity": "sha512-I8m/d/oj3Qh8nG5nqkWD90m8qgNwlPK9oNh5tlVvGNdSYCTLddRG7Og8wpYKFAGxe2D+0zOIhYGarC0ZKZgSzw=="
|
|
263
|
+
},
|
|
264
|
+
"@tanstack/router-core": {
|
|
265
|
+
"request": "https://github.com/BleedingDev/router/releases/download/ultramodern-router-core-585d3233f7f5/tanstack-router-core-1.171.38.tgz",
|
|
266
|
+
"version": "1.171.38",
|
|
267
|
+
"integrity": "sha512-d/aGvcyEVwDh2Cn9MuZM1n1dqTIqkFYi7AHY2Na/6x/a0jVSDVTNVVVY7QEsuKFXktaJF9zjVwetaRm/0MALZg=="
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"sourceName": "@modern-js/renderer-octane"
|
|
271
|
+
},
|
|
207
272
|
"scripts": {
|
|
208
273
|
"build": "rslib build && tsc -p tsconfig.types.json",
|
|
209
274
|
"test": "rstest"
|
|
@@ -211,8 +276,5 @@
|
|
|
211
276
|
"homepage": "https://github.com/ultramodernjs/ultramodern.js#readme",
|
|
212
277
|
"bugs": {
|
|
213
278
|
"url": "https://github.com/ultramodernjs/ultramodern.js/issues"
|
|
214
|
-
},
|
|
215
|
-
"ultramodern": {
|
|
216
|
-
"sourceName": "@modern-js/renderer-octane"
|
|
217
279
|
}
|
|
218
280
|
}
|
package/src/client.ts
CHANGED
|
@@ -24,6 +24,11 @@ import {
|
|
|
24
24
|
FederationApplication,
|
|
25
25
|
type OctaneFederationScope,
|
|
26
26
|
} from './federation-context';
|
|
27
|
+
import {
|
|
28
|
+
type OctaneWorkerFederationFactory,
|
|
29
|
+
type OctaneWorkerFederationScope,
|
|
30
|
+
WorkerFederationApplication,
|
|
31
|
+
} from './worker-federation-context';
|
|
27
32
|
|
|
28
33
|
export type { OctaneDocumentBootstrap } from './bootstrap';
|
|
29
34
|
export { readOctaneDocumentBootstrap } from './bootstrap';
|
|
@@ -50,9 +55,14 @@ export interface OctaneApplicationOptions {
|
|
|
50
55
|
readonly signal?: AbortSignal;
|
|
51
56
|
/** Hydration installs the native signal bridge before invoking this importer. */
|
|
52
57
|
readonly load: () => Promise<OctaneApplicationModule>;
|
|
53
|
-
readonly options?: Omit<RootOptions, 'signalOwner'>;
|
|
58
|
+
readonly options?: Omit<RootOptions, 'signalOwner' | 'externalSnapshots'>;
|
|
54
59
|
/** This browser compilation's native Module Federation runtime. */
|
|
55
60
|
readonly federation?: NativeFederationBinding;
|
|
61
|
+
readonly workerFederation?:
|
|
62
|
+
| OctaneWorkerFederationScope
|
|
63
|
+
| OctaneWorkerFederationFactory;
|
|
64
|
+
/** Trusted document bootstrap identity, also present for a CSR document. */
|
|
65
|
+
readonly documentId?: string;
|
|
56
66
|
}
|
|
57
67
|
|
|
58
68
|
export interface OctaneHydrationOptions extends OctaneApplicationOptions {
|
|
@@ -296,6 +306,8 @@ function createHandle(input: {
|
|
|
296
306
|
signal?: AbortSignal;
|
|
297
307
|
onCleanupError?: (error: unknown) => void;
|
|
298
308
|
federation?: OctaneFederationScope;
|
|
309
|
+
workerFederation?: OctaneWorkerFederationScope;
|
|
310
|
+
retireWorkerFederation?: () => void;
|
|
299
311
|
}): OctaneApplicationHandle {
|
|
300
312
|
let releaseModule = input.releaseModule;
|
|
301
313
|
let disposed = false;
|
|
@@ -310,12 +322,18 @@ function createHandle(input: {
|
|
|
310
322
|
const nextRelease = claimModuleResources(next);
|
|
311
323
|
releaseModule = nextRelease;
|
|
312
324
|
try {
|
|
313
|
-
input.
|
|
314
|
-
? input.root.render(
|
|
315
|
-
scope: input.
|
|
325
|
+
input.workerFederation
|
|
326
|
+
? input.root.render(WorkerFederationApplication, {
|
|
327
|
+
scope: input.workerFederation,
|
|
328
|
+
federation: input.federation,
|
|
316
329
|
application: next,
|
|
317
330
|
})
|
|
318
|
-
: input.
|
|
331
|
+
: input.federation
|
|
332
|
+
? input.root.render(FederationApplication, {
|
|
333
|
+
scope: input.federation,
|
|
334
|
+
application: next,
|
|
335
|
+
})
|
|
336
|
+
: input.root.render(next.default, next.props);
|
|
319
337
|
previousRelease();
|
|
320
338
|
} catch (error) {
|
|
321
339
|
cleanupResources([previousRelease, () => handle.dispose()]);
|
|
@@ -327,6 +345,7 @@ function createHandle(input: {
|
|
|
327
345
|
disposed = true;
|
|
328
346
|
input.signal?.removeEventListener('abort', onAbort);
|
|
329
347
|
cleanupResources([
|
|
348
|
+
() => input.retireWorkerFederation?.(),
|
|
330
349
|
() => input.root.unmount(),
|
|
331
350
|
() => releaseModule(),
|
|
332
351
|
() => input.bridge?.dispose(),
|
|
@@ -356,6 +375,21 @@ async function startApplication(
|
|
|
356
375
|
hydration?: { document: Document; documentId: string },
|
|
357
376
|
): Promise<OctaneApplicationHandle> {
|
|
358
377
|
const errors = observeRootErrors(input.options);
|
|
378
|
+
const workerController = input.workerFederation
|
|
379
|
+
? new AbortController()
|
|
380
|
+
: undefined;
|
|
381
|
+
let workerFederation: OctaneWorkerFederationScope | undefined;
|
|
382
|
+
const retireWorkerFederation = () =>
|
|
383
|
+
cleanupResources([
|
|
384
|
+
() =>
|
|
385
|
+
workerController?.abort(
|
|
386
|
+
new DOMException(
|
|
387
|
+
'The Worker federation document was disposed',
|
|
388
|
+
'AbortError',
|
|
389
|
+
),
|
|
390
|
+
),
|
|
391
|
+
() => workerFederation?.transport.dispose(),
|
|
392
|
+
]);
|
|
359
393
|
let bridge: StreamedSignalHydration | undefined;
|
|
360
394
|
let root: Root | undefined;
|
|
361
395
|
let releaseModule: (() => void) | undefined;
|
|
@@ -369,6 +403,7 @@ async function startApplication(
|
|
|
369
403
|
if (cleaned) return;
|
|
370
404
|
cleaned = true;
|
|
371
405
|
cleanupResources([
|
|
406
|
+
retireWorkerFederation,
|
|
372
407
|
() => root?.unmount(),
|
|
373
408
|
() => releaseModule?.(),
|
|
374
409
|
() => bridge?.dispose(),
|
|
@@ -376,10 +411,30 @@ async function startApplication(
|
|
|
376
411
|
]);
|
|
377
412
|
};
|
|
378
413
|
try {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
414
|
+
if (input.workerFederation && workerController) {
|
|
415
|
+
const signal = AbortSignal.any([
|
|
416
|
+
workerController.signal,
|
|
417
|
+
...(input.signal ? [input.signal] : []),
|
|
418
|
+
]);
|
|
419
|
+
const scope =
|
|
420
|
+
typeof input.workerFederation === 'function'
|
|
421
|
+
? input.workerFederation(signal)
|
|
422
|
+
: input.workerFederation;
|
|
423
|
+
workerFederation = {
|
|
424
|
+
...scope,
|
|
425
|
+
signal: scope.signal ? AbortSignal.any([signal, scope.signal]) : signal,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (workerFederation && !hydration && !input.documentId)
|
|
429
|
+
throw new Error(
|
|
430
|
+
'Worker federation requires the trusted document identity before application loading',
|
|
431
|
+
);
|
|
432
|
+
// Capture the host before imports and retain Worker SSR's provider ranges
|
|
433
|
+
// even when no regular Module Federation binding is configured.
|
|
434
|
+
const federation =
|
|
435
|
+
input.federation || workerFederation
|
|
436
|
+
? createFederationScope(input.federation, false)
|
|
437
|
+
: undefined;
|
|
383
438
|
if (hydration) {
|
|
384
439
|
const { document, documentId } = hydration;
|
|
385
440
|
bridge = bootstrapStreamedSignalHydration({
|
|
@@ -402,15 +457,41 @@ async function startApplication(
|
|
|
402
457
|
if (bridge) {
|
|
403
458
|
root = hydrateRoot(
|
|
404
459
|
input.container,
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
460
|
+
workerFederation
|
|
461
|
+
? WorkerFederationApplication
|
|
462
|
+
: federation
|
|
463
|
+
? FederationApplication
|
|
464
|
+
: application.default,
|
|
465
|
+
workerFederation
|
|
466
|
+
? { scope: workerFederation, federation, application }
|
|
467
|
+
: federation
|
|
468
|
+
? { scope: federation, application }
|
|
469
|
+
: application.props,
|
|
470
|
+
{
|
|
471
|
+
...errors.options,
|
|
472
|
+
signalOwner: bridge.signalOwner,
|
|
473
|
+
externalSnapshots: { documentId: hydration!.documentId },
|
|
474
|
+
},
|
|
408
475
|
);
|
|
409
476
|
} else {
|
|
410
|
-
root = createRoot(input.container,
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
477
|
+
root = createRoot(input.container, {
|
|
478
|
+
...errors.options,
|
|
479
|
+
...(input.documentId
|
|
480
|
+
? { externalSnapshots: { documentId: input.documentId } }
|
|
481
|
+
: {}),
|
|
482
|
+
});
|
|
483
|
+
workerFederation
|
|
484
|
+
? root.render(WorkerFederationApplication, {
|
|
485
|
+
scope: workerFederation,
|
|
486
|
+
federation,
|
|
487
|
+
application,
|
|
488
|
+
})
|
|
489
|
+
: federation
|
|
490
|
+
? root.render(FederationApplication, {
|
|
491
|
+
scope: federation,
|
|
492
|
+
application,
|
|
493
|
+
})
|
|
494
|
+
: root.render(application.default, application.props);
|
|
414
495
|
}
|
|
415
496
|
errors.assertInitialRender();
|
|
416
497
|
input.signal?.throwIfAborted();
|
|
@@ -421,6 +502,8 @@ async function startApplication(
|
|
|
421
502
|
release,
|
|
422
503
|
bridge,
|
|
423
504
|
federation,
|
|
505
|
+
workerFederation,
|
|
506
|
+
retireWorkerFederation,
|
|
424
507
|
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
425
508
|
onCleanupError: error => reportCleanupError(input, error),
|
|
426
509
|
});
|
package/src/entry-application.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { type ComponentBody, createElement } from 'octane';
|
|
11
11
|
import { I18nProvider } from './i18n/I18nProvider';
|
|
12
12
|
import type { I18nInstanceLike } from './i18n/types';
|
|
13
|
+
import { associateOctaneFileRouteSnapshot } from './router-external-snapshot';
|
|
13
14
|
import {
|
|
14
15
|
createFileSystemRouteTree,
|
|
15
16
|
type FileSystemRouteModule,
|
|
@@ -41,8 +42,8 @@ export const octaneRouterFactory: NativeRouterFactory<AnyRoute, AnyRouter> = {
|
|
|
41
42
|
modules as Readonly<Record<string, FileSystemRouteModule>>,
|
|
42
43
|
options,
|
|
43
44
|
),
|
|
44
|
-
router: ({ location, ...options }) =>
|
|
45
|
-
createRouter({
|
|
45
|
+
router: ({ location, ...options }) => {
|
|
46
|
+
const router = createRouter({
|
|
46
47
|
...options,
|
|
47
48
|
...(location
|
|
48
49
|
? {
|
|
@@ -50,7 +51,10 @@ export const octaneRouterFactory: NativeRouterFactory<AnyRoute, AnyRouter> = {
|
|
|
50
51
|
history: createMemoryHistory({ initialEntries: [location.href] }),
|
|
51
52
|
}
|
|
52
53
|
: {}),
|
|
53
|
-
})
|
|
54
|
+
});
|
|
55
|
+
associateOctaneFileRouteSnapshot(router);
|
|
56
|
+
return router;
|
|
57
|
+
},
|
|
54
58
|
};
|
|
55
59
|
|
|
56
60
|
interface LocalizedRouterProps {
|
package/src/entry-client.ts
CHANGED
|
@@ -21,11 +21,18 @@ import {
|
|
|
21
21
|
OctaneRouterRoot,
|
|
22
22
|
prepareOctaneRouterHydration,
|
|
23
23
|
} from './router-client';
|
|
24
|
+
import type {
|
|
25
|
+
OctaneWorkerFederationFactory,
|
|
26
|
+
OctaneWorkerFederationScope,
|
|
27
|
+
} from './worker-federation-context';
|
|
24
28
|
|
|
25
29
|
export interface OctaneClientEntryOptions
|
|
26
30
|
extends NativeClientEntryOptions<NativeI18nInstance, LocalisedUrlsOption> {
|
|
27
31
|
/** The native client compilation hash, `__webpack_hash__`. */
|
|
28
32
|
readonly nativeHydrationBuildId: string;
|
|
33
|
+
readonly workerFederation?:
|
|
34
|
+
| OctaneWorkerFederationScope
|
|
35
|
+
| OctaneWorkerFederationFactory;
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
const LocalizedRouterRoot = localizedRouterRoot(OctaneRouterRoot);
|
|
@@ -38,6 +45,7 @@ export function startNativeClient(options: OctaneClientEntryOptions): void {
|
|
|
38
45
|
readOctaneDocumentBootstrap(document, identity, nativeHydrationBuildId),
|
|
39
46
|
createRouter: (application, routerOptions) =>
|
|
40
47
|
createNativeRouter(application, routerOptions, octaneRouterFactory),
|
|
48
|
+
disposeRouter: router => router.history.destroy(),
|
|
41
49
|
async prepareRouter(router, hydrating, signal) {
|
|
42
50
|
// Hydration adopts the server's matches; a fresh mount loads its own.
|
|
43
51
|
if (hydrating) await prepareOctaneRouterHydration(router, { signal });
|
|
@@ -49,6 +57,8 @@ export function startNativeClient(options: OctaneClientEntryOptions): void {
|
|
|
49
57
|
identity,
|
|
50
58
|
nativeHydrationBuildId,
|
|
51
59
|
federation: options.federation,
|
|
60
|
+
workerFederation: options.workerFederation,
|
|
61
|
+
documentId: bootstrap?.documentId,
|
|
52
62
|
signal,
|
|
53
63
|
// Hydration installs the native signal bridge before this importer runs.
|
|
54
64
|
load: async (): Promise<OctaneApplicationModule> => {
|
package/src/entry-server.ts
CHANGED
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
import { validateOctaneModuleManifest } from './manifest';
|
|
24
24
|
import {
|
|
25
25
|
createOctaneRequestHandler,
|
|
26
|
-
createOctaneRouterInjection,
|
|
27
26
|
createSsrStreamResponse,
|
|
27
|
+
getSsrStatus,
|
|
28
28
|
OctaneRouterServer,
|
|
29
29
|
} from './router-server';
|
|
30
30
|
import { renderOctaneApplication, renderOctaneCSRDocument } from './server';
|
|
@@ -52,10 +52,12 @@ export function withOctaneDocumentFields(
|
|
|
52
52
|
: policy;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
export { createNativeWorkerFederationRuntime } from './worker-federation';
|
|
56
|
+
|
|
57
|
+
export interface OctaneServerEntryOptions
|
|
58
|
+
extends NativeServerEntryOptions<NativeI18nInstance, LocalisedUrlsOption> {
|
|
59
|
+
readonly workerFederationLocale?: string;
|
|
60
|
+
}
|
|
59
61
|
|
|
60
62
|
const LocalizedRouterServer = localizedRouterRoot(OctaneRouterServer);
|
|
61
63
|
|
|
@@ -77,16 +79,23 @@ export function createNativeServerEntry(
|
|
|
77
79
|
createNativeRouter(application, routerOptions, octaneRouterFactory),
|
|
78
80
|
renderCSR: ({ session }, document) =>
|
|
79
81
|
renderOctaneCSRDocument({ session, document }),
|
|
80
|
-
renderComponent: (
|
|
82
|
+
renderComponent: (
|
|
83
|
+
{ session, workerFederation },
|
|
84
|
+
component,
|
|
85
|
+
document,
|
|
86
|
+
i18n,
|
|
87
|
+
) =>
|
|
81
88
|
renderOctaneApplication({
|
|
82
89
|
session,
|
|
83
90
|
App: componentView(component, i18n) as ServerRenderNode,
|
|
84
91
|
document,
|
|
85
92
|
federation: options.federation,
|
|
93
|
+
workerFederation,
|
|
94
|
+
workerFederationLocale: options.workerFederationLocale,
|
|
86
95
|
}),
|
|
87
96
|
async renderRoutes({
|
|
88
97
|
request,
|
|
89
|
-
context: { session },
|
|
98
|
+
context: { session, workerFederation },
|
|
90
99
|
router,
|
|
91
100
|
outcomes,
|
|
92
101
|
document,
|
|
@@ -100,7 +109,7 @@ export function createNativeServerEntry(
|
|
|
100
109
|
serialization: { forbiddenValues },
|
|
101
110
|
})(async ({ router, responseHeaders }) => {
|
|
102
111
|
const metadata = mergeDataResponseMetadata(outcomes, {
|
|
103
|
-
status: router
|
|
112
|
+
status: getSsrStatus(router),
|
|
104
113
|
});
|
|
105
114
|
// Route headers() take precedence over loader singleton fields; list
|
|
106
115
|
// fields keep both.
|
|
@@ -127,7 +136,9 @@ export function createNativeServerEntry(
|
|
|
127
136
|
}),
|
|
128
137
|
document,
|
|
129
138
|
federation: options.federation,
|
|
130
|
-
|
|
139
|
+
workerFederation,
|
|
140
|
+
workerFederationLocale: options.workerFederationLocale,
|
|
141
|
+
router,
|
|
131
142
|
});
|
|
132
143
|
return createSsrStreamResponse(router, rendered);
|
|
133
144
|
});
|