@bleedingdev/modern-js-app-tools 3.5.0-ultramodern.9 → 3.5.0-ultramodern.90
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/bin/modern.js +0 -0
- package/dist/cjs/builder/generator/getBuilderEnvironments.js +13 -16
- package/dist/cjs/builder/shared/builderPlugins/adapterPrecompress.js +13 -4
- package/dist/cjs/builder/shared/builderPlugins/adapterSSR.js +14 -11
- package/dist/cjs/builder/shared/bundlerPlugins/CssExtractRuntimePlugin.js +72 -0
- package/dist/cjs/builder/shared/bundlerPlugins/RouterPlugin.js +28 -11
- package/dist/cjs/builder/shared/bundlerPlugins/index.js +13 -6
- package/dist/cjs/builder/shared/lazyCompilation.js +2 -10
- package/dist/cjs/commands/index.js +0 -4
- package/dist/cjs/config/build-environment.js +268 -0
- package/dist/cjs/config/index.js +11 -4
- package/dist/cjs/config/public.js +46 -0
- package/dist/cjs/index.js +39 -62
- package/dist/cjs/plugins/analyze/getServerRoutes.js +19 -0
- package/dist/cjs/plugins/analyze/index.js +20 -12
- package/dist/cjs/plugins/backend-federation/codegen.js +255 -0
- package/dist/cjs/plugins/backend-federation/config.js +204 -0
- package/dist/cjs/plugins/backend-federation/emit.js +148 -0
- package/dist/cjs/plugins/backendFederationBuild.js +53 -0
- package/dist/cjs/plugins/deploy/index.js +4 -4
- package/dist/cjs/plugins/deploy/platforms/cloudflare/artifacts.js +127 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/constants.js +141 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/delivery-unit.js +139 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/i18n-worker.js +135 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/index.js +150 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/security-policies.js +205 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/types.js +18 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/utils.js +66 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/worker-manifest.js +208 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare/wrangler-config.js +204 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-contract.js +108 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-plan.js +93 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier/identity.js +83 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier/index.js +188 -0
- package/dist/cjs/{baseline.js → plugins/deploy/platforms/cloudflare-output-verifier/issues.js} +19 -10
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier/manifest.js +89 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier/mutation-policy.js +151 -0
- package/dist/cjs/plugins/deploy/platforms/cloudflare-output-verifier/worker-bundles.js +302 -0
- package/dist/cjs/plugins/deploy/platforms/node.js +20 -2
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.001-bootstrap-security.mjs +250 -0
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.004-rendering-css.mjs +1012 -0
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.005-worker-dispatch.mjs +363 -0
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-worker-fs-promises.mjs +8 -4
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-worker-loadable-server.mjs +251 -155
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-worker-path.mjs +78 -39
- package/dist/cjs/plugins/deploy/platforms/templates/netlify-entry.cjs +62 -41
- package/dist/cjs/plugins/deploy/platforms/templates/netlify-entry.mjs +63 -41
- package/dist/cjs/plugins/deploy/platforms/templates/node-entry.cjs +52 -35
- package/dist/cjs/plugins/deploy/platforms/templates/node-entry.mjs +53 -35
- package/dist/cjs/plugins/deploy/platforms/templates/vercel-entry.cjs +61 -41
- package/dist/cjs/plugins/deploy/platforms/templates/vercel-entry.mjs +61 -40
- package/dist/cjs/plugins/deploy/utils/npmAliases.js +226 -0
- package/dist/cjs/plugins/ultramodernReleaseEnvelope.js +100 -0
- package/dist/cjs/presetUltramodern.js +33 -2
- package/dist/cjs/ultramodern-release-envelope/canonical.js +68 -0
- package/dist/cjs/ultramodern-release-envelope/framework-output.js +597 -0
- package/dist/cjs/ultramodern-release-envelope/index.js +399 -0
- package/dist/cjs/ultramodern-release-envelope/types.js +51 -0
- package/dist/cjs/ultramodern-release-identity.js +110 -0
- package/dist/esm/builder/generator/getBuilderEnvironments.mjs +12 -15
- package/dist/esm/builder/shared/builderPlugins/adapterPrecompress.mjs +13 -4
- package/dist/esm/builder/shared/builderPlugins/adapterSSR.mjs +15 -12
- package/dist/esm/builder/shared/bundlerPlugins/CssExtractRuntimePlugin.mjs +30 -0
- package/dist/esm/builder/shared/bundlerPlugins/RouterPlugin.mjs +24 -10
- package/dist/esm/builder/shared/bundlerPlugins/index.mjs +1 -0
- package/dist/esm/builder/shared/lazyCompilation.mjs +1 -3
- package/dist/esm/commands/index.mjs +0 -1
- package/dist/esm/config/build-environment.mjs +224 -0
- package/dist/esm/config/index.mjs +1 -0
- package/dist/esm/config/public.mjs +1 -0
- package/dist/esm/index.mjs +5 -4
- package/dist/esm/plugins/analyze/getHtmlTemplate.mjs +2 -2
- package/dist/esm/plugins/analyze/getServerRoutes.mjs +17 -1
- package/dist/esm/plugins/analyze/index.mjs +20 -12
- package/dist/esm/plugins/analyze/isDefaultExportFunction.mjs +2 -2
- package/dist/esm/plugins/backend-federation/codegen.mjs +204 -0
- package/dist/esm/plugins/backend-federation/config.mjs +128 -0
- package/dist/esm/plugins/backend-federation/emit.mjs +97 -0
- package/dist/esm/plugins/backendFederationBuild.mjs +1 -0
- package/dist/esm/plugins/deploy/index.mjs +1 -1
- package/dist/esm/plugins/deploy/platforms/cloudflare/artifacts.mjs +64 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/constants.mjs +34 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/delivery-unit.mjs +88 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/i18n-worker.mjs +97 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/index.mjs +102 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/security-policies.mjs +167 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/types.mjs +0 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/utils.mjs +12 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/worker-manifest.mjs +148 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare/wrangler-config.mjs +150 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-contract.mjs +31 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-plan.mjs +45 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier/identity.mjs +45 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier/index.mjs +133 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier/issues.mjs +10 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier/manifest.mjs +51 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier/mutation-policy.mjs +99 -0
- package/dist/esm/plugins/deploy/platforms/cloudflare-output-verifier/worker-bundles.mjs +238 -0
- package/dist/esm/plugins/deploy/platforms/node.mjs +20 -2
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.001-bootstrap-security.mjs +250 -0
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.004-rendering-css.mjs +1012 -0
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.005-worker-dispatch.mjs +363 -0
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-worker-fs-promises.mjs +8 -4
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-worker-loadable-server.mjs +251 -155
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-worker-path.mjs +78 -39
- package/dist/esm/plugins/deploy/platforms/templates/netlify-entry.cjs +62 -41
- package/dist/esm/plugins/deploy/platforms/templates/netlify-entry.mjs +63 -41
- package/dist/esm/plugins/deploy/platforms/templates/node-entry.cjs +52 -35
- package/dist/esm/plugins/deploy/platforms/templates/node-entry.mjs +53 -35
- package/dist/esm/plugins/deploy/platforms/templates/vercel-entry.cjs +61 -41
- package/dist/esm/plugins/deploy/platforms/templates/vercel-entry.mjs +61 -40
- package/dist/esm/plugins/deploy/utils/npmAliases.mjs +174 -0
- package/dist/esm/plugins/ultramodernReleaseEnvelope.mjs +52 -0
- package/dist/esm/presetUltramodern.mjs +33 -2
- package/dist/esm/ultramodern-release-envelope/canonical.mjs +21 -0
- package/dist/esm/ultramodern-release-envelope/framework-output.mjs +524 -0
- package/dist/esm/ultramodern-release-envelope/index.mjs +335 -0
- package/dist/esm/ultramodern-release-envelope/types.mjs +7 -0
- package/dist/esm/ultramodern-release-identity.mjs +66 -0
- package/dist/esm-node/builder/generator/getBuilderEnvironments.mjs +12 -15
- package/dist/esm-node/builder/shared/builderPlugins/adapterPrecompress.mjs +13 -4
- package/dist/esm-node/builder/shared/builderPlugins/adapterSSR.mjs +15 -12
- package/dist/esm-node/builder/shared/bundlerPlugins/CssExtractRuntimePlugin.mjs +31 -0
- package/dist/esm-node/builder/shared/bundlerPlugins/RouterPlugin.mjs +24 -10
- package/dist/esm-node/builder/shared/bundlerPlugins/index.mjs +1 -0
- package/dist/esm-node/builder/shared/lazyCompilation.mjs +1 -3
- package/dist/esm-node/commands/index.mjs +0 -1
- package/dist/esm-node/config/build-environment.mjs +225 -0
- package/dist/esm-node/config/index.mjs +1 -0
- package/dist/esm-node/config/public.mjs +2 -0
- package/dist/esm-node/index.mjs +5 -4
- package/dist/esm-node/plugins/analyze/getHtmlTemplate.mjs +2 -2
- package/dist/esm-node/plugins/analyze/getServerRoutes.mjs +17 -1
- package/dist/esm-node/plugins/analyze/index.mjs +20 -12
- package/dist/esm-node/plugins/analyze/isDefaultExportFunction.mjs +2 -2
- package/dist/esm-node/plugins/backend-federation/codegen.mjs +205 -0
- package/dist/esm-node/plugins/backend-federation/config.mjs +129 -0
- package/dist/esm-node/plugins/backend-federation/emit.mjs +98 -0
- package/dist/esm-node/plugins/backendFederationBuild.mjs +2 -0
- package/dist/esm-node/plugins/deploy/index.mjs +1 -1
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/artifacts.mjs +65 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/constants.mjs +35 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/delivery-unit.mjs +89 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/i18n-worker.mjs +98 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/index.mjs +103 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/security-policies.mjs +168 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/types.mjs +1 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/utils.mjs +13 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/worker-manifest.mjs +149 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare/wrangler-config.mjs +151 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-contract.mjs +32 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-plan.mjs +46 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier/identity.mjs +46 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier/index.mjs +134 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier/issues.mjs +11 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier/manifest.mjs +52 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier/mutation-policy.mjs +100 -0
- package/dist/esm-node/plugins/deploy/platforms/cloudflare-output-verifier/worker-bundles.mjs +239 -0
- package/dist/esm-node/plugins/deploy/platforms/node.mjs +20 -2
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.001-bootstrap-security.mjs +250 -0
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.004-rendering-css.mjs +1012 -0
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.005-worker-dispatch.mjs +363 -0
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-worker-fs-promises.mjs +8 -4
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-worker-loadable-server.mjs +251 -155
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-worker-path.mjs +78 -39
- package/dist/esm-node/plugins/deploy/platforms/templates/netlify-entry.cjs +62 -41
- package/dist/esm-node/plugins/deploy/platforms/templates/netlify-entry.mjs +63 -41
- package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.cjs +52 -35
- package/dist/esm-node/plugins/deploy/platforms/templates/node-entry.mjs +53 -35
- package/dist/esm-node/plugins/deploy/platforms/templates/vercel-entry.cjs +61 -41
- package/dist/esm-node/plugins/deploy/platforms/templates/vercel-entry.mjs +61 -40
- package/dist/esm-node/plugins/deploy/utils/npmAliases.mjs +175 -0
- package/dist/esm-node/plugins/ultramodernReleaseEnvelope.mjs +53 -0
- package/dist/esm-node/presetUltramodern.mjs +33 -2
- package/dist/esm-node/ultramodern-release-envelope/canonical.mjs +22 -0
- package/dist/esm-node/ultramodern-release-envelope/framework-output.mjs +525 -0
- package/dist/esm-node/ultramodern-release-envelope/index.mjs +336 -0
- package/dist/esm-node/ultramodern-release-envelope/types.mjs +8 -0
- package/dist/esm-node/ultramodern-release-identity.mjs +67 -0
- package/dist/types/builder/generator/createCopyPattern.d.ts +7 -5
- package/dist/types/builder/shared/bundlerPlugins/CssExtractRuntimePlugin.d.ts +6 -0
- package/dist/types/builder/shared/bundlerPlugins/RouterPlugin.d.ts +1 -0
- package/dist/types/builder/shared/bundlerPlugins/index.d.ts +1 -0
- package/dist/types/builder/shared/lazyCompilation.d.ts +2 -4
- package/dist/types/commands/index.d.ts +0 -1
- package/dist/types/config/build-environment.d.ts +22 -0
- package/dist/types/config/index.d.ts +1 -0
- package/dist/types/config/public.d.ts +2 -0
- package/dist/types/index.d.ts +0 -2
- package/dist/types/plugins/analyze/getServerRoutes.d.ts +1 -0
- package/dist/types/plugins/backend-federation/codegen.d.ts +83 -0
- package/dist/types/plugins/backend-federation/config.d.ts +103 -0
- package/dist/types/plugins/backend-federation/emit.d.ts +13 -0
- package/dist/types/plugins/backendFederationBuild.d.ts +2 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/artifacts.d.ts +15 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/constants.d.ts +24 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/delivery-unit.d.ts +23 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/i18n-worker.d.ts +22 -0
- package/dist/types/plugins/deploy/platforms/{cloudflare.d.ts → cloudflare/index.d.ts} +1 -1
- package/dist/types/plugins/deploy/platforms/cloudflare/security-policies.d.ts +51 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/types.d.ts +5 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/utils.d.ts +6 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/worker-manifest.d.ts +122 -0
- package/dist/types/plugins/deploy/platforms/cloudflare/wrangler-config.d.ts +46 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-contract.d.ts +14 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-plan.d.ts +34 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier/identity.d.ts +4 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier/index.d.ts +18 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier/issues.d.ts +14 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier/manifest.d.ts +2 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier/mutation-policy.d.ts +14 -0
- package/dist/types/plugins/deploy/platforms/cloudflare-output-verifier/worker-bundles.d.ts +20 -0
- package/dist/types/plugins/deploy/platforms/templates/cloudflare-entry.001-bootstrap-security.d.mts +1 -0
- package/dist/types/plugins/deploy/platforms/templates/cloudflare-entry.002-assets-routes.d.mts +1 -0
- package/dist/types/plugins/deploy/platforms/templates/cloudflare-entry.003-i18n-locales.d.mts +1 -0
- package/dist/types/plugins/deploy/platforms/templates/cloudflare-entry.004-rendering-css.d.mts +1 -0
- package/dist/types/plugins/deploy/platforms/templates/cloudflare-entry.005-worker-dispatch.d.mts +1 -0
- package/dist/types/plugins/deploy/utils/npmAliases.d.ts +14 -0
- package/dist/types/plugins/ultramodernReleaseEnvelope.d.ts +3 -0
- package/dist/types/presetUltramodern.d.ts +10 -0
- package/dist/types/run/index.d.ts +1 -1
- package/dist/types/types/config/cloudflareDeploy.d.ts +41 -0
- package/dist/types/types/config/deploy.d.ts +15 -2
- package/dist/types/ultramodern-release-envelope/canonical.d.ts +5 -0
- package/dist/types/ultramodern-release-envelope/framework-output.d.ts +31 -0
- package/dist/types/ultramodern-release-envelope/index.d.ts +6 -0
- package/dist/types/ultramodern-release-envelope/types.d.ts +62 -0
- package/dist/types/ultramodern-release-identity.d.ts +16 -0
- package/lib/types.d.ts +2 -3
- package/package.json +38 -23
- package/rslib.config.mts +11 -12
- package/dist/cjs/commands/runtime.js +0 -196
- package/dist/cjs/plugins/deploy/platforms/cloudflare.js +0 -540
- package/dist/cjs/plugins/deploy/platforms/templates/cloudflare-entry.mjs +0 -576
- package/dist/cjs/ultramodern/designSystem.js +0 -123
- package/dist/esm/baseline.mjs +0 -4
- package/dist/esm/commands/runtime.mjs +0 -146
- package/dist/esm/plugins/deploy/platforms/cloudflare.mjs +0 -492
- package/dist/esm/plugins/deploy/platforms/templates/cloudflare-entry.mjs +0 -576
- package/dist/esm/ultramodern/designSystem.mjs +0 -73
- package/dist/esm-node/baseline.mjs +0 -5
- package/dist/esm-node/commands/runtime.mjs +0 -147
- package/dist/esm-node/plugins/deploy/platforms/cloudflare.mjs +0 -493
- package/dist/esm-node/plugins/deploy/platforms/templates/cloudflare-entry.mjs +0 -576
- package/dist/esm-node/ultramodern/designSystem.mjs +0 -74
- package/dist/types/baseline.d.ts +0 -16
- package/dist/types/commands/runtime.d.ts +0 -12
- package/dist/types/ultramodern/designSystem.d.ts +0 -54
- /package/dist/types/plugins/deploy/platforms/templates/{cloudflare-entry.d.mts → cloudflare-entry.006-fetch-handler.d.mts} +0 -0
|
@@ -0,0 +1,1012 @@
|
|
|
1
|
+
function createNoopMonitors() {
|
|
2
|
+
const noop = () => {};
|
|
3
|
+
|
|
4
|
+
return {
|
|
5
|
+
debug: noop,
|
|
6
|
+
error: noop,
|
|
7
|
+
info: noop,
|
|
8
|
+
warn: noop,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY = '__modernDistributedSsrFragments';
|
|
13
|
+
const DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY =
|
|
14
|
+
'__modernDistributedSsrFragmentRequest';
|
|
15
|
+
const DISTRIBUTED_SSR_CSS_HEADER = 'x-modern-distributed-ssr-css';
|
|
16
|
+
const DISTRIBUTED_SSR_PROVENANCE_HEADER = 'x-modern-distributed-ssr-provenance';
|
|
17
|
+
|
|
18
|
+
function distributedSsrFragmentKey(remote, expose) {
|
|
19
|
+
return `${remote}::${expose}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function escapeFragmentRegExp(value) {
|
|
23
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function openingTagHasAttribute(openingTag, name, value) {
|
|
27
|
+
const pattern = new RegExp(
|
|
28
|
+
`\\s${escapeFragmentRegExp(name)}=(?:"${escapeFragmentRegExp(value)}"|'${escapeFragmentRegExp(value)}')`,
|
|
29
|
+
'u',
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return pattern.test(openingTag);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function extractRenderedBoundaryElement(html, boundaryId, expose) {
|
|
36
|
+
const boundaryPattern = new RegExp(
|
|
37
|
+
`\\sdata-modern-boundary-id=(?:"${escapeFragmentRegExp(boundaryId)}"|'${escapeFragmentRegExp(boundaryId)}')`,
|
|
38
|
+
'u',
|
|
39
|
+
);
|
|
40
|
+
const boundaryMatch = boundaryPattern.exec(html);
|
|
41
|
+
if (!boundaryMatch) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const openingStart = html.lastIndexOf('<', boundaryMatch.index);
|
|
46
|
+
const openingEnd = html.indexOf('>', boundaryMatch.index);
|
|
47
|
+
if (openingStart < 0 || openingEnd < 0) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const openingTag = html.slice(openingStart, openingEnd + 1);
|
|
52
|
+
const tagName = /^<([a-z][\w:-]*)\b/iu.exec(openingTag)?.[1];
|
|
53
|
+
if (
|
|
54
|
+
!tagName ||
|
|
55
|
+
!openingTagHasAttribute(openingTag, 'data-modern-mf-expose', expose)
|
|
56
|
+
) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const tagPattern = new RegExp(
|
|
61
|
+
`<\\/?${escapeFragmentRegExp(tagName)}\\b[^>]*>`,
|
|
62
|
+
'giu',
|
|
63
|
+
);
|
|
64
|
+
let depth = 0;
|
|
65
|
+
|
|
66
|
+
for (const tagMatch of html.slice(openingStart).matchAll(tagPattern)) {
|
|
67
|
+
const tag = tagMatch[0];
|
|
68
|
+
const absoluteStart = openingStart + (tagMatch.index ?? 0);
|
|
69
|
+
if (tag.startsWith('</')) {
|
|
70
|
+
depth -= 1;
|
|
71
|
+
if (depth === 0) {
|
|
72
|
+
return html.slice(openingStart, absoluteStart + tag.length);
|
|
73
|
+
}
|
|
74
|
+
} else if (!tag.endsWith('/>')) {
|
|
75
|
+
depth += 1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function findFragmentMarker(html, boundaryId, expose, marker, fromIndex = 0) {
|
|
83
|
+
const tagPattern = /<template\b[^>]*>/giu;
|
|
84
|
+
tagPattern.lastIndex = fromIndex;
|
|
85
|
+
|
|
86
|
+
for (const match of html.matchAll(tagPattern)) {
|
|
87
|
+
const tag = match[0];
|
|
88
|
+
if (
|
|
89
|
+
openingTagHasAttribute(tag, 'data-modern-boundary-id', boundaryId) &&
|
|
90
|
+
openingTagHasAttribute(tag, 'data-modern-mf-expose', expose) &&
|
|
91
|
+
openingTagHasAttribute(tag, 'data-modern-distributed-ssr-marker', marker)
|
|
92
|
+
) {
|
|
93
|
+
return {
|
|
94
|
+
end: (match.index ?? 0) + tag.length,
|
|
95
|
+
start: match.index ?? 0,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function extractRenderedFragmentHtml(html, boundaryId, expose) {
|
|
104
|
+
const start = findFragmentMarker(html, boundaryId, expose, 'start');
|
|
105
|
+
if (start) {
|
|
106
|
+
const startClose = html.indexOf('</template>', start.end);
|
|
107
|
+
const contentStart =
|
|
108
|
+
startClose === -1 ? start.end : startClose + '</template>'.length;
|
|
109
|
+
const end = findFragmentMarker(
|
|
110
|
+
html,
|
|
111
|
+
boundaryId,
|
|
112
|
+
expose,
|
|
113
|
+
'end',
|
|
114
|
+
contentStart,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
if (end && end.start >= contentStart) {
|
|
118
|
+
return html.slice(contentStart, end.start);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return extractRenderedBoundaryElement(html, boundaryId, expose);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function readOpeningTagAttribute(openingTag, name) {
|
|
126
|
+
const pattern = new RegExp(
|
|
127
|
+
`\\s${escapeFragmentRegExp(name)}=(?:"([^"]*)"|'([^']*)')`,
|
|
128
|
+
'iu',
|
|
129
|
+
);
|
|
130
|
+
const match = pattern.exec(openingTag);
|
|
131
|
+
|
|
132
|
+
return match?.[1] ?? match?.[2];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function collectStylesheetHrefs(html) {
|
|
136
|
+
const hrefs = [];
|
|
137
|
+
|
|
138
|
+
for (const match of html.matchAll(/<link\b[^>]*>/giu)) {
|
|
139
|
+
const link = match[0];
|
|
140
|
+
const rel = readOpeningTagAttribute(link, 'rel');
|
|
141
|
+
const href = readOpeningTagAttribute(link, 'href');
|
|
142
|
+
|
|
143
|
+
if (href && rel?.split(/\s+/u).includes('stylesheet')) {
|
|
144
|
+
hrefs.push(href);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return hrefs;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function dedupeStylesheetLinks(html) {
|
|
152
|
+
const seenHrefs = new Set();
|
|
153
|
+
|
|
154
|
+
return html.replace(/<link\b[^>]*>/giu, link => {
|
|
155
|
+
const rel = readOpeningTagAttribute(link, 'rel');
|
|
156
|
+
const href = readOpeningTagAttribute(link, 'href');
|
|
157
|
+
|
|
158
|
+
if (!href || !rel?.split(/\s+/u).includes('stylesheet')) {
|
|
159
|
+
return link;
|
|
160
|
+
}
|
|
161
|
+
if (seenHrefs.has(href)) {
|
|
162
|
+
return '';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
seenHrefs.add(href);
|
|
166
|
+
return link;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function readFragmentStylesheetAssets(response) {
|
|
171
|
+
const value = response.headers.get(DISTRIBUTED_SSR_CSS_HEADER);
|
|
172
|
+
|
|
173
|
+
if (value === null) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
const assets = JSON.parse(value);
|
|
179
|
+
|
|
180
|
+
return Array.isArray(assets) &&
|
|
181
|
+
assets.every(asset => typeof asset === 'string' && asset.endsWith('.css'))
|
|
182
|
+
? assets
|
|
183
|
+
: undefined;
|
|
184
|
+
} catch {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function resolveFragmentStylesheetHrefs(
|
|
190
|
+
stylesheetAssets,
|
|
191
|
+
fragment,
|
|
192
|
+
fragmentUrl,
|
|
193
|
+
request,
|
|
194
|
+
env,
|
|
195
|
+
) {
|
|
196
|
+
const hostManifest = await readAssetJson('mf-manifest.json', request, env);
|
|
197
|
+
const remote = (
|
|
198
|
+
Array.isArray(hostManifest?.remotes) ? hostManifest.remotes : []
|
|
199
|
+
).find(
|
|
200
|
+
candidate =>
|
|
201
|
+
candidate?.alias === fragment.remote ||
|
|
202
|
+
candidate?.federationContainerName === fragment.boundaryId,
|
|
203
|
+
);
|
|
204
|
+
const manifestUrl = remote
|
|
205
|
+
? getRemoteManifestUrl(remote, request)
|
|
206
|
+
: undefined;
|
|
207
|
+
const publicBase = manifestUrl
|
|
208
|
+
? new URL('.', manifestUrl).toString()
|
|
209
|
+
: undefined;
|
|
210
|
+
const hrefs = stylesheetAssets.map(href => {
|
|
211
|
+
const resolved = new URL(href, fragmentUrl);
|
|
212
|
+
|
|
213
|
+
if (
|
|
214
|
+
publicBase &&
|
|
215
|
+
(!isAbsoluteUrl(href) || resolved.origin === fragmentUrl.origin)
|
|
216
|
+
) {
|
|
217
|
+
return new URL(href.replace(/^\/+/u, ''), publicBase).toString();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return resolved.toString();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
return [...new Set(hrefs)];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function createHydratableFragmentHtml(fragmentHtml) {
|
|
227
|
+
return `<!--$-->${fragmentHtml}<!--/$-->`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async function sha256Hex(value) {
|
|
231
|
+
const bytes = new Uint8Array(
|
|
232
|
+
await crypto.subtle.digest('SHA-256', new TextEncoder().encode(value)),
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
return [...bytes].map(byte => byte.toString(16).padStart(2, '0')).join('');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function serializeDistributedSsrProps(props) {
|
|
239
|
+
const seen = new WeakSet();
|
|
240
|
+
const serialized = JSON.stringify(props, (_key, value) => {
|
|
241
|
+
if (
|
|
242
|
+
typeof value === 'bigint' ||
|
|
243
|
+
typeof value === 'function' ||
|
|
244
|
+
typeof value === 'symbol'
|
|
245
|
+
) {
|
|
246
|
+
throw new TypeError('Distributed SSR props must be JSON serializable.');
|
|
247
|
+
}
|
|
248
|
+
if (typeof value === 'number' && !Number.isFinite(value)) {
|
|
249
|
+
throw new TypeError('Distributed SSR props must contain finite numbers.');
|
|
250
|
+
}
|
|
251
|
+
if (value && typeof value === 'object') {
|
|
252
|
+
if (seen.has(value)) {
|
|
253
|
+
throw new TypeError('Distributed SSR props must not contain cycles.');
|
|
254
|
+
}
|
|
255
|
+
seen.add(value);
|
|
256
|
+
}
|
|
257
|
+
return value;
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
if (typeof serialized !== 'string') {
|
|
261
|
+
throw new TypeError('Distributed SSR props must serialize to JSON.');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return serialized;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function readFragmentProvenance(response) {
|
|
268
|
+
const value = response.headers.get(DISTRIBUTED_SSR_PROVENANCE_HEADER);
|
|
269
|
+
if (value === null) {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
const provenance = JSON.parse(decodeURIComponent(value));
|
|
275
|
+
return provenance && typeof provenance === 'object'
|
|
276
|
+
? provenance
|
|
277
|
+
: undefined;
|
|
278
|
+
} catch {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function fragmentLocale(request) {
|
|
284
|
+
const segment = new URL(request.url).pathname.split('/').filter(Boolean)[0];
|
|
285
|
+
|
|
286
|
+
return segment && /^[a-z\d-]+$/iu.test(segment) ? segment : 'en';
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function createFragmentFailure(fragment, reason) {
|
|
290
|
+
return {
|
|
291
|
+
boundaryId: fragment.boundaryId,
|
|
292
|
+
expose: fragment.expose,
|
|
293
|
+
reason,
|
|
294
|
+
remote: fragment.remote,
|
|
295
|
+
status: 'degraded',
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function emitFragmentFailure(binding, fragment, reason) {
|
|
300
|
+
try {
|
|
301
|
+
console.error(
|
|
302
|
+
JSON.stringify({
|
|
303
|
+
appName: 'modern-js-cloudflare-worker',
|
|
304
|
+
eventName: 'modernjs:microvertical-server-fallback',
|
|
305
|
+
metadata: {
|
|
306
|
+
classification: 'remote-unavailable',
|
|
307
|
+
expose: fragment.expose,
|
|
308
|
+
platform: 'cloudflare-service-binding',
|
|
309
|
+
reason,
|
|
310
|
+
remote: fragment.remote,
|
|
311
|
+
serviceBinding: binding.binding,
|
|
312
|
+
status: 'degraded',
|
|
313
|
+
},
|
|
314
|
+
phase: 'discovery',
|
|
315
|
+
reason: 'remote-unavailable',
|
|
316
|
+
schemaVersion: 1,
|
|
317
|
+
}),
|
|
318
|
+
);
|
|
319
|
+
} catch {}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async function fetchDistributedSsrFragment(
|
|
323
|
+
binding,
|
|
324
|
+
fragment,
|
|
325
|
+
propsJson,
|
|
326
|
+
request,
|
|
327
|
+
env,
|
|
328
|
+
) {
|
|
329
|
+
const service = env?.[binding.binding];
|
|
330
|
+
if (!service || typeof service.fetch !== 'function') {
|
|
331
|
+
emitFragmentFailure(binding, fragment, 'binding-unavailable');
|
|
332
|
+
return createFragmentFailure(fragment, 'binding-unavailable');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const fragmentPath = fragment.path.replaceAll(
|
|
336
|
+
'{locale}',
|
|
337
|
+
encodeURIComponent(fragmentLocale(request)),
|
|
338
|
+
);
|
|
339
|
+
const fragmentUrl = new URL(fragmentPath, request.url);
|
|
340
|
+
const headers = new Headers(request.headers);
|
|
341
|
+
headers.delete('host');
|
|
342
|
+
headers.set('x-modern-js-fragment-request', '1');
|
|
343
|
+
headers.set('x-modern-distributed-ssr-boundary-id', fragment.boundaryId);
|
|
344
|
+
headers.set('x-modern-distributed-ssr-expose', fragment.expose);
|
|
345
|
+
headers.set('x-modern-distributed-ssr-props', encodeURIComponent(propsJson));
|
|
346
|
+
headers.set('x-modern-distributed-ssr-remote', fragment.remote);
|
|
347
|
+
headers.set('x-modern-distributed-ssr-source-url', request.url);
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
const response = await service.fetch(
|
|
351
|
+
new Request(fragmentUrl, {
|
|
352
|
+
headers,
|
|
353
|
+
method: 'GET',
|
|
354
|
+
}),
|
|
355
|
+
);
|
|
356
|
+
if (!response.ok) {
|
|
357
|
+
const reason = `fragment-http-${response.status}`;
|
|
358
|
+
emitFragmentFailure(binding, fragment, reason);
|
|
359
|
+
return createFragmentFailure(fragment, reason);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const html = await response.text();
|
|
363
|
+
const stylesheetAssets = readFragmentStylesheetAssets(response);
|
|
364
|
+
const renderedBoundaryHtml = extractRenderedFragmentHtml(
|
|
365
|
+
html,
|
|
366
|
+
fragment.boundaryId,
|
|
367
|
+
fragment.expose,
|
|
368
|
+
);
|
|
369
|
+
const provenance = readFragmentProvenance(response);
|
|
370
|
+
if (
|
|
371
|
+
!renderedBoundaryHtml ||
|
|
372
|
+
stylesheetAssets === undefined ||
|
|
373
|
+
provenance?.boundaryId !== fragment.boundaryId ||
|
|
374
|
+
provenance?.expose !== fragment.expose ||
|
|
375
|
+
provenance?.remote !== fragment.remote ||
|
|
376
|
+
typeof provenance?.buildMarker !== 'string' ||
|
|
377
|
+
typeof provenance?.digest !== 'string' ||
|
|
378
|
+
typeof provenance?.sourceRevision !== 'string' ||
|
|
379
|
+
typeof provenance?.unitId !== 'string' ||
|
|
380
|
+
provenance.digest !== (await sha256Hex(renderedBoundaryHtml))
|
|
381
|
+
) {
|
|
382
|
+
emitFragmentFailure(binding, fragment, 'fragment-contract-mismatch');
|
|
383
|
+
return createFragmentFailure(fragment, 'fragment-contract-mismatch');
|
|
384
|
+
}
|
|
385
|
+
const stylesheetHrefs = await resolveFragmentStylesheetHrefs(
|
|
386
|
+
stylesheetAssets,
|
|
387
|
+
fragment,
|
|
388
|
+
fragmentUrl,
|
|
389
|
+
request,
|
|
390
|
+
env,
|
|
391
|
+
);
|
|
392
|
+
const fragmentHtml = createHydratableFragmentHtml(renderedBoundaryHtml);
|
|
393
|
+
|
|
394
|
+
return {
|
|
395
|
+
boundaryId: fragment.boundaryId,
|
|
396
|
+
buildMarker: provenance.buildMarker,
|
|
397
|
+
digest: provenance.digest,
|
|
398
|
+
expose: fragment.expose,
|
|
399
|
+
html: fragmentHtml,
|
|
400
|
+
provenance,
|
|
401
|
+
remote: fragment.remote,
|
|
402
|
+
status: 'ready',
|
|
403
|
+
stylesheetHrefs,
|
|
404
|
+
};
|
|
405
|
+
} catch {
|
|
406
|
+
emitFragmentFailure(binding, fragment, 'fragment-request-failed');
|
|
407
|
+
return createFragmentFailure(fragment, 'fragment-request-failed');
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function createDistributedSsrFragmentContext(request, env) {
|
|
412
|
+
const bindings = Array.isArray(MODERN_WORKER_MANIFEST.serviceBindings)
|
|
413
|
+
? MODERN_WORKER_MANIFEST.serviceBindings
|
|
414
|
+
: [];
|
|
415
|
+
const configuredFragments = bindings.flatMap(binding =>
|
|
416
|
+
Array.isArray(binding.fragments)
|
|
417
|
+
? binding.fragments.map(fragment => ({ binding, fragment }))
|
|
418
|
+
: [],
|
|
419
|
+
);
|
|
420
|
+
if (configuredFragments.length === 0) {
|
|
421
|
+
return undefined;
|
|
422
|
+
}
|
|
423
|
+
const cache = new Map();
|
|
424
|
+
const stylesheetHrefs = new Set();
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
required: true,
|
|
428
|
+
getStylesheetHrefs() {
|
|
429
|
+
return [...stylesheetHrefs];
|
|
430
|
+
},
|
|
431
|
+
resolve(remote, expose, props) {
|
|
432
|
+
const configured = configuredFragments.find(
|
|
433
|
+
candidate =>
|
|
434
|
+
candidate.fragment.remote === remote &&
|
|
435
|
+
candidate.fragment.expose === expose,
|
|
436
|
+
);
|
|
437
|
+
if (!configured) {
|
|
438
|
+
return {
|
|
439
|
+
boundaryId: remote,
|
|
440
|
+
expose,
|
|
441
|
+
reason: 'fragment-not-configured',
|
|
442
|
+
remote,
|
|
443
|
+
status: 'degraded',
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
let propsJson;
|
|
448
|
+
try {
|
|
449
|
+
propsJson = serializeDistributedSsrProps(props);
|
|
450
|
+
} catch {
|
|
451
|
+
return createFragmentFailure(
|
|
452
|
+
configured.fragment,
|
|
453
|
+
'fragment-props-not-serializable',
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
const key = `${distributedSsrFragmentKey(remote, expose)}::${propsJson}`;
|
|
457
|
+
if (!cache.has(key)) {
|
|
458
|
+
cache.set(
|
|
459
|
+
key,
|
|
460
|
+
fetchDistributedSsrFragment(
|
|
461
|
+
configured.binding,
|
|
462
|
+
configured.fragment,
|
|
463
|
+
propsJson,
|
|
464
|
+
request,
|
|
465
|
+
env,
|
|
466
|
+
).then(result => {
|
|
467
|
+
if (result.status === 'ready') {
|
|
468
|
+
for (const href of result.stylesheetHrefs) {
|
|
469
|
+
stylesheetHrefs.add(href);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
const { stylesheetHrefs: _stylesheetHrefs, ...publicResult } =
|
|
473
|
+
result;
|
|
474
|
+
cache.set(key, publicResult);
|
|
475
|
+
return publicResult;
|
|
476
|
+
}),
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return cache.get(key);
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function readDistributedSsrFragmentRequest(request) {
|
|
486
|
+
if (request.headers.get('x-modern-js-fragment-request') !== '1') {
|
|
487
|
+
return undefined;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
try {
|
|
491
|
+
const boundaryId = request.headers.get(
|
|
492
|
+
'x-modern-distributed-ssr-boundary-id',
|
|
493
|
+
);
|
|
494
|
+
const expose = request.headers.get('x-modern-distributed-ssr-expose');
|
|
495
|
+
const propsValue = request.headers.get('x-modern-distributed-ssr-props');
|
|
496
|
+
const remote = request.headers.get('x-modern-distributed-ssr-remote');
|
|
497
|
+
const sourceUrl = request.headers.get(
|
|
498
|
+
'x-modern-distributed-ssr-source-url',
|
|
499
|
+
);
|
|
500
|
+
const props = JSON.parse(decodeURIComponent(propsValue ?? ''));
|
|
501
|
+
if (
|
|
502
|
+
!boundaryId ||
|
|
503
|
+
!expose ||
|
|
504
|
+
!remote ||
|
|
505
|
+
!sourceUrl ||
|
|
506
|
+
!props ||
|
|
507
|
+
typeof props !== 'object' ||
|
|
508
|
+
Array.isArray(props)
|
|
509
|
+
) {
|
|
510
|
+
return undefined;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return { boundaryId, expose, props, remote, sourceUrl };
|
|
514
|
+
} catch {
|
|
515
|
+
return undefined;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function createRequestHandlerOptions({
|
|
520
|
+
route,
|
|
521
|
+
htmlTemplate,
|
|
522
|
+
routeManifest,
|
|
523
|
+
loadableStats,
|
|
524
|
+
distributedSsrFragments,
|
|
525
|
+
distributedSsrFragmentRequest,
|
|
526
|
+
}) {
|
|
527
|
+
const monitors = createNoopMonitors();
|
|
528
|
+
|
|
529
|
+
return {
|
|
530
|
+
resource: {
|
|
531
|
+
route,
|
|
532
|
+
routeManifest,
|
|
533
|
+
loadableStats,
|
|
534
|
+
htmlTemplate,
|
|
535
|
+
entryName: route.entryName,
|
|
536
|
+
},
|
|
537
|
+
params: {},
|
|
538
|
+
loaderContext: {},
|
|
539
|
+
config: {},
|
|
540
|
+
locals: {
|
|
541
|
+
...(distributedSsrFragments === undefined
|
|
542
|
+
? {}
|
|
543
|
+
: {
|
|
544
|
+
[DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY]: distributedSsrFragments,
|
|
545
|
+
}),
|
|
546
|
+
...(distributedSsrFragmentRequest === undefined
|
|
547
|
+
? {}
|
|
548
|
+
: {
|
|
549
|
+
[DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY]:
|
|
550
|
+
distributedSsrFragmentRequest,
|
|
551
|
+
}),
|
|
552
|
+
},
|
|
553
|
+
staticGenerate: false,
|
|
554
|
+
monitors,
|
|
555
|
+
onError(error) {
|
|
556
|
+
monitors.error(error);
|
|
557
|
+
},
|
|
558
|
+
onTiming() {},
|
|
559
|
+
reporter: {
|
|
560
|
+
reportTiming: () => {},
|
|
561
|
+
},
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function collectRouteCssAssets(route, routeManifest) {
|
|
566
|
+
const routeAssets = routeManifest?.routeAssets || {};
|
|
567
|
+
const candidateKeys = [route.entryName, `async-${route.entryName}`].filter(
|
|
568
|
+
Boolean,
|
|
569
|
+
);
|
|
570
|
+
const assets = new Set();
|
|
571
|
+
|
|
572
|
+
for (const key of candidateKeys) {
|
|
573
|
+
const routeAsset = routeAssets[key];
|
|
574
|
+
const cssAssets = [
|
|
575
|
+
...(Array.isArray(routeAsset?.referenceCssAssets)
|
|
576
|
+
? routeAsset.referenceCssAssets
|
|
577
|
+
: []),
|
|
578
|
+
...(Array.isArray(routeAsset?.assets) ? routeAsset.assets : []),
|
|
579
|
+
];
|
|
580
|
+
|
|
581
|
+
for (const asset of cssAssets) {
|
|
582
|
+
if (typeof asset === 'string' && asset.endsWith('.css')) {
|
|
583
|
+
assets.add(asset);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return [...assets];
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
function collectRenderedFederatedExposes(html) {
|
|
592
|
+
const renderedExposes = [];
|
|
593
|
+
const tagPattern =
|
|
594
|
+
/<[^>]*data-modern-(?:boundary-id|mf-expose)=["'][^"']+["'][^>]*>/g;
|
|
595
|
+
const attributePattern =
|
|
596
|
+
/\s(data-modern-(?:boundary-id|mf-expose))=["']([^"']+)["']/g;
|
|
597
|
+
|
|
598
|
+
for (const [tag] of html.matchAll(tagPattern)) {
|
|
599
|
+
const attributes = {};
|
|
600
|
+
|
|
601
|
+
for (const [, name, value] of tag.matchAll(attributePattern)) {
|
|
602
|
+
attributes[name] = value;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const boundaryId = attributes['data-modern-boundary-id'];
|
|
606
|
+
const expose = attributes['data-modern-mf-expose'];
|
|
607
|
+
|
|
608
|
+
if (boundaryId && expose) {
|
|
609
|
+
renderedExposes.push({ boundaryId, expose });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return renderedExposes;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function getRemoteManifestUrl(remote, request) {
|
|
617
|
+
const entry = remote?.entry;
|
|
618
|
+
|
|
619
|
+
if (typeof entry !== 'string' || entry.length === 0) {
|
|
620
|
+
return undefined;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return new URL(entry, request.url).toString();
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
function ensureTrailingSlash(value) {
|
|
627
|
+
return value.endsWith('/') ? value : `${value}/`;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function isAutomaticPublicPath(publicPath) {
|
|
631
|
+
return publicPath === 'auto' || publicPath === 'auto/';
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function getRemoteAssetBase(remoteManifest, manifestUrl) {
|
|
635
|
+
const publicPath =
|
|
636
|
+
typeof remoteManifest?.metaData?.publicPath === 'string'
|
|
637
|
+
? remoteManifest.metaData.publicPath
|
|
638
|
+
: undefined;
|
|
639
|
+
const fallbackBase = new URL('.', manifestUrl).toString();
|
|
640
|
+
|
|
641
|
+
if (!publicPath || isAutomaticPublicPath(publicPath)) {
|
|
642
|
+
return fallbackBase;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
try {
|
|
646
|
+
return new URL(ensureTrailingSlash(publicPath), manifestUrl).toString();
|
|
647
|
+
} catch {
|
|
648
|
+
return fallbackBase;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
async function fetchRemoteJson(jsonUrl) {
|
|
653
|
+
if (!remoteJsonPromises.has(jsonUrl)) {
|
|
654
|
+
remoteJsonPromises.set(
|
|
655
|
+
jsonUrl,
|
|
656
|
+
fetch(jsonUrl)
|
|
657
|
+
.then(response => {
|
|
658
|
+
if (!response.ok) {
|
|
659
|
+
remoteJsonPromises.delete(jsonUrl);
|
|
660
|
+
|
|
661
|
+
return {};
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return response.json().catch(() => {
|
|
665
|
+
remoteJsonPromises.delete(jsonUrl);
|
|
666
|
+
|
|
667
|
+
return {};
|
|
668
|
+
});
|
|
669
|
+
})
|
|
670
|
+
.catch(() => {
|
|
671
|
+
remoteJsonPromises.delete(jsonUrl);
|
|
672
|
+
|
|
673
|
+
return {};
|
|
674
|
+
}),
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return remoteJsonPromises.get(jsonUrl);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function findRemoteExpose(remoteManifest, exposePath) {
|
|
682
|
+
const exposes = Array.isArray(remoteManifest?.exposes)
|
|
683
|
+
? remoteManifest.exposes
|
|
684
|
+
: [];
|
|
685
|
+
const normalizedExpose = exposePath.replace(/^\.\//u, '');
|
|
686
|
+
|
|
687
|
+
return exposes.find(expose => {
|
|
688
|
+
if (!expose || typeof expose !== 'object') {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
return (
|
|
693
|
+
expose.path === exposePath ||
|
|
694
|
+
expose.path === `./${normalizedExpose}` ||
|
|
695
|
+
expose.name === normalizedExpose
|
|
696
|
+
);
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function collectCssAssetEntries(assets) {
|
|
701
|
+
const cssAssets = assets?.css;
|
|
702
|
+
|
|
703
|
+
return [
|
|
704
|
+
...(Array.isArray(cssAssets?.sync) ? cssAssets.sync : []),
|
|
705
|
+
...(Array.isArray(cssAssets?.async) ? cssAssets.async : []),
|
|
706
|
+
].filter(asset => typeof asset === 'string' && asset.endsWith('.css'));
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function collectLocalFragmentCssAssets(html, request) {
|
|
710
|
+
if (request.headers.get('x-modern-js-fragment-request') !== '1') {
|
|
711
|
+
return undefined;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const renderedExposes = collectRenderedFederatedExposes(html);
|
|
715
|
+
const localManifest = MODERN_WORKER_MANIFEST.moduleFederation;
|
|
716
|
+
if (!localManifest) {
|
|
717
|
+
return undefined;
|
|
718
|
+
}
|
|
719
|
+
const containerName = localManifest?.name;
|
|
720
|
+
const assets = new Set();
|
|
721
|
+
|
|
722
|
+
for (const { boundaryId, expose } of renderedExposes) {
|
|
723
|
+
if (containerName && boundaryId !== containerName) {
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const localExpose = findRemoteExpose(localManifest, expose);
|
|
728
|
+
|
|
729
|
+
for (const asset of Array.isArray(localExpose?.css)
|
|
730
|
+
? localExpose.css
|
|
731
|
+
: []) {
|
|
732
|
+
assets.add(asset);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return [...assets];
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
async function createLocalFragmentProvenance(html, request) {
|
|
740
|
+
const fragmentRequest = readDistributedSsrFragmentRequest(request);
|
|
741
|
+
if (!fragmentRequest) {
|
|
742
|
+
return undefined;
|
|
743
|
+
}
|
|
744
|
+
const localManifest = MODERN_WORKER_MANIFEST.moduleFederation;
|
|
745
|
+
const deliveryUnit = MODERN_WORKER_MANIFEST.deliveryUnit;
|
|
746
|
+
if (
|
|
747
|
+
!localManifest ||
|
|
748
|
+
localManifest.name !== fragmentRequest.boundaryId ||
|
|
749
|
+
!findRemoteExpose(localManifest, fragmentRequest.expose) ||
|
|
750
|
+
typeof deliveryUnit?.buildMarker !== 'string' ||
|
|
751
|
+
typeof deliveryUnit?.sourceRevision !== 'string' ||
|
|
752
|
+
typeof deliveryUnit?.unitId !== 'string'
|
|
753
|
+
) {
|
|
754
|
+
return undefined;
|
|
755
|
+
}
|
|
756
|
+
const fragmentHtml = extractRenderedFragmentHtml(
|
|
757
|
+
html,
|
|
758
|
+
fragmentRequest.boundaryId,
|
|
759
|
+
fragmentRequest.expose,
|
|
760
|
+
);
|
|
761
|
+
if (!fragmentHtml) {
|
|
762
|
+
return undefined;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return {
|
|
766
|
+
boundaryId: fragmentRequest.boundaryId,
|
|
767
|
+
buildMarker: deliveryUnit.buildMarker,
|
|
768
|
+
digest: await sha256Hex(fragmentHtml),
|
|
769
|
+
expose: fragmentRequest.expose,
|
|
770
|
+
remote: fragmentRequest.remote,
|
|
771
|
+
sourceRevision: deliveryUnit.sourceRevision,
|
|
772
|
+
unitId: deliveryUnit.unitId,
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function collectRouteManifestCssAssets(routeManifest) {
|
|
777
|
+
const routeAssets = routeManifest?.routeAssets || {};
|
|
778
|
+
const assets = new Set();
|
|
779
|
+
|
|
780
|
+
for (const routeAsset of Object.values(routeAssets)) {
|
|
781
|
+
const cssAssets = [
|
|
782
|
+
...(Array.isArray(routeAsset?.referenceCssAssets)
|
|
783
|
+
? routeAsset.referenceCssAssets
|
|
784
|
+
: []),
|
|
785
|
+
...(Array.isArray(routeAsset?.assets) ? routeAsset.assets : []),
|
|
786
|
+
];
|
|
787
|
+
|
|
788
|
+
for (const asset of cssAssets) {
|
|
789
|
+
if (typeof asset === 'string' && asset.endsWith('.css')) {
|
|
790
|
+
assets.add(asset);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return [...assets];
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
async function collectRenderedRemoteCssHrefs(html, request, env) {
|
|
799
|
+
const bodyStart = html.indexOf('</head>');
|
|
800
|
+
const composedFragmentHrefs = collectStylesheetHrefs(
|
|
801
|
+
bodyStart >= 0 ? html.slice(bodyStart + '</head>'.length) : html,
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
if (composedFragmentHrefs.length > 0) {
|
|
805
|
+
return [...new Set(composedFragmentHrefs)];
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const renderedExposes = collectRenderedFederatedExposes(html);
|
|
809
|
+
|
|
810
|
+
if (renderedExposes.length === 0) {
|
|
811
|
+
return [];
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
const hostManifest = await readAssetJson('mf-manifest.json', request, env);
|
|
815
|
+
const remotes = Array.isArray(hostManifest?.remotes)
|
|
816
|
+
? hostManifest.remotes
|
|
817
|
+
: [];
|
|
818
|
+
const remoteByBoundary = new Map();
|
|
819
|
+
const hrefs = new Set();
|
|
820
|
+
|
|
821
|
+
for (const remote of remotes) {
|
|
822
|
+
if (typeof remote?.alias === 'string') {
|
|
823
|
+
remoteByBoundary.set(remote.alias, remote);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
if (typeof remote?.federationContainerName === 'string') {
|
|
827
|
+
remoteByBoundary.set(remote.federationContainerName, remote);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
await Promise.all(
|
|
832
|
+
renderedExposes.map(async ({ boundaryId, expose }) => {
|
|
833
|
+
const remote = remoteByBoundary.get(boundaryId);
|
|
834
|
+
const manifestUrl = remote
|
|
835
|
+
? getRemoteManifestUrl(remote, request)
|
|
836
|
+
: undefined;
|
|
837
|
+
|
|
838
|
+
if (!manifestUrl) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
const remoteManifest = await fetchRemoteJson(manifestUrl);
|
|
843
|
+
const remoteExpose = findRemoteExpose(remoteManifest, expose);
|
|
844
|
+
const publicPath = getRemoteAssetBase(remoteManifest, manifestUrl);
|
|
845
|
+
const remoteRouteManifest = await fetchRemoteJson(
|
|
846
|
+
new URL('routes-manifest.json', publicPath).toString(),
|
|
847
|
+
);
|
|
848
|
+
|
|
849
|
+
for (const asset of collectCssAssetEntries(remoteExpose?.assets)) {
|
|
850
|
+
hrefs.add(new URL(asset, publicPath).toString());
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
for (const asset of collectRouteManifestCssAssets(remoteRouteManifest)) {
|
|
854
|
+
hrefs.add(new URL(asset, publicPath).toString());
|
|
855
|
+
}
|
|
856
|
+
}),
|
|
857
|
+
);
|
|
858
|
+
|
|
859
|
+
return [...hrefs];
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
function escapeAttribute(value) {
|
|
863
|
+
return String(value)
|
|
864
|
+
.replace(/&/g, '&')
|
|
865
|
+
.replace(/"/g, '"')
|
|
866
|
+
.replace(/</g, '<')
|
|
867
|
+
.replace(/>/g, '>');
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
function isAbsoluteUrl(value) {
|
|
871
|
+
return /^[a-z][a-z\d+.-]*:/iu.test(value);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
function toRouteCssHtmlHref(asset) {
|
|
875
|
+
if (isAbsoluteUrl(asset) || asset.startsWith('/')) {
|
|
876
|
+
return asset;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
return `/${asset.replace(/^\/+/u, '')}`;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
async function withRouteCssLinks(
|
|
883
|
+
response,
|
|
884
|
+
route,
|
|
885
|
+
routeManifest,
|
|
886
|
+
request,
|
|
887
|
+
env,
|
|
888
|
+
distributedSsrFragmentCssHrefs = [],
|
|
889
|
+
) {
|
|
890
|
+
const contentType = response.headers.get('content-type') || '';
|
|
891
|
+
|
|
892
|
+
if (!contentType.includes('text/html')) {
|
|
893
|
+
return response;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
const html = dedupeStylesheetLinks(await response.text());
|
|
897
|
+
const headers = new Headers(response.headers);
|
|
898
|
+
const localFragmentCssAssets = collectLocalFragmentCssAssets(html, request);
|
|
899
|
+
const localFragmentProvenance = await createLocalFragmentProvenance(
|
|
900
|
+
html,
|
|
901
|
+
request,
|
|
902
|
+
);
|
|
903
|
+
|
|
904
|
+
if (localFragmentCssAssets !== undefined) {
|
|
905
|
+
headers.set(
|
|
906
|
+
DISTRIBUTED_SSR_CSS_HEADER,
|
|
907
|
+
JSON.stringify(localFragmentCssAssets),
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
if (localFragmentProvenance !== undefined) {
|
|
911
|
+
headers.set(
|
|
912
|
+
DISTRIBUTED_SSR_PROVENANCE_HEADER,
|
|
913
|
+
encodeURIComponent(JSON.stringify(localFragmentProvenance)),
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
const cssEntries = [
|
|
918
|
+
...collectRouteCssAssets(route, routeManifest).map(asset => {
|
|
919
|
+
const href = toRouteCssHtmlHref(asset);
|
|
920
|
+
|
|
921
|
+
return {
|
|
922
|
+
href,
|
|
923
|
+
preloadHref: new URL(href, request.url).toString(),
|
|
924
|
+
reactResource: false,
|
|
925
|
+
};
|
|
926
|
+
}),
|
|
927
|
+
...(distributedSsrFragmentCssHrefs.length > 0
|
|
928
|
+
? distributedSsrFragmentCssHrefs
|
|
929
|
+
: await collectRenderedRemoteCssHrefs(html, request, env)
|
|
930
|
+
).map(href => ({
|
|
931
|
+
href,
|
|
932
|
+
preloadHref: new URL(href, request.url).toString(),
|
|
933
|
+
reactResource: true,
|
|
934
|
+
})),
|
|
935
|
+
];
|
|
936
|
+
|
|
937
|
+
const requestOrigin = new URL(request.url).origin;
|
|
938
|
+
if (cssEntries.length === 0) {
|
|
939
|
+
return new Response(html, {
|
|
940
|
+
headers,
|
|
941
|
+
status: response.status,
|
|
942
|
+
statusText: response.statusText,
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
const seenCssHrefs = new Set();
|
|
947
|
+
const uniqueCssEntries = cssEntries.filter(entry => {
|
|
948
|
+
if (seenCssHrefs.has(entry.preloadHref)) {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
seenCssHrefs.add(entry.preloadHref);
|
|
953
|
+
return true;
|
|
954
|
+
});
|
|
955
|
+
for (const { href, preloadHref } of uniqueCssEntries) {
|
|
956
|
+
const preloadUrl = new URL(preloadHref);
|
|
957
|
+
const preloadReference =
|
|
958
|
+
preloadUrl.origin === requestOrigin
|
|
959
|
+
? `${preloadUrl.pathname}${preloadUrl.search}`
|
|
960
|
+
: preloadUrl.toString();
|
|
961
|
+
|
|
962
|
+
headers.append('link', `<${preloadReference}>; rel=preload; as=style`);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const links = uniqueCssEntries
|
|
966
|
+
.filter(
|
|
967
|
+
({ href, preloadHref }) =>
|
|
968
|
+
!html.includes(href) && !html.includes(preloadHref),
|
|
969
|
+
)
|
|
970
|
+
.map(({ href, reactResource }) =>
|
|
971
|
+
reactResource
|
|
972
|
+
? `<link href="${escapeAttribute(href)}" rel="stylesheet" type="text/css" data-precedence="default">`
|
|
973
|
+
: `<link rel="stylesheet" href="${escapeAttribute(href)}">`,
|
|
974
|
+
);
|
|
975
|
+
|
|
976
|
+
if (links.length === 0 || !html.includes('</head>')) {
|
|
977
|
+
return new Response(html, {
|
|
978
|
+
headers,
|
|
979
|
+
status: response.status,
|
|
980
|
+
statusText: response.statusText,
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
return new Response(html.replace('</head>', `${links.join('')}</head>`), {
|
|
985
|
+
headers,
|
|
986
|
+
status: response.status,
|
|
987
|
+
statusText: response.statusText,
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
async function getRequestHandlerOptions(route, request, env) {
|
|
992
|
+
const [htmlTemplate, routeManifest, loadableStats] = await Promise.all([
|
|
993
|
+
readAssetText(route.entryPath, request, env),
|
|
994
|
+
readAssetJson(MODERN_WORKER_MANIFEST.resources.routeManifest, request, env),
|
|
995
|
+
readAssetJson(MODERN_WORKER_MANIFEST.resources.loadableStats, request, env),
|
|
996
|
+
]);
|
|
997
|
+
const distributedSsrFragments = createDistributedSsrFragmentContext(
|
|
998
|
+
request,
|
|
999
|
+
env,
|
|
1000
|
+
);
|
|
1001
|
+
const distributedSsrFragmentRequest =
|
|
1002
|
+
readDistributedSsrFragmentRequest(request);
|
|
1003
|
+
|
|
1004
|
+
return createRequestHandlerOptions({
|
|
1005
|
+
route,
|
|
1006
|
+
htmlTemplate: htmlTemplate || '',
|
|
1007
|
+
routeManifest,
|
|
1008
|
+
loadableStats,
|
|
1009
|
+
distributedSsrFragments,
|
|
1010
|
+
distributedSsrFragmentRequest,
|
|
1011
|
+
});
|
|
1012
|
+
}
|