@bleedingdev/modern-js-ultramodern-app-tools 3.9.3-ultramodern.1 → 3.9.3-ultramodern.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/bin/ultramodern.mjs +1 -1
- package/dist/cjs/native-composition/config-metadata.js +76 -4
- package/dist/cjs/native-composition/module-federation-renderer-plugin.js +1 -1
- package/dist/cjs/native-composition/native-development.js +132 -27
- 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 +46 -0
- package/dist/cjs/native-composition/native-infrastructure.js +92 -2
- 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/preset.js +35 -15
- package/dist/cjs/native-composition/renderer-build-resolution.js +5 -1
- package/dist/cjs/native-composition/renderer-installed-profile.js +61 -2
- package/dist/cjs/native-composition/renderer-release-identity.js +95 -0
- package/dist/cjs/native-composition/renderer-selection.js +2 -1
- package/dist/cjs/native-composition/server-minify.js +73 -0
- package/dist/cjs/native-composition/type-checker.js +14 -4
- package/dist/cjs/native-composition/workspace-preset.js +29 -9
- package/dist/cjs/renderers/react/build-metadata.js +2 -40
- package/dist/cjs/renderers/react/profile.js +4 -4
- package/dist/cjs/renderers/react/router-bindings.js +2 -2
- package/dist/cjs/renderers/react/ssr-integration-plugin.js +11 -3
- package/dist/esm/native-composition/config-metadata.mjs +76 -4
- package/dist/esm/native-composition/module-federation-renderer-plugin.mjs +2 -2
- package/dist/esm/native-composition/native-development.mjs +133 -28
- 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 +38 -1
- package/dist/esm/native-composition/native-infrastructure.mjs +92 -2
- 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/preset.mjs +28 -14
- package/dist/esm/native-composition/renderer-build-resolution.mjs +5 -1
- package/dist/esm/native-composition/renderer-installed-profile.mjs +54 -1
- package/dist/esm/native-composition/renderer-release-identity.mjs +54 -0
- package/dist/esm/native-composition/renderer-selection.mjs +2 -1
- package/dist/esm/native-composition/server-minify.mjs +32 -0
- package/dist/esm/native-composition/type-checker.mjs +4 -4
- package/dist/esm/native-composition/workspace-preset.mjs +29 -9
- package/dist/esm/renderers/react/build-metadata.mjs +2 -40
- package/dist/esm/renderers/react/profile.mjs +4 -4
- package/dist/esm/renderers/react/router-bindings.mjs +2 -2
- package/dist/esm/renderers/react/ssr-integration-plugin.mjs +11 -3
- package/dist/esm-node/native-composition/config-metadata.mjs +76 -4
- package/dist/esm-node/native-composition/module-federation-renderer-plugin.mjs +2 -2
- package/dist/esm-node/native-composition/native-development.mjs +133 -28
- 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 +38 -1
- package/dist/esm-node/native-composition/native-infrastructure.mjs +92 -2
- 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/preset.mjs +28 -14
- package/dist/esm-node/native-composition/renderer-build-resolution.mjs +5 -1
- package/dist/esm-node/native-composition/renderer-installed-profile.mjs +54 -1
- package/dist/esm-node/native-composition/renderer-release-identity.mjs +55 -0
- package/dist/esm-node/native-composition/renderer-selection.mjs +2 -1
- package/dist/esm-node/native-composition/server-minify.mjs +33 -0
- package/dist/esm-node/native-composition/type-checker.mjs +4 -4
- package/dist/esm-node/native-composition/workspace-preset.mjs +29 -9
- package/dist/esm-node/renderers/react/build-metadata.mjs +2 -40
- package/dist/esm-node/renderers/react/profile.mjs +4 -4
- package/dist/esm-node/renderers/react/router-bindings.mjs +2 -2
- package/dist/esm-node/renderers/react/ssr-integration-plugin.mjs +11 -3
- package/dist/types/native-composition/config-metadata.d.ts +6 -0
- package/dist/types/native-composition/native-development.d.ts +8 -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 +9 -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/preset.d.ts +16 -1
- package/dist/types/native-composition/renderer-installed-profile.d.ts +6 -0
- package/dist/types/native-composition/renderer-release-identity.d.ts +11 -0
- package/dist/types/native-composition/server-minify.d.ts +33 -0
- package/dist/types-esm/native-composition/config-metadata.d.mts +6 -0
- package/dist/types-esm/native-composition/native-development.d.mts +8 -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 +9 -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/preset.d.mts +16 -1
- package/dist/types-esm/native-composition/renderer-installed-profile.d.mts +6 -0
- package/dist/types-esm/native-composition/renderer-release-identity.d.mts +11 -0
- package/dist/types-esm/native-composition/server-minify.d.mts +33 -0
- package/lib/build-target.d.ts +17 -0
- package/lib/react-types.d.ts +1 -0
- package/package.json +39 -37
- package/src/native-composition/config-metadata.ts +114 -12
- package/src/native-composition/module-federation-renderer-plugin.ts +6 -2
- package/src/native-composition/native-development.ts +256 -46
- package/src/native-composition/native-entry.ts +116 -21
- package/src/native-composition/native-federation-dev-assets.ts +240 -13
- package/src/native-composition/native-federation-dev-public-path.ts +96 -0
- package/src/native-composition/native-infrastructure.ts +176 -2
- 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/preset.ts +54 -23
- package/src/native-composition/renderer-build-resolution.ts +6 -1
- package/src/native-composition/renderer-installed-profile.ts +67 -0
- package/src/native-composition/renderer-release-identity.ts +78 -0
- package/src/native-composition/renderer-selection.ts +3 -1
- package/src/native-composition/server-minify.ts +48 -0
- package/src/native-composition/type-checker.ts +8 -8
- package/src/native-composition/workspace-preset.ts +65 -24
- package/src/renderers/react/build-metadata.ts +3 -46
- package/src/renderers/react/profile.ts +4 -4
- package/src/renderers/react/router-bindings.ts +2 -2
- package/src/renderers/react/ssr-integration-plugin.ts +14 -4
package/README.md
CHANGED
|
@@ -142,7 +142,9 @@ export default defineConfig(
|
|
|
142
142
|
The workspace preset reads `topology/reference-topology.json` and
|
|
143
143
|
`topology/local-overlays/development.json` relative to that config. Those records
|
|
144
144
|
provide app identity, renderer, development ports, composed remote references
|
|
145
|
-
and delivery unit identity. An authored `renderer` must match the topology.
|
|
145
|
+
and delivery unit identity. An authored `renderer` must match the topology. A
|
|
146
|
+
headless (API-only) unit declares renderer `none` and no Module Federation
|
|
147
|
+
name; its config selects no `renderer`.
|
|
146
148
|
Adding a shell or vertical changes the records; existing application configs
|
|
147
149
|
keep their authored contents.
|
|
148
150
|
|
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
|
|
@@ -140,7 +209,7 @@ function workerFile() {
|
|
|
140
209
|
if (parent === directory) throw new Error('Cannot find the UltraModern app tools package root');
|
|
141
210
|
directory = parent;
|
|
142
211
|
}
|
|
143
|
-
return external_node_path_default().join(directory, 'dist/
|
|
212
|
+
return external_node_path_default().join(directory, 'dist/esm-node/native-composition/config-metadata-worker.mjs');
|
|
144
213
|
}
|
|
145
214
|
function loadUltramodernConfigMetadata(options) {
|
|
146
215
|
const appDirectory = external_node_path_default().resolve(options.appDirectory);
|
|
@@ -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() {
|
|
@@ -226,8 +254,13 @@ class NativeDevelopment {
|
|
|
226
254
|
this.closed = true;
|
|
227
255
|
this.ready = void 0;
|
|
228
256
|
this.notify();
|
|
257
|
+
await this.publication.catch(()=>{});
|
|
229
258
|
this.retained.clear();
|
|
230
259
|
this.federationAssets = new Map();
|
|
260
|
+
this.federationRevision = void 0;
|
|
261
|
+
this.federationGraph = void 0;
|
|
262
|
+
this.federationCompilers.clear();
|
|
263
|
+
this.retainedFederationAssets = new Map();
|
|
231
264
|
if (this.manifestFile) await promises_default().rm(this.manifestFile, {
|
|
232
265
|
force: true
|
|
233
266
|
});
|
|
@@ -238,9 +271,12 @@ class NativeDevelopment {
|
|
|
238
271
|
this.compilerVersions = new WeakMap();
|
|
239
272
|
this.compilationVersions = new WeakMap();
|
|
240
273
|
this.generation = 0;
|
|
274
|
+
this.publication = Promise.resolve();
|
|
241
275
|
this.closed = false;
|
|
242
276
|
this.retained = new Map();
|
|
243
277
|
this.federationAssets = new Map();
|
|
278
|
+
this.federationCompilers = new Set();
|
|
279
|
+
this.retainedFederationAssets = new Map();
|
|
244
280
|
this.mutableClientAssets = new Set([
|
|
245
281
|
'renderer-assets.json'
|
|
246
282
|
]);
|
|
@@ -279,16 +315,73 @@ class NativeDevelopment {
|
|
|
279
315
|
config.mode = 'development';
|
|
280
316
|
const previous = config.dev?.setupMiddlewares;
|
|
281
317
|
const retain = (middlewares)=>{
|
|
282
|
-
|
|
318
|
+
const owner = this;
|
|
319
|
+
middlewares.unshift(function serve(request, response, next) {
|
|
320
|
+
if (owner.closed) return next();
|
|
283
321
|
if ('GET' !== request.method && 'HEAD' !== request.method) return next();
|
|
284
322
|
const pathname = URL.parse(request.url ?? '/', 'http://native-dev.invalid')?.pathname;
|
|
285
323
|
const protocol = request.socket instanceof external_node_tls_namespaceObject.TLSSocket ? 'https:' : 'http:';
|
|
286
|
-
const
|
|
287
|
-
|
|
324
|
+
const origin = `${protocol}//${request.headers.host}`;
|
|
325
|
+
const afterPublication = (resume)=>{
|
|
326
|
+
const pending = new AbortController();
|
|
327
|
+
const aborted = ()=>pending.abort(new Error('Native graph request closed'));
|
|
328
|
+
request.once('aborted', aborted);
|
|
329
|
+
response.once('close', aborted);
|
|
330
|
+
if (request.aborted || response.destroyed) aborted();
|
|
331
|
+
const cleanup = ()=>{
|
|
332
|
+
request.removeListener('aborted', aborted);
|
|
333
|
+
response.removeListener('close', aborted);
|
|
334
|
+
};
|
|
335
|
+
owner.waitForPublication(pending.signal).then(()=>{
|
|
336
|
+
cleanup();
|
|
337
|
+
if (!pending.signal.aborted) resume();
|
|
338
|
+
}, (error)=>{
|
|
339
|
+
cleanup();
|
|
340
|
+
if (!pending.signal.aborted) next(error);
|
|
341
|
+
});
|
|
342
|
+
};
|
|
343
|
+
if (!owner.federationGraph && [
|
|
344
|
+
...owner.federationCompilers
|
|
345
|
+
].some((compiler)=>{
|
|
346
|
+
const manifest = (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevManifest)(compiler);
|
|
347
|
+
return manifest && URL.parse(manifest)?.pathname === pathname;
|
|
348
|
+
})) return void afterPublication(()=>{
|
|
349
|
+
if (!owner.federationGraph) return next(new Error('Native browser manifest was not published'));
|
|
350
|
+
serve(request, response, next);
|
|
351
|
+
});
|
|
352
|
+
const hotUpdate = owner.federationGraph && (0, external_native_federation_dev_public_path_js_namespaceObject.nativeFederationDevHotUpdateTarget)(owner.federationGraph.publicPath, request.url ?? '/', origin);
|
|
353
|
+
if (hotUpdate) {
|
|
354
|
+
request.url = hotUpdate;
|
|
355
|
+
return next();
|
|
356
|
+
}
|
|
357
|
+
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));
|
|
358
|
+
const revision = owner.federationRevision;
|
|
359
|
+
const asset = federationAsset || pathname && owner.retained.get(pathname);
|
|
360
|
+
if (!asset) {
|
|
361
|
+
if (owner.federationGraph && !owner.ready && !owner.failure && (0, external_native_federation_dev_public_path_js_namespaceObject.isNativeFederationDevGraphAsset)(owner.federationGraph.publicPath, request.url ?? '/', origin)) return void afterPublication(()=>serve(request, response, next));
|
|
362
|
+
return next();
|
|
363
|
+
}
|
|
288
364
|
applyDevServerHeaders(request, response, api.getNormalizedConfig().server).then(()=>{
|
|
289
365
|
response.setHeader('Content-Type', asset.contentType);
|
|
290
366
|
response.setHeader('Content-Length', asset.bytes.length);
|
|
291
|
-
response.setHeader('Cache-Control', 'no-store');
|
|
367
|
+
response.setHeader('Cache-Control', asset.immutable ? 'public, max-age=31536000, immutable' : 'no-store');
|
|
368
|
+
if (federationAsset) {
|
|
369
|
+
const graphManifest = asset.graphManifest ?? owner.federationGraph?.immutableManifest;
|
|
370
|
+
if (graphManifest) response.setHeader('Link', `<${graphManifest}>; rel="ultramodern-completed-graph"`);
|
|
371
|
+
const graphRevision = asset.revision ?? revision;
|
|
372
|
+
if (graphRevision) response.setHeader(external_native_federation_dev_assets_js_namespaceObject.NATIVE_FEDERATION_DEV_REVISION_HEADER, graphRevision);
|
|
373
|
+
if (api.getNormalizedConfig().server.cors) {
|
|
374
|
+
const previous = response.getHeader('Access-Control-Expose-Headers');
|
|
375
|
+
const exposed = new Set([
|
|
376
|
+
...Array.isArray(previous) ? previous : String(previous ?? '').split(','),
|
|
377
|
+
'Link',
|
|
378
|
+
external_native_federation_dev_assets_js_namespaceObject.NATIVE_FEDERATION_DEV_REVISION_HEADER
|
|
379
|
+
].map((value)=>value.trim()).filter(Boolean));
|
|
380
|
+
response.setHeader('Access-Control-Expose-Headers', [
|
|
381
|
+
...exposed
|
|
382
|
+
].join(','));
|
|
383
|
+
}
|
|
384
|
+
}
|
|
292
385
|
response.end('HEAD' === request.method ? void 0 : asset.bytes);
|
|
293
386
|
}, next);
|
|
294
387
|
});
|
|
@@ -309,6 +402,7 @@ class NativeDevelopment {
|
|
|
309
402
|
compiler
|
|
310
403
|
];
|
|
311
404
|
for (const candidate of compilers){
|
|
405
|
+
this.federationCompilers.add(candidate);
|
|
312
406
|
this.compilerVersions.set(candidate, 0);
|
|
313
407
|
let runVersion = 0;
|
|
314
408
|
const captureRun = ()=>{
|
|
@@ -330,28 +424,39 @@ class NativeDevelopment {
|
|
|
330
424
|
candidate.hooks.failed.tap('UltraModernNativeDevelopment', (error)=>this.fail(error));
|
|
331
425
|
}
|
|
332
426
|
});
|
|
333
|
-
api.onDevCompileDone(
|
|
427
|
+
api.onDevCompileDone(({ stats })=>{
|
|
334
428
|
const epoch = this.epoch;
|
|
335
|
-
const
|
|
336
|
-
stats
|
|
337
|
-
];
|
|
338
|
-
if (this.closed || results.some((result)=>{
|
|
339
|
-
const version = this.compilationVersions.get(result.compilation);
|
|
340
|
-
return void 0 === version || version !== this.compilerVersions.get(result.compilation.compiler);
|
|
341
|
-
})) return;
|
|
342
|
-
if (stats.hasErrors()) return this.fail(new Error('Native development compilation failed'));
|
|
343
|
-
try {
|
|
344
|
-
const publication = await this.publish(stats);
|
|
345
|
-
if (this.closed || epoch !== this.epoch) return;
|
|
346
|
-
this.federationAssets = publication.federationAssets;
|
|
347
|
-
this.ready = publication.entries;
|
|
348
|
-
this.failure = void 0;
|
|
349
|
-
this.notify();
|
|
350
|
-
} catch (error) {
|
|
429
|
+
const publishNext = async ()=>{
|
|
351
430
|
if (this.closed || epoch !== this.epoch) return;
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
431
|
+
const results = 'stats' in stats ? stats.stats : [
|
|
432
|
+
stats
|
|
433
|
+
];
|
|
434
|
+
if (results.some((result)=>{
|
|
435
|
+
const version = this.compilationVersions.get(result.compilation);
|
|
436
|
+
return void 0 === version || version !== this.compilerVersions.get(result.compilation.compiler);
|
|
437
|
+
})) return;
|
|
438
|
+
if (stats.hasErrors()) return this.fail(new Error('Native development compilation failed'));
|
|
439
|
+
try {
|
|
440
|
+
const publication = await this.publish(stats);
|
|
441
|
+
if (this.closed || epoch !== this.epoch) return;
|
|
442
|
+
this.retainedFederationAssets = publication.retainedFederationAssets;
|
|
443
|
+
this.federationAssets = new Map([
|
|
444
|
+
...publication.federationAssets,
|
|
445
|
+
...this.retainedFederationAssets
|
|
446
|
+
]);
|
|
447
|
+
this.federationRevision = publication.federationRevision;
|
|
448
|
+
this.federationGraph = publication.federationGraph;
|
|
449
|
+
this.ready = publication.entries;
|
|
450
|
+
this.failure = void 0;
|
|
451
|
+
this.notify();
|
|
452
|
+
} catch (error) {
|
|
453
|
+
if (this.closed || epoch !== this.epoch) return;
|
|
454
|
+
this.fail(error);
|
|
455
|
+
api.logger.error('Native development could not load the compiled application.', error);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
this.publication = this.publication.then(publishNext, publishNext);
|
|
459
|
+
return this.publication;
|
|
355
460
|
});
|
|
356
461
|
api.onCloseDevServer(()=>this.close());
|
|
357
462
|
}
|
|
@@ -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;
|