@bleedingdev/modern-js-ultramodern-app-tools 3.9.3-ultramodern.7 → 3.9.3-ultramodern.9
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/ultramodern.mjs +1 -1
- package/dist/cjs/native-composition/config-metadata.js +75 -3
- package/dist/cjs/native-composition/module-federation-renderer-plugin.js +1 -1
- package/dist/cjs/native-composition/native-development.js +101 -7
- package/dist/cjs/native-composition/native-entry.js +84 -19
- package/dist/cjs/native-composition/native-federation-dev-assets.js +143 -10
- package/dist/cjs/native-composition/native-federation-dev-public-path.js +36 -0
- package/dist/cjs/native-composition/native-infrastructure.js +81 -1
- package/dist/cjs/native-composition/native-module-federation.js +109 -25
- package/dist/cjs/native-composition/native-routes.js +120 -5
- package/dist/cjs/native-composition/native-worker-context-profiles.js +112 -0
- package/dist/cjs/native-composition/native-worker-federation-config.js +215 -0
- package/dist/cjs/native-composition/native-worker-federation-policy.js +102 -0
- package/dist/cjs/native-composition/native-worker-federation.js +226 -0
- package/dist/cjs/native-composition/native-worker-publication.js +107 -0
- package/dist/cjs/native-composition/native-worker.js +37 -3
- package/dist/cjs/native-composition/renderer-installed-profile.js +61 -2
- package/dist/cjs/native-composition/renderer-selection.js +2 -1
- package/dist/cjs/native-composition/workspace-preset.js +19 -2
- package/dist/cjs/renderers/react/profile.js +4 -4
- package/dist/cjs/renderers/react/router-bindings.js +2 -2
- package/dist/esm/native-composition/config-metadata.mjs +75 -3
- package/dist/esm/native-composition/module-federation-renderer-plugin.mjs +2 -2
- package/dist/esm/native-composition/native-development.mjs +102 -8
- package/dist/esm/native-composition/native-entry.mjs +85 -20
- package/dist/esm/native-composition/native-federation-dev-assets.mjs +124 -9
- package/dist/esm/native-composition/native-federation-dev-public-path.mjs +31 -1
- package/dist/esm/native-composition/native-infrastructure.mjs +81 -1
- package/dist/esm/native-composition/native-module-federation.mjs +108 -27
- package/dist/esm/native-composition/native-routes.mjs +110 -4
- package/dist/esm/native-composition/native-worker-context-profiles.mjs +63 -0
- package/dist/esm/native-composition/native-worker-federation-config.mjs +164 -0
- package/dist/esm/native-composition/native-worker-federation-policy.mjs +53 -0
- package/dist/esm/native-composition/native-worker-federation.mjs +166 -0
- package/dist/esm/native-composition/native-worker-publication.mjs +66 -0
- package/dist/esm/native-composition/native-worker.mjs +37 -3
- package/dist/esm/native-composition/renderer-installed-profile.mjs +54 -1
- package/dist/esm/native-composition/renderer-selection.mjs +2 -1
- package/dist/esm/native-composition/workspace-preset.mjs +19 -2
- package/dist/esm/renderers/react/profile.mjs +4 -4
- package/dist/esm/renderers/react/router-bindings.mjs +2 -2
- package/dist/esm-node/native-composition/config-metadata.mjs +75 -3
- package/dist/esm-node/native-composition/module-federation-renderer-plugin.mjs +2 -2
- package/dist/esm-node/native-composition/native-development.mjs +102 -8
- package/dist/esm-node/native-composition/native-entry.mjs +85 -20
- package/dist/esm-node/native-composition/native-federation-dev-assets.mjs +124 -9
- package/dist/esm-node/native-composition/native-federation-dev-public-path.mjs +31 -1
- package/dist/esm-node/native-composition/native-infrastructure.mjs +81 -1
- package/dist/esm-node/native-composition/native-module-federation.mjs +108 -27
- package/dist/esm-node/native-composition/native-routes.mjs +110 -4
- package/dist/esm-node/native-composition/native-worker-context-profiles.mjs +64 -0
- package/dist/esm-node/native-composition/native-worker-federation-config.mjs +165 -0
- package/dist/esm-node/native-composition/native-worker-federation-policy.mjs +54 -0
- package/dist/esm-node/native-composition/native-worker-federation.mjs +167 -0
- package/dist/esm-node/native-composition/native-worker-publication.mjs +67 -0
- package/dist/esm-node/native-composition/native-worker.mjs +37 -3
- package/dist/esm-node/native-composition/renderer-installed-profile.mjs +54 -1
- package/dist/esm-node/native-composition/renderer-selection.mjs +2 -1
- package/dist/esm-node/native-composition/workspace-preset.mjs +19 -2
- package/dist/esm-node/renderers/react/profile.mjs +4 -4
- package/dist/esm-node/renderers/react/router-bindings.mjs +2 -2
- package/dist/types/native-composition/config-metadata.d.ts +6 -0
- package/dist/types/native-composition/native-development.d.ts +6 -0
- package/dist/types/native-composition/native-entry.d.ts +1 -1
- package/dist/types/native-composition/native-federation-dev-assets.d.ts +26 -2
- package/dist/types/native-composition/native-federation-dev-public-path.d.ts +4 -0
- package/dist/types/native-composition/native-infrastructure.d.ts +10 -0
- package/dist/types/native-composition/native-module-federation.d.ts +8 -4
- package/dist/types/native-composition/native-routes.d.ts +11 -0
- package/dist/types/native-composition/native-worker-context-profiles.d.ts +2 -0
- package/dist/types/native-composition/native-worker-federation-config.d.ts +46 -0
- package/dist/types/native-composition/native-worker-federation-policy.d.ts +8 -0
- package/dist/types/native-composition/native-worker-federation.d.ts +57 -0
- package/dist/types/native-composition/native-worker-publication.d.ts +12 -0
- package/dist/types/native-composition/native-worker.d.ts +14 -1
- package/dist/types/native-composition/renderer-installed-profile.d.ts +6 -0
- package/dist/types-esm/native-composition/config-metadata.d.mts +6 -0
- package/dist/types-esm/native-composition/native-development.d.mts +6 -0
- package/dist/types-esm/native-composition/native-entry.d.mts +1 -1
- package/dist/types-esm/native-composition/native-federation-dev-assets.d.mts +26 -2
- package/dist/types-esm/native-composition/native-federation-dev-public-path.d.mts +4 -0
- package/dist/types-esm/native-composition/native-infrastructure.d.mts +10 -0
- package/dist/types-esm/native-composition/native-module-federation.d.mts +8 -4
- package/dist/types-esm/native-composition/native-routes.d.mts +11 -0
- package/dist/types-esm/native-composition/native-worker-context-profiles.d.mts +2 -0
- package/dist/types-esm/native-composition/native-worker-federation-config.d.mts +46 -0
- package/dist/types-esm/native-composition/native-worker-federation-policy.d.mts +8 -0
- package/dist/types-esm/native-composition/native-worker-federation.d.mts +57 -0
- package/dist/types-esm/native-composition/native-worker-publication.d.mts +12 -0
- package/dist/types-esm/native-composition/native-worker.d.mts +14 -1
- package/dist/types-esm/native-composition/renderer-installed-profile.d.mts +6 -0
- package/package.json +39 -37
- package/src/native-composition/config-metadata.ts +110 -11
- package/src/native-composition/module-federation-renderer-plugin.ts +6 -2
- package/src/native-composition/native-development.ts +187 -13
- package/src/native-composition/native-entry.ts +116 -21
- package/src/native-composition/native-federation-dev-assets.ts +237 -13
- package/src/native-composition/native-federation-dev-public-path.ts +69 -0
- package/src/native-composition/native-infrastructure.ts +164 -1
- package/src/native-composition/native-module-federation.ts +178 -55
- package/src/native-composition/native-routes.ts +167 -3
- package/src/native-composition/native-worker-context-profiles.ts +119 -0
- package/src/native-composition/native-worker-federation-config.ts +343 -0
- package/src/native-composition/native-worker-federation-policy.ts +119 -0
- package/src/native-composition/native-worker-federation.ts +401 -0
- package/src/native-composition/native-worker-publication.ts +151 -0
- package/src/native-composition/native-worker.ts +71 -3
- package/src/native-composition/renderer-installed-profile.ts +67 -0
- package/src/native-composition/renderer-selection.ts +3 -1
- package/src/native-composition/workspace-preset.ts +34 -4
- package/src/renderers/react/profile.ts +4 -4
- package/src/renderers/react/router-bindings.ts +2 -2
package/bin/ultramodern.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { readFile } from 'node:fs/promises';
|
|
|
4
4
|
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
5
5
|
if (major < 26 || (major === 26 && minor < 10)) {
|
|
6
6
|
console.error(
|
|
7
|
-
`UltraModern.js requires Node.js >=26.
|
|
7
|
+
`UltraModern.js requires Node.js >=26.12.0; detected v${process.versions.node}.`,
|
|
8
8
|
);
|
|
9
9
|
process.exit(1);
|
|
10
10
|
}
|
|
@@ -47,8 +47,12 @@ const external_node_module_namespaceObject = require("node:module");
|
|
|
47
47
|
const external_node_path_namespaceObject = require("node:path");
|
|
48
48
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
49
49
|
const external_node_url_namespaceObject = require("node:url");
|
|
50
|
+
const cli_namespaceObject = require("@modern-js/plugin/cli");
|
|
50
51
|
const core_namespaceObject = require("@rsbuild/core");
|
|
51
52
|
const external_config_js_namespaceObject = require("./config.js");
|
|
53
|
+
const external_config_read_context_js_namespaceObject = require("./config-read-context.js");
|
|
54
|
+
const external_native_i18n_js_namespaceObject = require("./native-i18n.js");
|
|
55
|
+
const external_renderer_router_resolution_js_namespaceObject = require("./renderer-router-resolution.js");
|
|
52
56
|
function inside(directory, file) {
|
|
53
57
|
const relative = external_node_path_default().relative(directory, file);
|
|
54
58
|
return '' !== relative && !relative.startsWith(`..${external_node_path_default().sep}`) && '..' !== relative && !external_node_path_default().isAbsolute(relative);
|
|
@@ -115,11 +119,76 @@ async function readUltramodernConfigMetadata(options) {
|
|
|
115
119
|
appDirectory,
|
|
116
120
|
configFile: options.configFile,
|
|
117
121
|
env: options.env,
|
|
118
|
-
command: options.command
|
|
122
|
+
command: options.analyzeServerRoutes ? 'metadata' : options.command
|
|
119
123
|
});
|
|
124
|
+
const installedAppDirectory = options.stagedWorkspace && (appDirectory === external_node_path_default().resolve(options.stagedWorkspace.root) || inside(external_node_path_default().resolve(options.stagedWorkspace.root), appDirectory)) ? external_node_path_default().resolve(options.stagedWorkspace.originalRoot, external_node_path_default().relative(options.stagedWorkspace.root, appDirectory)) : appDirectory;
|
|
125
|
+
if (options.analyzeServerRoutes) {
|
|
126
|
+
const previousArgv = process.env.MODERN_ARGV;
|
|
127
|
+
process.env.MODERN_ARGV = 'node modern metadata';
|
|
128
|
+
const cli = (0, cli_namespaceObject.createCli)();
|
|
129
|
+
let cleanup;
|
|
130
|
+
try {
|
|
131
|
+
return await (0, external_config_read_context_js_namespaceObject.withEntryMetadataRead)(async ()=>{
|
|
132
|
+
const { appContext } = await cli.init({
|
|
133
|
+
cwd: appDirectory,
|
|
134
|
+
configFile: false,
|
|
135
|
+
config: loaded.config,
|
|
136
|
+
command: 'metadata',
|
|
137
|
+
internalPlugins: [
|
|
138
|
+
{
|
|
139
|
+
name: '@modern-js/ultramodern-route-metadata-context',
|
|
140
|
+
setup (api) {
|
|
141
|
+
api.updateAppContext({
|
|
142
|
+
configFile: loaded.configFile
|
|
143
|
+
});
|
|
144
|
+
cleanup = ()=>api.getHooks().onBeforeExit.call();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
});
|
|
149
|
+
const context = appContext.pluginAPI.getAppContext();
|
|
150
|
+
const entrypoints = context.entrypoints ?? [];
|
|
151
|
+
if (!entrypoints.length) throw new Error('UltraModern analyzed configuration has no application entries');
|
|
152
|
+
const entryBasePaths = {};
|
|
153
|
+
for (const entry of entrypoints){
|
|
154
|
+
const prefixes = [
|
|
155
|
+
...new Set((context.serverRoutes ?? []).filter((route)=>route.entryName === entry.entryName && !route.isApi).map((route)=>route.urlPath))
|
|
156
|
+
];
|
|
157
|
+
if (1 !== prefixes.length || 'string' != typeof prefixes[0]) throw new Error(`Native Worker federation entry ${entry.entryName} requires exactly one analyzed public route prefix.`);
|
|
158
|
+
entryBasePaths[entry.entryName] = prefixes[0];
|
|
159
|
+
}
|
|
160
|
+
const entries = entrypoints.map(({ entryName, isMainEntry })=>({
|
|
161
|
+
entryName,
|
|
162
|
+
isMainEntry
|
|
163
|
+
}));
|
|
164
|
+
const primary = entries.find((entry)=>entry.isMainEntry) ?? entries[0];
|
|
165
|
+
const renderer = loaded.config.renderer;
|
|
166
|
+
const routerBindings = await (0, external_renderer_router_resolution_js_namespaceObject.resolveEntrypointRouterBindings)(renderer, entrypoints, context.plugins.map((plugin)=>plugin.name), void 0, installedAppDirectory);
|
|
167
|
+
const i18n = (0, external_native_i18n_js_namespaceObject.findNativeI18nConfig)(loaded.config.plugins ?? []);
|
|
168
|
+
return {
|
|
169
|
+
renderer,
|
|
170
|
+
entries,
|
|
171
|
+
primaryEntryName: primary.entryName,
|
|
172
|
+
routerBindings,
|
|
173
|
+
entryBasePaths,
|
|
174
|
+
...i18n ? {
|
|
175
|
+
i18n
|
|
176
|
+
} : {}
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
} finally{
|
|
180
|
+
try {
|
|
181
|
+
await cleanup?.();
|
|
182
|
+
} finally{
|
|
183
|
+
cli.dispose();
|
|
184
|
+
if (void 0 === previousArgv) delete process.env.MODERN_ARGV;
|
|
185
|
+
else process.env.MODERN_ARGV = previousArgv;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
120
189
|
const resolution = await (0, external_config_js_namespaceObject.resolveUltramodernEntryIdentities)({
|
|
121
190
|
appDirectory,
|
|
122
|
-
installedAppDirectory
|
|
191
|
+
installedAppDirectory,
|
|
123
192
|
config: loaded.config,
|
|
124
193
|
command: options.command,
|
|
125
194
|
configFile: loaded.configFile
|
|
@@ -150,7 +219,10 @@ function loadUltramodernConfigMetadata(options) {
|
|
|
150
219
|
execArgv: [],
|
|
151
220
|
env: {
|
|
152
221
|
...process.env,
|
|
153
|
-
NODE_ENV: options.env
|
|
222
|
+
NODE_ENV: options.env,
|
|
223
|
+
...options.analyzeServerRoutes ? {
|
|
224
|
+
MODERN_ARGV: 'node modern metadata'
|
|
225
|
+
} : {}
|
|
154
226
|
},
|
|
155
227
|
stdio: [
|
|
156
228
|
'ignore',
|
|
@@ -83,7 +83,7 @@ function resolveRendererFederationCompatibility(renderer) {
|
|
|
83
83
|
specifier: owners.package,
|
|
84
84
|
filename: (0, external_node_module_namespaceObject.createRequire)(`${bootstrap.directory}/package.json`).resolve(owners.package)
|
|
85
85
|
});
|
|
86
|
-
const { protocolVersion, compiler, hydration, router } = metadata.profile;
|
|
86
|
+
const { protocolVersion, compiler, hydration, router } = (0, external_renderer_installed_profile_js_namespaceObject.projectInstalledFederationProfile)(metadata.profile, bootstrap);
|
|
87
87
|
return (0, renderer_contract_namespaceObject.readRendererFederationCompatibility)({
|
|
88
88
|
profile: {
|
|
89
89
|
renderer,
|
|
@@ -56,6 +56,7 @@ const server_namespaceObject = require("@modern-js/renderer-core/server");
|
|
|
56
56
|
const utils_namespaceObject = require("@modern-js/utils");
|
|
57
57
|
const external_native_build_manifest_js_namespaceObject = require("./native-build-manifest.js");
|
|
58
58
|
const external_native_federation_dev_assets_js_namespaceObject = require("./native-federation-dev-assets.js");
|
|
59
|
+
const external_native_federation_dev_public_path_js_namespaceObject = require("./native-federation-dev-public-path.js");
|
|
59
60
|
const external_renderer_registration_js_namespaceObject = require("./renderer-registration.js");
|
|
60
61
|
const allowsOrigin = (allowed, origin)=>Array.isArray(allowed) ? allowed.some((entry)=>allowsOrigin(entry, origin)) : allowed instanceof RegExp ? allowed.test(origin) : 'string' == typeof allowed ? allowed === origin : Boolean(allowed);
|
|
61
62
|
async function applyDevServerHeaders(request, response, server) {
|
|
@@ -124,6 +125,15 @@ class NativeDevelopment {
|
|
|
124
125
|
(0, identity_namespaceObject.assertRendererIdentity)(snapshot.manifest.rendererIdentity, identity);
|
|
125
126
|
return snapshot;
|
|
126
127
|
}
|
|
128
|
+
await this.waitForPublication(signal);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async waitForPublication(signal) {
|
|
132
|
+
for(;;){
|
|
133
|
+
signal.throwIfAborted();
|
|
134
|
+
if (this.closed) throw new Error('Native development compiler is closed');
|
|
135
|
+
if (this.failure) throw this.failure.error;
|
|
136
|
+
if (this.ready) return;
|
|
127
137
|
await new Promise((resolve, reject)=>{
|
|
128
138
|
const resumed = ()=>{
|
|
129
139
|
signal.removeEventListener('abort', aborted);
|
|
@@ -150,11 +160,26 @@ class NativeDevelopment {
|
|
|
150
160
|
if (!client?.compilation.hash || !server?.compilation.hash || !serverRoot) throw new Error('Native development requires completed client and server compilations');
|
|
151
161
|
const session = this.options.getSessionIdentities();
|
|
152
162
|
const entryNames = Object.keys(session.identities);
|
|
153
|
-
const federationAssets =
|
|
163
|
+
const federationAssets = new Map([
|
|
164
|
+
...await (0, external_native_federation_dev_assets_js_namespaceObject.collectNativeFederationDevAssets)(server, entryNames, (name)=>emittedBytes(server, name)),
|
|
165
|
+
...await (0, external_native_federation_dev_assets_js_namespaceObject.collectNativeFederationDevAssets)(client, entryNames, (name)=>emittedBytes(client, name))
|
|
166
|
+
]);
|
|
167
|
+
const federationGraph = (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevGraph)(client);
|
|
168
|
+
const federationRevision = federationAssets.size ? (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevRevision)(federationAssets) : void 0;
|
|
169
|
+
const retainedFederationAssets = (0, external_native_federation_dev_assets_js_namespaceObject.retainNativeFederationDevAssets)(this.retainedFederationAssets, new Map([
|
|
170
|
+
...federationAssets
|
|
171
|
+
].map(([url, asset])=>[
|
|
172
|
+
url,
|
|
173
|
+
{
|
|
174
|
+
...asset,
|
|
175
|
+
revision: federationRevision,
|
|
176
|
+
graphManifest: federationGraph?.immutableManifest
|
|
177
|
+
}
|
|
178
|
+
])));
|
|
154
179
|
const publicPath = client.compilation.outputOptions.publicPath;
|
|
155
180
|
const prefix = 'string' == typeof publicPath && 'auto' !== publicPath ? publicPath.endsWith('/') ? publicPath : `${publicPath}/` : '/';
|
|
156
181
|
for (const asset of client.compilation.getAssets()){
|
|
157
|
-
if (asset.info.hotModuleReplacement || this.mutableClientAssets.has(asset.name) || this.compilerArtifacts.isMutableDevelopmentAsset(asset.name, entryNames)) continue;
|
|
182
|
+
if (true !== asset.info.immutable || asset.info.hotModuleReplacement || this.mutableClientAssets.has(asset.name) || this.compilerArtifacts.isMutableDevelopmentAsset(asset.name, entryNames)) continue;
|
|
158
183
|
const pathname = new URL(`${prefix}${asset.name}`, 'http://native-dev.invalid').pathname;
|
|
159
184
|
if (!this.retained.has(pathname)) this.retained.set(pathname, {
|
|
160
185
|
bytes: await emittedBytes(client, asset.name),
|
|
@@ -218,7 +243,10 @@ class NativeDevelopment {
|
|
|
218
243
|
await promises_default().rename(temporary, manifestFile);
|
|
219
244
|
return {
|
|
220
245
|
entries,
|
|
221
|
-
federationAssets
|
|
246
|
+
federationAssets,
|
|
247
|
+
federationGraph,
|
|
248
|
+
federationRevision,
|
|
249
|
+
retainedFederationAssets
|
|
222
250
|
};
|
|
223
251
|
}
|
|
224
252
|
async close() {
|
|
@@ -228,6 +256,10 @@ class NativeDevelopment {
|
|
|
228
256
|
this.notify();
|
|
229
257
|
this.retained.clear();
|
|
230
258
|
this.federationAssets = new Map();
|
|
259
|
+
this.federationRevision = void 0;
|
|
260
|
+
this.federationGraph = void 0;
|
|
261
|
+
this.federationCompilers.clear();
|
|
262
|
+
this.retainedFederationAssets = new Map();
|
|
231
263
|
if (this.manifestFile) await promises_default().rm(this.manifestFile, {
|
|
232
264
|
force: true
|
|
233
265
|
});
|
|
@@ -241,6 +273,8 @@ class NativeDevelopment {
|
|
|
241
273
|
this.closed = false;
|
|
242
274
|
this.retained = new Map();
|
|
243
275
|
this.federationAssets = new Map();
|
|
276
|
+
this.federationCompilers = new Set();
|
|
277
|
+
this.retainedFederationAssets = new Map();
|
|
244
278
|
this.mutableClientAssets = new Set([
|
|
245
279
|
'renderer-assets.json'
|
|
246
280
|
]);
|
|
@@ -279,16 +313,69 @@ class NativeDevelopment {
|
|
|
279
313
|
config.mode = 'development';
|
|
280
314
|
const previous = config.dev?.setupMiddlewares;
|
|
281
315
|
const retain = (middlewares)=>{
|
|
282
|
-
|
|
316
|
+
const owner = this;
|
|
317
|
+
middlewares.unshift(function serve(request, response, next) {
|
|
318
|
+
if (owner.closed) return next();
|
|
283
319
|
if ('GET' !== request.method && 'HEAD' !== request.method) return next();
|
|
284
320
|
const pathname = URL.parse(request.url ?? '/', 'http://native-dev.invalid')?.pathname;
|
|
285
321
|
const protocol = request.socket instanceof external_node_tls_namespaceObject.TLSSocket ? 'https:' : 'http:';
|
|
286
|
-
const
|
|
322
|
+
const origin = `${protocol}//${request.headers.host}`;
|
|
323
|
+
if (!owner.federationGraph && [
|
|
324
|
+
...owner.federationCompilers
|
|
325
|
+
].some((compiler)=>{
|
|
326
|
+
const manifest = (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevManifest)(compiler);
|
|
327
|
+
return manifest && URL.parse(manifest)?.pathname === pathname;
|
|
328
|
+
})) {
|
|
329
|
+
const pending = new AbortController();
|
|
330
|
+
const aborted = ()=>pending.abort(new Error('Native manifest request closed'));
|
|
331
|
+
request.once('aborted', aborted);
|
|
332
|
+
response.once('close', aborted);
|
|
333
|
+
if (request.aborted || response.destroyed) aborted();
|
|
334
|
+
const cleanup = ()=>{
|
|
335
|
+
request.removeListener('aborted', aborted);
|
|
336
|
+
response.removeListener('close', aborted);
|
|
337
|
+
};
|
|
338
|
+
owner.waitForPublication(pending.signal).then(()=>{
|
|
339
|
+
cleanup();
|
|
340
|
+
if (pending.signal.aborted) return;
|
|
341
|
+
if (!owner.federationGraph) return next(new Error('Native browser manifest was not published'));
|
|
342
|
+
serve(request, response, next);
|
|
343
|
+
}, (error)=>{
|
|
344
|
+
cleanup();
|
|
345
|
+
if (!pending.signal.aborted) next(error);
|
|
346
|
+
});
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const hotUpdate = owner.federationGraph && (0, external_native_federation_dev_public_path_js_namespaceObject.nativeFederationDevHotUpdateTarget)(owner.federationGraph.publicPath, request.url ?? '/', origin);
|
|
350
|
+
if (hotUpdate) {
|
|
351
|
+
request.url = hotUpdate;
|
|
352
|
+
return next();
|
|
353
|
+
}
|
|
354
|
+
const federationAsset = (0, external_native_federation_dev_assets_js_namespaceObject.resolveNativeFederationDevAsset)(owner.federationAssets, request.url ?? '/', origin) ?? (owner.federationGraph && (0, external_native_federation_dev_assets_js_namespaceObject.resolveNativeFederationDevManifest)(owner.federationAssets, request.url ?? '/', owner.federationGraph.manifest));
|
|
355
|
+
const revision = owner.federationRevision;
|
|
356
|
+
const asset = federationAsset || pathname && owner.retained.get(pathname);
|
|
287
357
|
if (!asset) return next();
|
|
288
358
|
applyDevServerHeaders(request, response, api.getNormalizedConfig().server).then(()=>{
|
|
289
359
|
response.setHeader('Content-Type', asset.contentType);
|
|
290
360
|
response.setHeader('Content-Length', asset.bytes.length);
|
|
291
|
-
response.setHeader('Cache-Control', 'no-store');
|
|
361
|
+
response.setHeader('Cache-Control', asset.immutable ? 'public, max-age=31536000, immutable' : 'no-store');
|
|
362
|
+
if (federationAsset) {
|
|
363
|
+
const graphManifest = asset.graphManifest ?? owner.federationGraph?.immutableManifest;
|
|
364
|
+
if (graphManifest) response.setHeader('Link', `<${graphManifest}>; rel="ultramodern-completed-graph"`);
|
|
365
|
+
const graphRevision = asset.revision ?? revision;
|
|
366
|
+
if (graphRevision) response.setHeader(external_native_federation_dev_assets_js_namespaceObject.NATIVE_FEDERATION_DEV_REVISION_HEADER, graphRevision);
|
|
367
|
+
if (api.getNormalizedConfig().server.cors) {
|
|
368
|
+
const previous = response.getHeader('Access-Control-Expose-Headers');
|
|
369
|
+
const exposed = new Set([
|
|
370
|
+
...Array.isArray(previous) ? previous : String(previous ?? '').split(','),
|
|
371
|
+
'Link',
|
|
372
|
+
external_native_federation_dev_assets_js_namespaceObject.NATIVE_FEDERATION_DEV_REVISION_HEADER
|
|
373
|
+
].map((value)=>value.trim()).filter(Boolean));
|
|
374
|
+
response.setHeader('Access-Control-Expose-Headers', [
|
|
375
|
+
...exposed
|
|
376
|
+
].join(','));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
292
379
|
response.end('HEAD' === request.method ? void 0 : asset.bytes);
|
|
293
380
|
}, next);
|
|
294
381
|
});
|
|
@@ -309,6 +396,7 @@ class NativeDevelopment {
|
|
|
309
396
|
compiler
|
|
310
397
|
];
|
|
311
398
|
for (const candidate of compilers){
|
|
399
|
+
this.federationCompilers.add(candidate);
|
|
312
400
|
this.compilerVersions.set(candidate, 0);
|
|
313
401
|
let runVersion = 0;
|
|
314
402
|
const captureRun = ()=>{
|
|
@@ -343,7 +431,13 @@ class NativeDevelopment {
|
|
|
343
431
|
try {
|
|
344
432
|
const publication = await this.publish(stats);
|
|
345
433
|
if (this.closed || epoch !== this.epoch) return;
|
|
346
|
-
this.
|
|
434
|
+
this.retainedFederationAssets = publication.retainedFederationAssets;
|
|
435
|
+
this.federationAssets = new Map([
|
|
436
|
+
...publication.federationAssets,
|
|
437
|
+
...this.retainedFederationAssets
|
|
438
|
+
]);
|
|
439
|
+
this.federationRevision = publication.federationRevision;
|
|
440
|
+
this.federationGraph = publication.federationGraph;
|
|
347
441
|
this.ready = publication.entries;
|
|
348
442
|
this.failure = void 0;
|
|
349
443
|
this.notify();
|
|
@@ -51,6 +51,8 @@ const external_native_federation_files_js_namespaceObject = require("./native-fe
|
|
|
51
51
|
const external_native_i18n_js_namespaceObject = require("./native-i18n.js");
|
|
52
52
|
const external_native_module_federation_js_namespaceObject = require("./native-module-federation.js");
|
|
53
53
|
const external_native_routes_js_namespaceObject = require("./native-routes.js");
|
|
54
|
+
const external_native_worker_js_namespaceObject = require("./native-worker.js");
|
|
55
|
+
const external_native_worker_federation_js_namespaceObject = require("./native-worker-federation.js");
|
|
54
56
|
const external_renderer_registration_js_namespaceObject = require("./renderer-registration.js");
|
|
55
57
|
const entryRoutes = new WeakMap();
|
|
56
58
|
function resolveNativeEntryIdentity(context, renderer) {
|
|
@@ -88,13 +90,18 @@ async function emitNativeEntryApplication(context, mode) {
|
|
|
88
90
|
entryRoutes.set(context, discovery);
|
|
89
91
|
}
|
|
90
92
|
const routes = await discovery;
|
|
93
|
+
const sourceRequests = await (0, external_native_routes_js_namespaceObject.resolveNativeApplicationSourceRequests)(routes, context.profile.sourceExtensions, 'server' === mode ? 'node' : mode);
|
|
91
94
|
if (context.i18n) (0, external_native_i18n_js_namespaceObject.validateNativeLocalisedUrls)(context.i18n, routes);
|
|
92
95
|
sources[`app.${mode}.ts`] = (0, external_native_routes_js_namespaceObject.emitNativeApplicationModule)({
|
|
93
96
|
routes,
|
|
94
|
-
mode,
|
|
95
|
-
basePath: context.basePath
|
|
97
|
+
mode: 'client' === mode ? 'client' : 'server',
|
|
98
|
+
basePath: context.basePath,
|
|
99
|
+
sourceRequests
|
|
96
100
|
});
|
|
97
|
-
} else
|
|
101
|
+
} else {
|
|
102
|
+
const sourceRequest = await (0, external_native_routes_js_namespaceObject.resolveNativeApplicationSourceRequest)(source, context.profile.sourceExtensions, 'server' === mode ? 'node' : mode);
|
|
103
|
+
sources[`app.${mode}.ts`] = `export { default } from ${JSON.stringify(sourceRequest)};\n`;
|
|
104
|
+
}
|
|
98
105
|
await writeNativeEntryModules(directory, sources);
|
|
99
106
|
return {
|
|
100
107
|
routed,
|
|
@@ -105,11 +112,36 @@ const NATIVE_APPLICATION_CLIENT_REQUEST = './app.client';
|
|
|
105
112
|
function createNativeEntryStubGenerator(adapter) {
|
|
106
113
|
const renderer = adapter.name;
|
|
107
114
|
const extra = adapter.entryClient;
|
|
115
|
+
const serverSource = async (context, worker = false)=>{
|
|
116
|
+
const identity = resolveNativeEntryIdentity(context, renderer);
|
|
117
|
+
const { directory, routed } = await emitNativeEntryApplication(context, worker ? 'worker' : 'server');
|
|
118
|
+
const federated = Boolean(!worker && (0, external_native_federation_files_js_namespaceObject.findNativeFederationConfig)(context.appDirectory));
|
|
119
|
+
const server = `import { createNativeServerEntry } from ${JSON.stringify(adapter.runtime.entryServer)};
|
|
120
|
+
${worker && !context.workerFederation?.plan ? workerContextStartup(context, routed) : ''}${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${federated ? nativeFederationDeclaration : ''}
|
|
121
|
+
export const { ${nativeServerHandlers.join(', ')} } = createNativeServerEntry({
|
|
122
|
+
identity: ${JSON.stringify(identity)},
|
|
123
|
+
app: () => import("./app.${worker ? 'worker' : 'server'}"),${worker && context.workerFederation ? `\n workerFederationLocale: ${JSON.stringify(context.i18n?.fallbackLanguage ?? 'default')},` : ''}${federated ? `\n federation: ${nativeServerFederationBinding},` : ''}${context.i18n ? '\n i18n,' : ''}
|
|
124
|
+
});
|
|
125
|
+
`;
|
|
126
|
+
if (!federated) return {
|
|
127
|
+
source: server,
|
|
128
|
+
directory,
|
|
129
|
+
routed
|
|
130
|
+
};
|
|
131
|
+
await writeNativeEntryModules(directory, {
|
|
132
|
+
'handlers.server.ts': server
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
source: federatedServerSource(identity),
|
|
136
|
+
directory,
|
|
137
|
+
routed
|
|
138
|
+
};
|
|
139
|
+
};
|
|
108
140
|
return {
|
|
109
141
|
async client (context) {
|
|
110
142
|
const identity = resolveNativeEntryIdentity(context, renderer);
|
|
111
143
|
const federated = Boolean((0, external_native_federation_files_js_namespaceObject.findNativeFederationConfig)(context.appDirectory));
|
|
112
|
-
await emitNativeEntryApplication(context, 'client');
|
|
144
|
+
const { routed } = await emitNativeEntryApplication(context, 'client');
|
|
113
145
|
const fields = {
|
|
114
146
|
identity: JSON.stringify(identity),
|
|
115
147
|
load: `() => import(${JSON.stringify(NATIVE_APPLICATION_CLIENT_REQUEST)})`,
|
|
@@ -120,34 +152,47 @@ function createNativeEntryStubGenerator(adapter) {
|
|
|
120
152
|
...federated ? {
|
|
121
153
|
federation: nativeFederationBinding
|
|
122
154
|
} : {},
|
|
155
|
+
...context.workerFederation ? {
|
|
156
|
+
workerFederation: 'workerFederation'
|
|
157
|
+
} : {},
|
|
123
158
|
...extra?.fields
|
|
124
159
|
};
|
|
125
160
|
return `import { startNativeClient } from ${JSON.stringify(adapter.runtime.entryClient)};
|
|
126
|
-
${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${extra?.declarations ?? ''}${federated ? nativeFederationDeclaration : ''}
|
|
161
|
+
${workerContextStartup(context, routed)}${context.workerFederation ? nativeWorkerClientTransportSource(context) : ''}${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${extra?.declarations ?? ''}${federated ? nativeFederationDeclaration : ''}
|
|
127
162
|
startNativeClient({
|
|
128
163
|
${Object.entries(fields).map(([name, value])=>` ${name === value ? name : `${name}: ${value}`},`).join('\n')}
|
|
129
164
|
});
|
|
130
165
|
`;
|
|
131
166
|
},
|
|
132
|
-
async
|
|
133
|
-
|
|
134
|
-
const { directory } = await
|
|
135
|
-
const
|
|
136
|
-
const server = `import { createNativeServerEntry } from ${JSON.stringify(adapter.runtime.entryServer)};
|
|
137
|
-
${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${federated ? nativeFederationDeclaration : ''}
|
|
138
|
-
export const { ${nativeServerHandlers.join(', ')} } = createNativeServerEntry({
|
|
139
|
-
identity: ${JSON.stringify(identity)},
|
|
140
|
-
app: () => import("./app.server"),${federated ? `\n federation: ${nativeServerFederationBinding},` : ''}${context.i18n ? '\n i18n,' : ''}
|
|
141
|
-
});
|
|
142
|
-
`;
|
|
143
|
-
if (!federated) return server;
|
|
167
|
+
server: async (context)=>(await serverSource(context)).source,
|
|
168
|
+
async worker (context) {
|
|
169
|
+
const { source, directory, routed } = await serverSource(context, true);
|
|
170
|
+
const federation = context.workerFederation;
|
|
144
171
|
await writeNativeEntryModules(directory, {
|
|
145
|
-
'handlers.
|
|
172
|
+
'handlers.worker.ts': source,
|
|
173
|
+
...federation?.plan ? {
|
|
174
|
+
'federation.worker.ts': (0, external_native_worker_federation_js_namespaceObject.nativeWorkerFederationRegistrySource)(federation.plan, workerContextOptions(context, routed))
|
|
175
|
+
} : {}
|
|
146
176
|
});
|
|
147
|
-
return
|
|
177
|
+
return (0, external_native_worker_js_namespaceObject.nativeWorkerEntrySource)('./handlers.worker', federation ? {
|
|
178
|
+
runtime: adapter.runtime.entryServer,
|
|
179
|
+
compatibility: federation.compatibility,
|
|
180
|
+
registry: federation.plan ? './federation.worker' : void 0
|
|
181
|
+
} : void 0);
|
|
148
182
|
}
|
|
149
183
|
};
|
|
150
184
|
}
|
|
185
|
+
function workerContextOptions(context, routed) {
|
|
186
|
+
return 'octane' === context.renderer && context.workerFederation ? {
|
|
187
|
+
router: routed,
|
|
188
|
+
i18n: Boolean(context.i18n),
|
|
189
|
+
contextProfiles: context.workerFederation.contextProfiles
|
|
190
|
+
} : {};
|
|
191
|
+
}
|
|
192
|
+
function workerContextStartup(context, routed) {
|
|
193
|
+
const source = (0, external_native_worker_federation_js_namespaceObject.nativeWorkerContextStartupSource)(workerContextOptions(context, routed));
|
|
194
|
+
return source ? `${source}\n` : '';
|
|
195
|
+
}
|
|
151
196
|
const nativeFederationBinding = '{ instance: () => __webpack_require__.federation.instance }';
|
|
152
197
|
const nativeServerFederationBinding = `{ instance: () => __webpack_require__.federation.instance, hydrationModule: ${JSON.stringify(external_native_module_federation_js_namespaceObject.NATIVE_FEDERATION_HYDRATION_MODULE)} }`;
|
|
153
198
|
const nativeFederationDeclaration = 'declare const __webpack_require__: { federation: { instance: import("@modern-js/renderer-core/federation").FederationInstance } };\n';
|
|
@@ -169,6 +214,26 @@ ${nativeServerHandlers.slice(1).map((name)=>`export async function ${name}(reque
|
|
|
169
214
|
function createNativeEntryGenerator(renderer) {
|
|
170
215
|
return createNativeEntryStubGenerator((0, external_renderer_registration_js_namespaceObject.resolveNativeRendererAdapter)(renderer));
|
|
171
216
|
}
|
|
217
|
+
function nativeWorkerClientTransportSource(context) {
|
|
218
|
+
const federation = context.workerFederation;
|
|
219
|
+
return `import { createWorkerFederationTransport } from '@modern-js/renderer-core/worker-federation';
|
|
220
|
+
import { assertRendererFederationCompatibility, readRendererFederationContract } from '@modern-js/federation-runtime/renderer-contract';
|
|
221
|
+
const expectedWorkerRenderer = ${JSON.stringify(federation.compatibility)};
|
|
222
|
+
const workerFederation = signal => ({
|
|
223
|
+
locale: ${JSON.stringify(context.i18n?.fallbackLanguage ?? 'default')},
|
|
224
|
+
signal,
|
|
225
|
+
transport: createWorkerFederationTransport({
|
|
226
|
+
signal,
|
|
227
|
+
services: ${JSON.stringify(federation.services)}.map(service => ({...service, fetch: request => globalThis.fetch(request)})),
|
|
228
|
+
admitRendererContract(value) {
|
|
229
|
+
const contract = readRendererFederationContract(value);
|
|
230
|
+
assertRendererFederationCompatibility(expectedWorkerRenderer, contract);
|
|
231
|
+
return contract;
|
|
232
|
+
},
|
|
233
|
+
}),
|
|
234
|
+
});
|
|
235
|
+
`;
|
|
236
|
+
}
|
|
172
237
|
exports.NATIVE_APPLICATION_CLIENT_REQUEST = __webpack_exports__.NATIVE_APPLICATION_CLIENT_REQUEST;
|
|
173
238
|
exports.createNativeEntryGenerator = __webpack_exports__.createNativeEntryGenerator;
|
|
174
239
|
exports.createNativeEntryStubGenerator = __webpack_exports__.createNativeEntryStubGenerator;
|