Project Init

This commit is contained in:
Muluhabt
2026-05-29 15:23:46 +03:00
commit 2fbc557aac
67387 changed files with 6063341 additions and 0 deletions

22
node_modules/@nx/module-federation/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2017-2026 Narwhal Technologies Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

70
node_modules/@nx/module-federation/README.md generated vendored Normal file
View File

@@ -0,0 +1,70 @@
<p style="text-align: center;">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
<img alt="Nx - Smart Monorepos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
</picture>
</p>
<div style="text-align: center;">
[![CircleCI](https://circleci.com/gh/nrwl/nx.svg?style=svg)](https://circleci.com/gh/nrwl/nx)
[![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)]()
[![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
[![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)]()
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join us on the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
</div>
<hr>
# Nx: Smart Monorepos · Fast Builds
Get to green PRs in half the time. Nx optimizes your builds, scales your CI, and fixes failed PRs. Built for developers and AI agents.
This package is a [Module Federation plugin for Nx](https://nx.dev/nx-api/module-federation).
Module Federation allows developers to share code between deployed applications easier and makes team collaboration more efficient.
To learn more about Module Federation, check out the [official documentation](https://module-federation.io/).
## Getting Started
### Creating an Nx Workspace
**Using `npx`**
```bash
npx create-nx-workspace
```
**Using `npm init`**
```bash
npm init nx-workspace
```
**Using `yarn create`**
```bash
yarn create nx-workspace
```
### Adding Nx to an Existing Repository
Run:
```bash
npx nx@latest init
```
## Documentation & Resources
- [Nx.Dev: Documentation, Guides, Tutorials](https://nx.dev)
- [Intro to Nx](https://nx.dev/getting-started/intro)
- [Official Nx YouTube Channel](https://www.youtube.com/@NxDevtools)
- [Blog Posts About Nx](https://nx.dev/blog)
<p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
width="100%" alt="Nx - Smart Monorepos · Fast Builds"></a></p>

6
node_modules/@nx/module-federation/angular.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export * from './src/with-module-federation/angular/with-module-federation';
export * from './src/with-module-federation/angular/with-module-federation-ssr';
export * from './src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin';
export * from './src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin';
export * from './src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin';
//# sourceMappingURL=angular.d.ts.map

1
node_modules/@nx/module-federation/angular.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"angular.d.ts","sourceRoot":"","sources":["../../../packages/module-federation/angular.ts"],"names":[],"mappings":"AAAA,cAAc,6DAA6D,CAAC;AAC5E,cAAc,iEAAiE,CAAC;AAChF,cAAc,+EAA+E,CAAC;AAC9F,cAAc,0FAA0F,CAAC;AACzG,cAAc,8FAA8F,CAAC"}

8
node_modules/@nx/module-federation/angular.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./src/with-module-federation/angular/with-module-federation"), exports);
tslib_1.__exportStar(require("./src/with-module-federation/angular/with-module-federation-ssr"), exports);
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin"), exports);
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin"), exports);
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin"), exports);

4
node_modules/@nx/module-federation/executors.json generated vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"$schema": "http://json-schema.org/schema",
"executors": {}
}

2
node_modules/@nx/module-federation/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from './src/utils/public-api';
//# sourceMappingURL=index.d.ts.map

1
node_modules/@nx/module-federation/index.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/module-federation/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}

4
node_modules/@nx/module-federation/index.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./src/utils/public-api"), exports);

148
node_modules/@nx/module-federation/migrations.json generated vendored Normal file
View File

@@ -0,0 +1,148 @@
{
"packageJsonUpdates": {
"20.4.0": {
"version": "20.4.0-beta.0",
"packages": {
"@module-federation/enhanced": {
"version": "^0.8.8",
"alwaysAddToPackageJson": false
},
"@module-federation/runtime": {
"version": "^0.8.8",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^0.8.8",
"alwaysAddToPackageJson": false
},
"@module-federation/node": {
"version": "^2.6.21",
"alwaysAddToPackageJson": false
}
}
},
"20.5.0": {
"version": "20.5.0-beta.5",
"packages": {
"@module-federation/enhanced": {
"version": "^0.9.0",
"alwaysAddToPackageJson": false
},
"@module-federation/runtime": {
"version": "^0.9.0",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^0.9.0",
"alwaysAddToPackageJson": false
},
"@module-federation/node": {
"version": "^2.6.26",
"alwaysAddToPackageJson": false
}
}
},
"21.2.0": {
"version": "21.2.0-beta.6",
"packages": {
"@module-federation/enhanced": {
"version": "^0.15.0",
"alwaysAddToPackageJson": false
},
"@module-federation/runtime": {
"version": "^0.15.0",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^0.15.0",
"alwaysAddToPackageJson": false
}
}
},
"21.3.0": {
"version": "21.3.0-beta.8",
"packages": {
"@module-federation/enhanced": {
"version": "^0.17.0",
"alwaysAddToPackageJson": false
},
"@module-federation/node": {
"version": "^2.7.9",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^0.17.0",
"alwaysAddToPackageJson": false
}
}
},
"21.4.0": {
"version": "21.4.0-beta.8",
"packages": {
"http-proxy-middleware": {
"version": "^3.0.5",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^0.18.0",
"alwaysAddToPackageJson": false
},
"@module-federation/enhanced": {
"version": "^0.18.0",
"alwaysAddToPackageJson": false
},
"@module-federation/runtime": {
"version": "^0.18.0",
"alwaysAddToPackageJson": false
},
"@module-federation/node": {
"version": "^2.7.11",
"alwaysAddToPackageJson": false
}
}
},
"22.2.0": {
"version": "22.2.0-beta.0",
"packages": {
"@module-federation/enhanced": {
"version": "^0.21.2",
"alwaysAddToPackageJson": false
},
"@module-federation/runtime": {
"version": "^0.21.2",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^0.21.2",
"alwaysAddToPackageJson": false
},
"@module-federation/node": {
"version": "^2.7.21",
"alwaysAddToPackageJson": false
}
}
},
"22.6.0": {
"version": "22.6.0-beta.10",
"x-prompt": "Bump @module-federation packages to v2.x to resolve koa CVE-2026-27959 (via dts-plugin)",
"packages": {
"@module-federation/enhanced": {
"version": "^2.1.0",
"alwaysAddToPackageJson": false
},
"@module-federation/runtime": {
"version": "^2.1.0",
"alwaysAddToPackageJson": false
},
"@module-federation/sdk": {
"version": "^2.1.0",
"alwaysAddToPackageJson": false
},
"@module-federation/node": {
"version": "^2.7.21",
"alwaysAddToPackageJson": false
}
}
}
}
}

49
node_modules/@nx/module-federation/package.json generated vendored Normal file
View File

@@ -0,0 +1,49 @@
{
"name": "@nx/module-federation",
"description": "The Nx Plugin for Module Federation contains executors and utilities that support building applications using Module Federation.",
"version": "22.7.5",
"type": "commonjs",
"repository": {
"type": "git",
"url": "https://github.com/nrwl/nx.git",
"directory": "packages/module-federation"
},
"bugs": {
"url": "https://github.com/nrwl/nx/issues"
},
"keywords": [
"Monorepo",
"Rspack",
"Webpack",
"Bundling",
"Module Federation"
],
"author": "Colum Ferry",
"license": "MIT",
"homepage": "https://nx.dev",
"main": "index.js",
"executors": "./executors.json",
"dependencies": {
"@module-federation/enhanced": "^2.3.3",
"@module-federation/node": "^2.7.21",
"@module-federation/sdk": "^2.1.0",
"@nx/devkit": "22.7.5",
"@nx/js": "22.7.5",
"@nx/web": "22.7.5",
"@rspack/core": "1.6.8",
"express": "^4.21.2",
"http-proxy-middleware": "^3.0.5",
"picocolors": "^1.1.0",
"tslib": "^2.3.0",
"webpack": "^5.101.3"
},
"devDependencies": {
"nx": "22.7.5"
},
"nx-migrations": {
"migrations": "./migrations.json"
},
"publishConfig": {
"access": "public"
}
}

6
node_modules/@nx/module-federation/rspack.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export * from './src/with-module-federation/rspack/with-module-federation';
export * from './src/with-module-federation/rspack/with-module-federation-ssr';
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin';
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin';
export * from './src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-ssr-dev-server-plugin';
//# sourceMappingURL=rspack.d.ts.map

1
node_modules/@nx/module-federation/rspack.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"rspack.d.ts","sourceRoot":"","sources":["../../../packages/module-federation/rspack.ts"],"names":[],"mappings":"AAAA,cAAc,4DAA4D,CAAC;AAC3E,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8EAA8E,CAAC;AAC7F,cAAc,yFAAyF,CAAC;AACxG,cAAc,6FAA6F,CAAC"}

8
node_modules/@nx/module-federation/rspack.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./src/with-module-federation/rspack/with-module-federation"), exports);
tslib_1.__exportStar(require("./src/with-module-federation/rspack/with-module-federation-ssr"), exports);
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin"), exports);
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin"), exports);
tslib_1.__exportStar(require("./src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-ssr-dev-server-plugin"), exports);

View File

@@ -0,0 +1,5 @@
import { ExecutorContext } from '@nx/devkit';
import { type StaticRemotesConfig } from '../../utils';
import { type BuildStaticRemotesOptions } from './models';
export declare function buildStaticRemotes(staticRemotesConfig: StaticRemotesConfig, nxBin: any, context: ExecutorContext, options: BuildStaticRemotesOptions, buildTarget?: 'build' | 'server'): Promise<Record<string, string>>;
//# sourceMappingURL=build-static-remotes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"build-static-remotes.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/executors/utils/build-static-remotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAU,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAM1D,wBAAsB,kBAAkB,CACtC,mBAAmB,EAAE,mBAAmB,EACxC,KAAK,KAAA,EACL,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,yBAAyB,EAClC,WAAW,GAAE,OAAO,GAAG,QAAkB,mCAsF1C"}

View File

@@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildStaticRemotes = buildStaticRemotes;
const devkit_1 = require("@nx/devkit");
const node_child_process_1 = require("node:child_process");
const path_1 = require("path");
const cache_directory_1 = require("nx/src/utils/cache-directory");
const fs_1 = require("fs");
async function buildStaticRemotes(staticRemotesConfig, nxBin, context, options, buildTarget = 'build') {
if (!staticRemotesConfig.remotes.length) {
return;
}
devkit_1.logger.info(`NX Building ${staticRemotesConfig.remotes.length} static remotes...`);
const mappedLocationOfRemotes = {};
for (const app of staticRemotesConfig.remotes) {
mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${staticRemotesConfig.config[app].urlSegment}`;
}
await new Promise((res, rej) => {
const staticProcess = (0, node_child_process_1.fork)(nxBin, [
'run-many',
`--target=${buildTarget}`,
`--projects=${staticRemotesConfig.remotes.join(',')}`,
...(context.configurationName
? [`--configuration=${context.configurationName}`]
: []),
...(options.parallel ? [`--parallel=${options.parallel}`] : []),
], {
cwd: context.root,
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
env: {
...process.env,
// Ensure that webpack serve env var is not passed to static remotes
WEBPACK_SERVE: 'false',
},
});
// File to debug build failures e.g. 2024-01-01T00_00_0_0Z-build.log'
const remoteBuildLogFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`);
const stdoutStream = (0, fs_1.createWriteStream)(remoteBuildLogFile);
staticProcess.stdout.on('data', (data) => {
const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
stdoutStream.write(stdoutString);
// in addition to writing into the stdout stream, also show error directly in console
// so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
if (stdoutString.includes('ERROR in')) {
devkit_1.logger.log(stdoutString);
}
if (stdoutString.includes(`Successfully ran target ${buildTarget}`)) {
staticProcess.stdout.removeAllListeners('data');
devkit_1.logger.info(`NX Built ${staticRemotesConfig.remotes.length} static remotes`);
res();
}
});
staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
staticProcess.once('exit', (code) => {
stdoutStream.end();
staticProcess.stdout.removeAllListeners('data');
staticProcess.stderr.removeAllListeners('data');
if (code !== 0) {
rej(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
}
else {
res();
}
});
process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
process.on('exit', () => staticProcess.kill('SIGTERM'));
});
return mappedLocationOfRemotes;
}

View File

@@ -0,0 +1,5 @@
export * from './start-static-remotes-file-server';
export * from './build-static-remotes';
export * from './start-remote-iterators';
export { DevRemoteDefinition } from './models';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/executors/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./start-static-remotes-file-server"), exports);
tslib_1.__exportStar(require("./build-static-remotes"), exports);
tslib_1.__exportStar(require("./start-remote-iterators"), exports);

View File

@@ -0,0 +1,31 @@
import type { ProjectConfiguration, ExecutorContext } from '@nx/devkit';
export type DevRemoteDefinition = string | {
remoteName: string;
configuration: string;
};
export type StartRemoteFn = (remotes: string[], workspaceProjects: Record<string, ProjectConfiguration>, options: {
devRemotes: DevRemoteDefinition[];
verbose: boolean;
}, context: ExecutorContext, target: 'serve' | 'serve-static') => Promise<AsyncIterable<{
success: boolean;
}>[]>;
export interface StaticRemotesOptions {
staticRemotesPort?: number;
host?: string;
ssl?: boolean;
sslCert?: string;
sslKey?: string;
}
export interface BuildStaticRemotesOptions extends StaticRemotesOptions {
parallel?: number;
}
export interface StartRemoteIteratorsOptions extends BuildStaticRemotesOptions {
devRemotes: DevRemoteDefinition[];
skipRemotes?: string[];
buildTarget?: string;
liveReload?: boolean;
open?: boolean;
ssl?: boolean;
verbose: boolean;
}
//# sourceMappingURL=models.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/executors/utils/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAC3B,MAAM,GACN;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EAAE,EACjB,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,EACvD,OAAO,EAAE;IACP,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;CAClB,EACD,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,OAAO,GAAG,cAAc,KAC7B,OAAO,CAAC,aAAa,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,CAAC,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,2BAA4B,SAAQ,yBAAyB;IAC5E,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB"}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,26 @@
import { StartRemoteFn, type StartRemoteIteratorsOptions } from './models';
import { type ExecutorContext } from '@nx/devkit';
export declare function startRemoteIterators(options: StartRemoteIteratorsOptions, context: ExecutorContext, startRemoteFn: StartRemoteFn, pathToManifestFile: string | undefined, pluginName?: 'react' | 'angular', isServer?: boolean): Promise<{
remotes: {
staticRemotes: string[];
devRemotes: any[];
dynamicRemotes: any[];
remotePorts: number[];
staticRemotePort: number;
};
devRemoteIters: AsyncIterable<{
success: boolean;
}>[];
staticRemotesIter: AsyncGenerator<{
success: boolean;
baseUrl: string;
}, {
success: boolean;
}, unknown> | AsyncGenerator<{
success: boolean;
baseUrl: string;
} | {
success: boolean;
}, void, unknown>;
}>;
//# sourceMappingURL=start-remote-iterators.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"start-remote-iterators.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/executors/utils/start-remote-iterators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAgB3E,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAC;AAEpB,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,eAAe,EACxB,aAAa,EAAE,aAAa,EAC5B,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,UAAU,GAAE,OAAO,GAAG,SAAmB,EACzC,QAAQ,UAAQ;;;;;;;;;;;;;;;;;;;;;;GAuGjB"}

View File

@@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startRemoteIterators = startRemoteIterators;
const utils_1 = require("../../utils");
const build_static_remotes_1 = require("./build-static-remotes");
const start_static_remotes_file_server_1 = require("./start-static-remotes-file-server");
const devkit_1 = require("@nx/devkit");
async function startRemoteIterators(options, context, startRemoteFn, pathToManifestFile, pluginName = 'react', isServer = false) {
const nxBin = require.resolve('nx/bin/nx');
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(context.projectGraph);
const project = workspaceProjects[context.projectName];
const buildTargetName = (0, utils_1.getBuildTargetNameFromMFDevServer)(project, context.projectGraph);
const moduleFederationConfig = (0, utils_1.getModuleFederationConfig)(project.targets?.[buildTargetName]?.options?.tsConfig, context.root, project.root, pluginName);
const remoteNames = options.devRemotes.map((r) => typeof r === 'string' ? r : r.remoteName);
const remotes = (0, utils_1.getRemotes)(remoteNames, options.skipRemotes, moduleFederationConfig, {
projectName: project.name,
projectGraph: context.projectGraph,
root: context.root,
}, pathToManifestFile);
options.staticRemotesPort ??= remotes.staticRemotePort;
// Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(remotes.devRemotes.map((r) => typeof r === 'string' ? r : r.remoteName) ?? []).map((r) => (0, utils_1.normalizeProjectName)(r)),
(0, utils_1.normalizeProjectName)(project.name),
]);
const staticRemotesConfig = isServer
? (0, utils_1.parseStaticSsrRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context)
: (0, utils_1.parseStaticRemotesConfig)([...remotes.staticRemotes, ...remotes.dynamicRemotes], context);
const mappedLocationsOfStaticRemotes = await (0, build_static_remotes_1.buildStaticRemotes)(staticRemotesConfig, nxBin, context, options, isServer ? 'server' : 'build');
const devRemoteIters = await startRemoteFn(remotes.devRemotes, workspaceProjects, options, context, 'serve');
const staticRemotesIter = isServer
? (0, start_static_remotes_file_server_1.startSsrStaticRemotesFileServer)(staticRemotesConfig, context, options)
: (0, start_static_remotes_file_server_1.startStaticRemotesFileServer)(staticRemotesConfig, context, options);
isServer
? await (0, utils_1.startSsrRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes, options.ssl
? {
pathToCert: options.sslCert,
pathToKey: options.sslKey,
}
: undefined, options.host)
: await (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationsOfStaticRemotes, options.ssl
? {
pathToCert: options.sslCert,
pathToKey: options.sslKey,
}
: undefined, options.host);
return {
remotes,
devRemoteIters,
staticRemotesIter,
};
}

View File

@@ -0,0 +1,16 @@
import { type ExecutorContext } from '@nx/devkit';
import { type StaticRemotesOptions } from './models';
import type { StaticRemotesConfig } from '../../utils';
export declare function startStaticRemotesFileServer(staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, options: StaticRemotesOptions, forceMoveToCommonLocation?: boolean): AsyncGenerator<{
success: boolean;
baseUrl: string;
}, {
success: boolean;
}, unknown>;
export declare function startSsrStaticRemotesFileServer(staticRemotesConfig: StaticRemotesConfig, context: ExecutorContext, options: StaticRemotesOptions): AsyncGenerator<{
success: boolean;
baseUrl: string;
} | {
success: boolean;
}, void, unknown>;
//# sourceMappingURL=start-static-remotes-file-server.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"start-static-remotes-file-server.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/executors/utils/start-static-remotes-file-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAIrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,wBAAgB,4BAA4B,CAC1C,mBAAmB,EAAE,mBAAmB,EACxC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,oBAAoB,EAC7B,yBAAyB,UAAQ;;;;;YAuDlC;AAED,wBAAuB,+BAA+B,CACpD,mBAAmB,EAAE,mBAAmB,EACxC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,oBAAoB;;;;;kBAa9B"}

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startStaticRemotesFileServer = startStaticRemotesFileServer;
exports.startSsrStaticRemotesFileServer = startSsrStaticRemotesFileServer;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const file_server_impl_1 = tslib_1.__importDefault(require("@nx/web/src/executors/file-server/file-server.impl"));
const path_1 = require("path");
const fs_1 = require("fs");
function startStaticRemotesFileServer(staticRemotesConfig, context, options, forceMoveToCommonLocation = false) {
if (!staticRemotesConfig.remotes ||
staticRemotesConfig.remotes.length === 0) {
return;
}
let shouldMoveToCommonLocation = forceMoveToCommonLocation || false;
let commonOutputDirectory;
if (!forceMoveToCommonLocation) {
for (const app of staticRemotesConfig.remotes) {
const remoteBasePath = staticRemotesConfig.config[app].basePath;
if (!commonOutputDirectory) {
commonOutputDirectory = remoteBasePath;
}
else if (commonOutputDirectory !== remoteBasePath) {
shouldMoveToCommonLocation = true;
break;
}
}
}
if (shouldMoveToCommonLocation) {
commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
for (const app of staticRemotesConfig.remotes) {
const remoteConfig = staticRemotesConfig.config[app];
(0, fs_1.cpSync)(remoteConfig.outputPath, (0, path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
force: true,
recursive: true,
});
}
}
const staticRemotesIter = (0, file_server_impl_1.default)({
cors: true,
watch: false,
staticFilePath: commonOutputDirectory,
parallel: false,
spa: false,
withDeps: false,
host: options.host,
port: options.staticRemotesPort,
ssl: options.ssl,
sslCert: options.sslCert,
sslKey: options.sslKey,
cacheSeconds: -1,
}, context);
return staticRemotesIter;
}
async function* startSsrStaticRemotesFileServer(staticRemotesConfig, context, options) {
const staticRemotesIter = startStaticRemotesFileServer(staticRemotesConfig, context, options, true);
if (!staticRemotesIter) {
yield { success: true };
return;
}
yield* staticRemotesIter;
}

View File

@@ -0,0 +1,15 @@
export interface NxModuleFederationDevServerConfig {
host?: string;
staticRemotesPort?: number;
pathToManifestFile?: string;
ssl?: boolean;
sslCert?: string;
sslKey?: string;
parallel?: number;
devRemoteFindOptions?: DevRemoteFindOptions;
}
export interface DevRemoteFindOptions {
retries?: number;
retryDelay?: number;
}
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/models/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iCAAiC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,14 @@
import { Compiler, RspackPluginInstance } from '@rspack/core';
import { ModuleFederationConfig } from '../../../utils/models';
import { NxModuleFederationDevServerConfig } from '../../models';
export declare class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
private _options;
private nxBin;
constructor(_options: {
config: ModuleFederationConfig;
devServerConfig?: NxModuleFederationDevServerConfig;
});
apply(compiler: Compiler): void;
private setup;
}
//# sourceMappingURL=nx-module-federation-dev-server-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"nx-module-federation-dev-server-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/module-federation/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-dev-server-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAER,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAY/D,OAAO,EAAE,iCAAiC,EAAE,MAAM,cAAc,CAAC;AAIjE,qBAAa,iCAAkC,YAAW,oBAAoB;IAI1E,OAAO,CAAC,QAAQ;IAHlB,OAAO,CAAC,KAAK,CAAgC;gBAGnC,QAAQ,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAC;QAC/B,eAAe,CAAC,EAAE,iCAAiC,CAAC;KACrD;IAOH,KAAK,CAAC,QAAQ,EAAE,QAAQ;YAoDV,KAAK;CAyDpB"}

View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NxModuleFederationDevServerPlugin = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@rspack/core");
const pc = tslib_1.__importStar(require("picocolors"));
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const fs_1 = require("fs");
const utils_1 = require("../../utils");
const PLUGIN_NAME = 'NxModuleFederationDevServerPlugin';
class NxModuleFederationDevServerPlugin {
constructor(_options) {
this._options = _options;
this.nxBin = require.resolve('nx/bin/nx');
this._options.devServerConfig ??= {
host: 'localhost',
};
}
apply(compiler) {
const isDevServer = process.env['WEBPACK_SERVE'];
if (!isDevServer) {
return;
}
let initialized = false;
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
if (!initialized) {
initialized = true;
const staticRemotesConfig = await this.setup();
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
(0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
await (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
pathToCert: this._options.devServerConfig.sslCert,
pathToKey: this._options.devServerConfig.sslKey,
}, false, this._options.devServerConfig.host);
new core_1.DefinePlugin({
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
}).apply(compiler);
}
callback();
});
}
async setup() {
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
const project = workspaceProjects[this._options.config.name];
if (!this._options.devServerConfig.pathToManifestFile) {
this._options.devServerConfig.pathToManifestFile =
(0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
}
else {
const userPathToManifestFile = this._options.devServerConfig.pathToManifestFile.startsWith(devkit_1.workspaceRoot)
? this._options.devServerConfig.pathToManifestFile
: (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
}
else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
}
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
}
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph);
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {}, this._options.devServerConfig?.devRemoteFindOptions, this._options.devServerConfig?.host);
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(devRemotes.length > 0 ? devRemotes : []),
project.name,
]);
return staticRemotesConfig ?? {};
}
}
exports.NxModuleFederationDevServerPlugin = NxModuleFederationDevServerPlugin;

View File

@@ -0,0 +1,12 @@
import { Compiler, RspackPluginInstance } from '@rspack/core';
import { ModuleFederationConfig, NxModuleFederationConfigOverride } from '../../../utils/models';
export declare class NxModuleFederationPlugin implements RspackPluginInstance {
private _options;
private configOverride?;
constructor(_options: {
config: ModuleFederationConfig;
isServer?: boolean;
}, configOverride?: NxModuleFederationConfigOverride);
apply(compiler: Compiler): void;
}
//# sourceMappingURL=nx-module-federation-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"nx-module-federation-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/module-federation/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EACjC,MAAM,uBAAuB,CAAC;AAK/B,qBAAa,wBAAyB,YAAW,oBAAoB;IAEjE,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,cAAc,CAAC;gBAJf,QAAQ,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAC;QAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,EACO,cAAc,CAAC,EAAE,gCAAgC;IAG3D,KAAK,CAAC,QAAQ,EAAE,QAAQ;CA0FzB"}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NxModuleFederationPlugin = void 0;
const utils_1 = require("../../../with-module-federation/angular/utils");
const utils_2 = require("../../../utils");
const devkit_1 = require("@nx/devkit");
class NxModuleFederationPlugin {
constructor(_options, configOverride) {
this._options = _options;
this.configOverride = configOverride;
}
apply(compiler) {
if (global.NX_GRAPH_CREATION) {
return;
}
// This is required to ensure Module Federation will build the project correctly
compiler.options.optimization ??= {};
compiler.options.optimization.runtimeChunk =
process.env['WEBPACK_SERVE'] && !this._options.config.exposes
? (compiler.options.optimization?.runtimeChunk ?? undefined)
: false;
if (compiler.options.optimization.splitChunks) {
compiler.options.optimization.splitChunks.cacheGroups ??= {};
compiler.options.optimization.splitChunks.cacheGroups.default = false;
compiler.options.optimization.splitChunks.cacheGroups.common = false;
}
compiler.options.output.publicPath = !compiler.options.output.publicPath
? 'auto'
: compiler.options.output.publicPath;
compiler.options.output.uniqueName = this._options.config.name;
// Ensure workspace root is in resolve.modules so that expose paths
// like "apps/remote/src/..." resolve correctly without baseUrl.
compiler.options.resolve ??= {};
compiler.options.resolve.modules = [
...(compiler.options.resolve.modules ?? ['node_modules']),
devkit_1.workspaceRoot,
];
if (this._options.isServer) {
compiler.options.target = 'async-node';
compiler.options.output.library ??= {
type: 'commonjs-module',
};
compiler.options.output.library.type = 'commonjs-module';
}
else {
// Ensure ESM output is enabled when using library type 'module'.
// Without these, remoteEntry.js emits `export` statements but the
// runtime loads it as a classic script, causing "Unexpected token 'export'".
compiler.options.experiments ??= {};
compiler.options.experiments.outputModule = true;
compiler.options.output.module = true;
}
const config = (0, utils_1.getModuleFederationConfigSync)(this._options.config, {
isServer: this._options.isServer,
}, true);
const sharedLibraries = config.sharedLibraries;
const sharedDependencies = config.sharedDependencies;
const mappedRemotes = config.mappedRemotes;
const runtimePlugins = [];
if (this.configOverride?.runtimePlugins) {
runtimePlugins.push(...(this.configOverride.runtimePlugins ?? []));
}
if (this._options.isServer) {
runtimePlugins.push(require.resolve('@module-federation/node/runtimePlugin'));
}
new (require('@module-federation/enhanced/rspack').ModuleFederationPlugin)({
name: (0, utils_2.normalizeProjectName)(this._options.config.name),
filename: 'remoteEntry.js',
exposes: this._options.config.exposes,
remotes: mappedRemotes,
shared: {
...(sharedDependencies ?? {}),
},
...(this._options.isServer
? {
library: {
type: 'commonjs-module',
},
remoteType: 'script',
}
: { library: { type: 'module' } }),
...(this.configOverride ? this.configOverride : {}),
runtimePlugins,
}).apply(compiler);
if (sharedLibraries) {
sharedLibraries.getReplacementPlugin().apply(compiler);
}
}
}
exports.NxModuleFederationPlugin = NxModuleFederationPlugin;

View File

@@ -0,0 +1,16 @@
import { Compiler, RspackPluginInstance } from '@rspack/core';
import { ModuleFederationConfig } from '../../../utils/models';
import { NxModuleFederationDevServerConfig } from '../../models';
export declare class NxModuleFederationSSRDevServerPlugin implements RspackPluginInstance {
private _options;
private devServerProcess;
private nxBin;
constructor(_options: {
config: ModuleFederationConfig;
devServerConfig?: NxModuleFederationDevServerConfig;
});
apply(compiler: Compiler): void;
private startServer;
private setup;
}
//# sourceMappingURL=nx-module-federation-ssr-dev-server-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"nx-module-federation-ssr-dev-server-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/module-federation/src/plugins/nx-module-federation-plugin/angular/nx-module-federation-ssr-dev-server-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAER,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAY/D,OAAO,EAAE,iCAAiC,EAAE,MAAM,cAAc,CAAC;AAKjE,qBAAa,oCACX,YAAW,oBAAoB;IAM7B,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,KAAK,CAAgC;gBAGnC,QAAQ,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAC;QAC/B,eAAe,CAAC,EAAE,iCAAiC,CAAC;KACrD;IAOH,KAAK,CAAC,QAAQ,EAAE,QAAQ;YAsDV,WAAW;YAuCX,KAAK;CAmDpB"}

View File

@@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NxModuleFederationSSRDevServerPlugin = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@rspack/core");
const pc = tslib_1.__importStar(require("picocolors"));
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const fs_1 = require("fs");
const utils_1 = require("../../utils");
const node_child_process_1 = require("node:child_process");
const PLUGIN_NAME = 'NxModuleFederationSSRDevServerPlugin';
class NxModuleFederationSSRDevServerPlugin {
constructor(_options) {
this._options = _options;
this.nxBin = require.resolve('nx/bin/nx');
this._options.devServerConfig ??= {
host: 'localhost',
};
}
apply(compiler) {
const isDevServer = process.env['WEBPACK_SERVE'];
if (!isDevServer) {
return;
}
compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
const staticRemotesConfig = await this.setup(compiler);
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
(0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
await (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
pathToCert: this._options.devServerConfig.sslCert,
pathToKey: this._options.devServerConfig.sslKey,
}, true, this._options.devServerConfig.host);
new core_1.DefinePlugin({
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
}).apply(compiler);
await this.startServer(compiler);
callback();
});
callback();
});
}
async startServer(compiler) {
compiler.hooks.done.tapAsync(PLUGIN_NAME, async (_, callback) => {
const serverPath = (0, path_1.join)(compiler.options.output.path, compiler.options.output.filename ?? 'server.js');
if (this.devServerProcess) {
await new Promise((res) => {
this.devServerProcess.on('exit', () => {
res();
});
this.devServerProcess.kill('SIGKILL');
this.devServerProcess = undefined;
});
}
if (!(0, fs_1.existsSync)(serverPath)) {
for (let retries = 0; retries < 10; retries++) {
await new Promise((res) => setTimeout(res, 200));
if ((0, fs_1.existsSync)(serverPath)) {
break;
}
}
if (!(0, fs_1.existsSync)(serverPath)) {
throw new Error(`Could not find server bundle at ${serverPath}.`);
}
}
this.devServerProcess = (0, node_child_process_1.fork)(serverPath);
process.on('exit', () => {
this.devServerProcess?.kill('SIGKILL');
});
process.on('SIGINT', () => {
this.devServerProcess?.kill('SIGKILL');
});
callback();
});
}
async setup(compiler) {
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
const project = workspaceProjects[this._options.config.name];
if (!this._options.devServerConfig.pathToManifestFile) {
this._options.devServerConfig.pathToManifestFile =
(0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
}
else {
const userPathToManifestFile = (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
}
else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
}
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
}
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph, true);
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {});
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(devRemotes.length > 0 ? devRemotes : []),
project.name,
]);
return staticRemotesConfig ?? {};
}
}
exports.NxModuleFederationSSRDevServerPlugin = NxModuleFederationSSRDevServerPlugin;

View File

@@ -0,0 +1,14 @@
import { Compiler, RspackPluginInstance } from '@rspack/core';
import { ModuleFederationConfig } from '../../../utils/models';
import { NxModuleFederationDevServerConfig } from '../../models';
export declare class NxModuleFederationDevServerPlugin implements RspackPluginInstance {
private _options;
private nxBin;
constructor(_options: {
config: ModuleFederationConfig;
devServerConfig?: NxModuleFederationDevServerConfig;
});
apply(compiler: Compiler): void;
private setup;
}
//# sourceMappingURL=nx-module-federation-dev-server-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"nx-module-federation-dev-server-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/module-federation/src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-dev-server-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAER,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAY/D,OAAO,EAAE,iCAAiC,EAAE,MAAM,cAAc,CAAC;AAIjE,qBAAa,iCAAkC,YAAW,oBAAoB;IAI1E,OAAO,CAAC,QAAQ;IAHlB,OAAO,CAAC,KAAK,CAAgC;gBAGnC,QAAQ,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAC;QAC/B,eAAe,CAAC,EAAE,iCAAiC,CAAC;KACrD;IAOH,KAAK,CAAC,QAAQ,EAAE,QAAQ;YAoDV,KAAK;CAyDpB"}

View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NxModuleFederationDevServerPlugin = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@rspack/core");
const pc = tslib_1.__importStar(require("picocolors"));
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const fs_1 = require("fs");
const utils_1 = require("../../utils");
const PLUGIN_NAME = 'NxModuleFederationDevServerPlugin';
class NxModuleFederationDevServerPlugin {
constructor(_options) {
this._options = _options;
this.nxBin = require.resolve('nx/bin/nx');
this._options.devServerConfig ??= {
host: 'localhost',
};
}
apply(compiler) {
const isDevServer = process.env['WEBPACK_SERVE'];
if (!isDevServer) {
return;
}
let initialized = false;
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
if (!initialized) {
initialized = true;
const staticRemotesConfig = await this.setup();
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
(0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
await (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
pathToCert: this._options.devServerConfig.sslCert,
pathToKey: this._options.devServerConfig.sslKey,
}, false, this._options.devServerConfig.host);
new core_1.DefinePlugin({
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
}).apply(compiler);
}
callback();
});
}
async setup() {
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
const project = workspaceProjects[this._options.config.name];
if (!this._options.devServerConfig.pathToManifestFile) {
this._options.devServerConfig.pathToManifestFile =
(0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
}
else {
const userPathToManifestFile = this._options.devServerConfig.pathToManifestFile.startsWith(devkit_1.workspaceRoot)
? this._options.devServerConfig.pathToManifestFile
: (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
}
else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
}
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
}
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph);
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {}, this._options.devServerConfig?.devRemoteFindOptions, this._options.devServerConfig?.host);
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(devRemotes.length > 0 ? devRemotes : []),
project.name,
]);
return staticRemotesConfig ?? {};
}
}
exports.NxModuleFederationDevServerPlugin = NxModuleFederationDevServerPlugin;

View File

@@ -0,0 +1,12 @@
import { Compiler, RspackPluginInstance } from '@rspack/core';
import { ModuleFederationConfig, NxModuleFederationConfigOverride } from '../../../utils/models';
export declare class NxModuleFederationPlugin implements RspackPluginInstance {
private _options;
private configOverride?;
constructor(_options: {
config: ModuleFederationConfig;
isServer?: boolean;
}, configOverride?: NxModuleFederationConfigOverride);
apply(compiler: Compiler): void;
}
//# sourceMappingURL=nx-module-federation-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"nx-module-federation-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/module-federation/src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EACjC,MAAM,uBAAuB,CAAC;AAK/B,qBAAa,wBAAyB,YAAW,oBAAoB;IAEjE,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,cAAc,CAAC;gBAJf,QAAQ,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAC;QAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,EACO,cAAc,CAAC,EAAE,gCAAgC;IAG3D,KAAK,CAAC,QAAQ,EAAE,QAAQ;CA0EzB"}

View File

@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NxModuleFederationPlugin = void 0;
const utils_1 = require("../../../with-module-federation/rspack/utils");
const utils_2 = require("../../../utils");
const devkit_1 = require("@nx/devkit");
class NxModuleFederationPlugin {
constructor(_options, configOverride) {
this._options = _options;
this.configOverride = configOverride;
}
apply(compiler) {
if (global.NX_GRAPH_CREATION) {
return;
}
// This is required to ensure Module Federation will build the project correctly
compiler.options.optimization ??= {};
compiler.options.optimization.runtimeChunk = false;
if (compiler.options.optimization.splitChunks) {
compiler.options.optimization.splitChunks.cacheGroups ??= {};
compiler.options.optimization.splitChunks.cacheGroups.default = false;
compiler.options.optimization.splitChunks.cacheGroups.common = false;
}
compiler.options.output.uniqueName = this._options.config.name;
// Ensure workspace root is in resolve.modules so that expose paths
// like "apps/remote/src/..." resolve correctly without baseUrl.
compiler.options.resolve ??= {};
compiler.options.resolve.modules = [
...(compiler.options.resolve.modules ?? ['node_modules']),
devkit_1.workspaceRoot,
];
if (compiler.options.output.scriptType === 'module') {
compiler.options.output.scriptType = undefined;
compiler.options.output.module = undefined;
}
if (this._options.isServer) {
compiler.options.target = 'async-node';
compiler.options.output.library ??= {
type: 'commonjs-module',
};
compiler.options.output.library.type = 'commonjs-module';
}
const config = (0, utils_1.getModuleFederationConfig)(this._options.config, {
isServer: this._options.isServer,
});
const sharedLibraries = config.sharedLibraries;
const sharedDependencies = config.sharedDependencies;
const mappedRemotes = config.mappedRemotes;
const runtimePlugins = [];
if (this.configOverride?.runtimePlugins) {
runtimePlugins.push(...(this.configOverride.runtimePlugins ?? []));
}
if (this._options.isServer) {
runtimePlugins.push(require.resolve('@module-federation/node/runtimePlugin'));
}
new (require('@module-federation/enhanced/rspack').ModuleFederationPlugin)({
name: (0, utils_2.normalizeProjectName)(this._options.config.name),
filename: 'remoteEntry.js',
exposes: this._options.config.exposes,
remotes: mappedRemotes,
shared: {
...(sharedDependencies ?? {}),
},
...(this._options.isServer
? {
library: {
type: 'commonjs-module',
},
remoteType: 'script',
}
: {}),
...(this.configOverride ? this.configOverride : {}),
runtimePlugins,
}).apply(compiler);
if (sharedLibraries) {
sharedLibraries.getReplacementPlugin().apply(compiler);
}
}
}
exports.NxModuleFederationPlugin = NxModuleFederationPlugin;

View File

@@ -0,0 +1,16 @@
import { Compiler, RspackPluginInstance } from '@rspack/core';
import { ModuleFederationConfig } from '../../../utils/models';
import { NxModuleFederationDevServerConfig } from '../../models';
export declare class NxModuleFederationSSRDevServerPlugin implements RspackPluginInstance {
private _options;
private devServerProcess;
private nxBin;
constructor(_options: {
config: ModuleFederationConfig;
devServerConfig?: NxModuleFederationDevServerConfig;
});
apply(compiler: Compiler): void;
private startServer;
private setup;
}
//# sourceMappingURL=nx-module-federation-ssr-dev-server-plugin.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"nx-module-federation-ssr-dev-server-plugin.d.ts","sourceRoot":"","sources":["../../../../../../../packages/module-federation/src/plugins/nx-module-federation-plugin/rspack/nx-module-federation-ssr-dev-server-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAER,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAY/D,OAAO,EAAE,iCAAiC,EAAE,MAAM,cAAc,CAAC;AAKjE,qBAAa,oCACX,YAAW,oBAAoB;IAM7B,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,KAAK,CAAgC;gBAGnC,QAAQ,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAC;QAC/B,eAAe,CAAC,EAAE,iCAAiC,CAAC;KACrD;IAOH,KAAK,CAAC,QAAQ,EAAE,QAAQ;YAsDV,WAAW;YAuCX,KAAK;CAmDpB"}

View File

@@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NxModuleFederationSSRDevServerPlugin = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@rspack/core");
const pc = tslib_1.__importStar(require("picocolors"));
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const fs_1 = require("fs");
const utils_1 = require("../../utils");
const node_child_process_1 = require("node:child_process");
const PLUGIN_NAME = 'NxModuleFederationSSRDevServerPlugin';
class NxModuleFederationSSRDevServerPlugin {
constructor(_options) {
this._options = _options;
this.nxBin = require.resolve('nx/bin/nx');
this._options.devServerConfig ??= {
host: 'localhost',
};
}
apply(compiler) {
const isDevServer = process.env['WEBPACK_SERVE'];
if (!isDevServer) {
return;
}
compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
const staticRemotesConfig = await this.setup(compiler);
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(this._options.config.name)} with ${Object.keys(staticRemotesConfig).length} remotes`);
const mappedLocationOfRemotes = await (0, utils_1.buildStaticRemotes)(staticRemotesConfig, this._options.devServerConfig, this.nxBin);
(0, utils_1.startStaticRemotesFileServer)(staticRemotesConfig, devkit_1.workspaceRoot, this._options.devServerConfig.staticRemotesPort);
await (0, utils_1.startRemoteProxies)(staticRemotesConfig, mappedLocationOfRemotes, {
pathToCert: this._options.devServerConfig.sslCert,
pathToKey: this._options.devServerConfig.sslKey,
}, true, this._options.devServerConfig.host);
new core_1.DefinePlugin({
'process.env.NX_MF_DEV_REMOTES': process.env.NX_MF_DEV_REMOTES,
}).apply(compiler);
await this.startServer(compiler);
callback();
});
callback();
});
}
async startServer(compiler) {
compiler.hooks.done.tapAsync(PLUGIN_NAME, async (_, callback) => {
const serverPath = (0, path_1.join)(compiler.options.output.path, compiler.options.output.filename ?? 'server.js');
if (this.devServerProcess) {
await new Promise((res) => {
this.devServerProcess.on('exit', () => {
res();
});
this.devServerProcess.kill('SIGKILL');
this.devServerProcess = undefined;
});
}
if (!(0, fs_1.existsSync)(serverPath)) {
for (let retries = 0; retries < 10; retries++) {
await new Promise((res) => setTimeout(res, 200));
if ((0, fs_1.existsSync)(serverPath)) {
break;
}
}
if (!(0, fs_1.existsSync)(serverPath)) {
throw new Error(`Could not find server bundle at ${serverPath}.`);
}
}
this.devServerProcess = (0, node_child_process_1.fork)(serverPath);
process.on('exit', () => {
this.devServerProcess?.kill('SIGKILL');
});
process.on('SIGINT', () => {
this.devServerProcess?.kill('SIGKILL');
});
callback();
});
}
async setup(compiler) {
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
const project = workspaceProjects[this._options.config.name];
if (!this._options.devServerConfig.pathToManifestFile) {
this._options.devServerConfig.pathToManifestFile =
(0, utils_1.getDynamicMfManifestFile)(project, devkit_1.workspaceRoot);
}
else {
const userPathToManifestFile = (0, path_1.join)(devkit_1.workspaceRoot, this._options.devServerConfig.pathToManifestFile);
if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
}
else if ((0, path_1.extname)(this._options.devServerConfig.pathToManifestFile) !== '.json') {
throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
}
this._options.devServerConfig.pathToManifestFile = userPathToManifestFile;
}
const { remotes, staticRemotePort } = (0, utils_1.getRemotes)(this._options.config, projectGraph, this._options.devServerConfig.pathToManifestFile);
this._options.devServerConfig.staticRemotesPort ??= staticRemotePort;
const remotesConfig = (0, utils_1.parseRemotesConfig)(remotes, devkit_1.workspaceRoot, projectGraph, true);
const staticRemotesConfig = await (0, utils_1.getStaticRemotes)(remotesConfig.config ?? {});
const devRemotes = remotes.filter((r) => !staticRemotesConfig[r]);
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(devRemotes.length > 0 ? devRemotes : []),
project.name,
]);
return staticRemotesConfig ?? {};
}
}
exports.NxModuleFederationSSRDevServerPlugin = NxModuleFederationSSRDevServerPlugin;

View File

@@ -0,0 +1,4 @@
import { StaticRemoteConfig } from '../../utils';
import { NxModuleFederationDevServerConfig } from '../models';
export declare function buildStaticRemotes(staticRemotesConfig: Record<string, StaticRemoteConfig>, options: NxModuleFederationDevServerConfig, nxBin: string): Promise<Record<string, string>>;
//# sourceMappingURL=build-static-remotes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"build-static-remotes.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/build-static-remotes.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iCAAiC,EAAE,MAAM,WAAW,CAAC;AAE9D,wBAAsB,kBAAkB,CACtC,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACvD,OAAO,EAAE,iCAAiC,EAC1C,KAAK,EAAE,MAAM,mCA2Ed"}

View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildStaticRemotes = buildStaticRemotes;
const node_child_process_1 = require("node:child_process");
const path_1 = require("path");
const node_fs_1 = require("node:fs");
const cache_directory_1 = require("nx/src/utils/cache-directory");
const devkit_1 = require("@nx/devkit");
async function buildStaticRemotes(staticRemotesConfig, options, nxBin) {
const remotes = Object.keys(staticRemotesConfig);
if (!remotes.length) {
return;
}
const mappedLocationOfRemotes = {};
for (const app of remotes) {
mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host ?? 'localhost'}:${options.staticRemotesPort}/${staticRemotesConfig[app].urlSegment}`;
}
await new Promise((res, rej) => {
console.log(`NX Building ${remotes.length} static remotes...`);
const staticProcess = (0, node_child_process_1.fork)(nxBin, [
'run-many',
`--target=build`,
`--projects=${remotes.join(',')}`,
...(options.parallel ? [`--parallel=${options.parallel}`] : []),
], {
cwd: devkit_1.workspaceRoot,
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
env: {
...process.env,
WEBPACK_SERVE: 'false',
},
});
// File to debug build failures e.g. 2024-01-01T00_00_0_0Z-build.log'
const remoteBuildLogFile = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, `${new Date().toISOString().replace(/[:\.]/g, '_')}-build.log`);
const stdoutStream = (0, node_fs_1.createWriteStream)(remoteBuildLogFile);
staticProcess.stdout?.on('data', (data) => {
const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
stdoutStream.write(stdoutString);
// in addition to writing into the stdout stream, also show error directly in console
// so the error is easily discoverable. 'ERROR in' is the key word to search in webpack output.
if (stdoutString.includes('ERROR in')) {
console.log(stdoutString);
}
if (stdoutString.includes('Successfully ran target build')) {
staticProcess.stdout?.removeAllListeners('data');
console.info(`NX Built ${remotes.length} static remotes`);
res();
}
});
staticProcess.stderr?.on('data', (data) => console.log(data.toString()));
staticProcess.once('exit', (code) => {
stdoutStream.end();
staticProcess.stdout?.removeAllListeners('data');
staticProcess.stderr?.removeAllListeners('data');
if (code !== 0) {
rej(`Remote failed to start. A complete log can be found in: ${remoteBuildLogFile}`);
}
else {
res();
}
});
process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
process.on('exit', () => staticProcess.kill('SIGTERM'));
});
return mappedLocationOfRemotes;
}

View File

@@ -0,0 +1,3 @@
import { type ProjectConfiguration } from '@nx/devkit';
export declare function getDynamicMfManifestFile(project: ProjectConfiguration, workspaceRoot: string): string | undefined;
//# sourceMappingURL=get-dynamic-manifest-file.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-dynamic-manifest-file.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/get-dynamic-manifest-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,MAAM,GACpB,MAAM,GAAG,SAAS,CAepB"}

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDynamicMfManifestFile = getDynamicMfManifestFile;
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
const fs_1 = require("fs");
const path_1 = require("path");
function getDynamicMfManifestFile(project, workspaceRoot) {
// {sourceRoot}/assets/module-federation.manifest.json was the generated
// path for the manifest file in the past. We now generate the manifest
// file at {root}/public/module-federation.manifest.json. This check
// ensures that we can still support the old path for backwards
// compatibility since old projects may still have the manifest file
// at the old path.
return [
(0, path_1.join)(workspaceRoot, project.root, 'public/module-federation.manifest.json'),
(0, path_1.join)(workspaceRoot, (0, ts_solution_setup_1.getProjectSourceRoot)(project), 'assets/module-federation.manifest.json'),
].find((path) => (0, fs_1.existsSync)(path));
}

View File

@@ -0,0 +1,8 @@
import { ProjectGraph } from '@nx/devkit';
import { ModuleFederationConfig } from '../../utils';
export declare function getRemotes(config: ModuleFederationConfig, projectGraph: ProjectGraph, pathToManifestFile?: string): {
remotes: string[];
remotePorts: any[];
staticRemotePort: number;
};
//# sourceMappingURL=get-remotes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-remotes.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/get-remotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAiB,MAAM,YAAY,CAAC;AACjE,OAAO,EAA6B,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAIhF,wBAAgB,UAAU,CACxB,MAAM,EAAE,sBAAsB,EAC9B,YAAY,EAAE,YAAY,EAC1B,kBAAkB,CAAC,EAAE,MAAM;;;;EAoC5B"}

View File

@@ -0,0 +1,68 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRemotes = getRemotes;
const devkit_1 = require("@nx/devkit");
const utils_1 = require("../../utils");
const fs_1 = require("fs");
const path_1 = require("path");
function getRemotes(config, projectGraph, pathToManifestFile) {
const collectedRemotes = new Set();
const { remotes, dynamicRemotes } = extractRemoteProjectsFromConfig(config, pathToManifestFile);
remotes.forEach((r) => collectRemoteProjects(r, collectedRemotes, projectGraph));
// With dynamic remotes, the manifest file may contain the names with `_` due to MF limitations on naming
// The project graph might contain these names with `-` rather than `_`. Check for both.
// This can occur after migration of existing remotes past Nx 19.8
let normalizedDynamicRemotes = dynamicRemotes.map((r) => {
if (projectGraph.nodes[r.replace(/_/g, '-')]) {
return r.replace(/_/g, '-');
}
return r;
});
const knownDynamicRemotes = normalizedDynamicRemotes.filter((r) => projectGraph.nodes[r]);
knownDynamicRemotes.forEach((r) => collectRemoteProjects(r, collectedRemotes, projectGraph));
const remotePorts = [...collectedRemotes, ...knownDynamicRemotes].map((r) => projectGraph.nodes[r].data.targets['serve'].options.port);
const staticRemotePort = Math.max(...[...remotePorts]) + 1;
return {
remotes: Array.from(collectedRemotes),
remotePorts,
staticRemotePort,
};
}
function extractRemoteProjectsFromConfig(config, pathToManifestFile) {
const remotes = [];
const dynamicRemotes = [];
if (pathToManifestFile && (0, fs_1.existsSync)(pathToManifestFile)) {
const moduleFederationManifestJson = (0, fs_1.readFileSync)(pathToManifestFile, 'utf-8');
if (moduleFederationManifestJson) {
/**
*
* This should have shape of
* {
* "remoteName": "remoteLocation",
* }
* But users might have their own, enforce only that the key is the remote name
*/
const parsedManifest = JSON.parse(moduleFederationManifestJson);
if (Object.keys(parsedManifest).every((key) => typeof key === 'string')) {
dynamicRemotes.push(...Object.keys(parsedManifest));
}
}
}
const staticRemotes = config.remotes?.map((r) => (Array.isArray(r) ? r[0] : r)) ?? [];
remotes.push(...staticRemotes);
return { remotes, dynamicRemotes };
}
function collectRemoteProjects(remote, collected, projectGraph) {
const remoteProject = projectGraph.nodes[remote]?.data;
if (!projectGraph.nodes[remote] || collected.has(remote)) {
return;
}
collected.add(remote);
const remoteProjectRoot = remoteProject.root;
let remoteProjectTsConfig = ['tsconfig.app.json', 'tsconfig.json']
.map((p) => (0, path_1.join)(devkit_1.workspaceRoot, remoteProjectRoot, p))
.find((p) => (0, fs_1.existsSync)(p));
const remoteProjectConfig = (0, utils_1.getModuleFederationConfig)(remoteProjectTsConfig, devkit_1.workspaceRoot, remoteProjectRoot);
const { remotes: remoteProjectRemotes } = extractRemoteProjectsFromConfig(remoteProjectConfig);
remoteProjectRemotes.forEach((r) => collectRemoteProjects(r, collected, projectGraph));
}

View File

@@ -0,0 +1,4 @@
import { StaticRemoteConfig } from '../../utils';
import { DevRemoteFindOptions } from '../models';
export declare function getStaticRemotes(remotesConfig: Record<string, StaticRemoteConfig>, devRemoteFindOptions?: DevRemoteFindOptions, host?: string): Promise<Record<string, StaticRemoteConfig>>;
//# sourceMappingURL=get-static-remotes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-static-remotes.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/get-static-remotes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACjD,oBAAoB,CAAC,EAAE,oBAAoB,EAC3C,IAAI,GAAE,MAAoB,+CA8B3B"}

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStaticRemotes = getStaticRemotes;
const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
async function getStaticRemotes(remotesConfig, devRemoteFindOptions, host = '127.0.0.1') {
const remotes = Object.keys(remotesConfig);
const findStaticRemotesPromises = [];
for (const remote of remotes) {
findStaticRemotesPromises.push(new Promise((resolve, reject) => {
(0, wait_for_port_open_1.waitForPortOpen)(remotesConfig[remote].port, {
retries: devRemoteFindOptions?.retries ?? 3,
retryDelay: devRemoteFindOptions?.retryDelay ?? 1000,
host,
}).then((res) => {
resolve(undefined);
}, (rej) => {
resolve(remote);
});
}));
}
const staticRemoteNames = (await Promise.all(findStaticRemotesPromises)).filter(Boolean);
let staticRemotesConfig = {};
for (const remote of staticRemoteNames) {
staticRemotesConfig[remote] = remotesConfig[remote];
}
return staticRemotesConfig;
}

View File

@@ -0,0 +1,8 @@
export * from './build-static-remotes';
export * from './get-dynamic-manifest-file';
export * from './get-remotes';
export * from './get-static-remotes';
export * from './parse-remotes-config';
export * from './start-remote-proxies';
export * from './start-static-remotes-file-server';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oCAAoC,CAAC"}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./build-static-remotes"), exports);
tslib_1.__exportStar(require("./get-dynamic-manifest-file"), exports);
tslib_1.__exportStar(require("./get-remotes"), exports);
tslib_1.__exportStar(require("./get-static-remotes"), exports);
tslib_1.__exportStar(require("./parse-remotes-config"), exports);
tslib_1.__exportStar(require("./start-remote-proxies"), exports);
tslib_1.__exportStar(require("./start-static-remotes-file-server"), exports);

View File

@@ -0,0 +1,7 @@
import { ProjectGraph } from '@nx/devkit';
import { StaticRemoteConfig } from '../../utils';
export declare function parseRemotesConfig(remotes: string[] | undefined, workspaceRoot: string, projectGraph: ProjectGraph, isServer?: boolean): {
remotes: string[];
config: Record<string, StaticRemoteConfig>;
};
//# sourceMappingURL=parse-remotes-config.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parse-remotes-config.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/parse-remotes-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,EAC7B,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,YAAY,EAC1B,QAAQ,CAAC,EAAE,OAAO;;;EAmCnB"}

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseRemotesConfig = parseRemotesConfig;
const path_1 = require("path");
const devkit_internals_1 = require("nx/src/devkit-internals");
const devkit_1 = require("@nx/devkit");
function parseRemotesConfig(remotes, workspaceRoot, projectGraph, isServer) {
if (!remotes?.length) {
return { remotes: [], config: undefined };
}
const config = {};
for (const app of remotes) {
const projectRoot = projectGraph.nodes[app].data.root;
let outputPath = (0, devkit_internals_1.interpolate)(projectGraph.nodes[app].data.targets?.['build']?.options?.outputPath ??
projectGraph.nodes[app].data.targets?.['build']?.outputs?.[0] ??
`${workspaceRoot ? `${workspaceRoot}/` : ''}${projectGraph.nodes[app].data.root}/dist`, {
projectName: projectGraph.nodes[app].data.name,
projectRoot,
workspaceRoot,
});
if (!outputPath.startsWith(workspaceRoot)) {
outputPath = (0, devkit_1.joinPathFragments)(workspaceRoot, outputPath);
}
const basePath = (0, path_1.dirname)(outputPath);
const urlSegment = app;
const port = projectGraph.nodes[app].data.targets?.['serve']?.options.port;
config[app] = {
basePath,
outputPath: isServer ? (0, path_1.dirname)(outputPath) : outputPath,
urlSegment,
port,
};
}
return { remotes, config };
}

View File

@@ -0,0 +1,6 @@
import { StaticRemoteConfig } from '../../utils';
export declare function startRemoteProxies(staticRemotesConfig: Record<string, StaticRemoteConfig>, mappedLocationsOfRemotes: Record<string, string>, sslOptions?: {
pathToCert: string;
pathToKey: string;
}, isServer?: boolean, host?: string): Promise<void>;
//# sourceMappingURL=start-remote-proxies.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"start-remote-proxies.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/start-remote-proxies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,MAAM,aAAa,CAAC;AAI9D,wBAAsB,kBAAkB,CACtC,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACvD,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChD,UAAU,CAAC,EAAE;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,EACD,QAAQ,CAAC,EAAE,OAAO,EAClB,IAAI,GAAE,MAAoB,iBAwE3B"}

View File

@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startRemoteProxies = startRemoteProxies;
const utils_1 = require("../../utils");
const fs_1 = require("fs");
async function startRemoteProxies(staticRemotesConfig, mappedLocationsOfRemotes, sslOptions, isServer, host = '127.0.0.1') {
const { createProxyMiddleware } = require('http-proxy-middleware');
const express = require('express');
let sslCert;
let sslKey;
if (sslOptions && sslOptions.pathToCert && sslOptions.pathToKey) {
if ((0, fs_1.existsSync)(sslOptions.pathToCert) && (0, fs_1.existsSync)(sslOptions.pathToKey)) {
sslCert = (0, fs_1.readFileSync)(sslOptions.pathToCert);
sslKey = (0, fs_1.readFileSync)(sslOptions.pathToKey);
}
else {
console.warn(`Encountered SSL options in project.json, however, the certificate files do not exist in the filesystem. Using http.`);
console.warn(`Attempted to find '${sslOptions.pathToCert}' and '${sslOptions.pathToKey}'.`);
}
}
const http = require('http');
const https = require('https');
const remotes = Object.keys(staticRemotesConfig);
console.log(`NX Starting static remotes proxies...`);
let startedProxies = 0;
let skippedProxies = 0;
for (const app of remotes) {
const appConfig = staticRemotesConfig[app];
// Check if the port is already in use (another MF dev server may have already started a proxy)
const portInUse = await (0, utils_1.isPortInUse)(appConfig.port, host);
if (portInUse) {
console.log(`NX Skipping proxy for ${app} on port ${appConfig.port} - port already in use (likely served by another process)`);
skippedProxies++;
continue;
}
const expressProxy = express();
expressProxy.use(createProxyMiddleware({
target: mappedLocationsOfRemotes[app],
changeOrigin: true,
secure: sslCert ? false : undefined,
pathRewrite: isServer
? (path) => {
if (path.includes('/server')) {
return path;
}
else {
return `browser/${path}`;
}
}
: undefined,
}));
const proxyServer = (sslCert ? https : http)
.createServer({ cert: sslCert, key: sslKey }, expressProxy)
.listen(appConfig.port);
process.on('SIGTERM', () => proxyServer.close());
process.on('exit', () => proxyServer.close());
startedProxies++;
}
if (skippedProxies > 0) {
console.info(`NX Static remotes proxies: started ${startedProxies}, skipped ${skippedProxies} (already running)`);
}
else {
console.info(`NX Static remotes proxies started successfully`);
}
}

View File

@@ -0,0 +1,3 @@
import { StaticRemoteConfig } from '../../utils';
export declare function startStaticRemotesFileServer(staticRemotesConfig: Record<string, StaticRemoteConfig>, root: string, staticRemotesPort: number): void;
//# sourceMappingURL=start-static-remotes-file-server.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"start-static-remotes-file-server.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/plugins/utils/start-static-remotes-file-server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIjD,wBAAgB,4BAA4B,CAC1C,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACvD,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,QAoD1B"}

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startStaticRemotesFileServer = startStaticRemotesFileServer;
const path_1 = require("path");
const fs_1 = require("fs");
const node_child_process_1 = require("node:child_process");
const devkit_1 = require("@nx/devkit");
const devkit_internals_1 = require("nx/src/devkit-internals");
function startStaticRemotesFileServer(staticRemotesConfig, root, staticRemotesPort) {
const remotes = Object.keys(staticRemotesConfig);
if (!remotes || remotes.length === 0) {
return;
}
let shouldMoveToCommonLocation = false;
const commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
for (const app of remotes) {
const remoteConfig = staticRemotesConfig[app];
if (remoteConfig) {
(0, fs_1.cpSync)(remoteConfig.outputPath, (0, path_1.join)(commonOutputDirectory, remoteConfig.urlSegment), {
force: true,
recursive: true,
});
}
}
const { path: pathToHttpServerPkgJson, packageJson } = (0, devkit_internals_1.readModulePackageJson)('http-server', module.paths);
const pathToHttpServerBin = packageJson.bin['http-server'];
const pathToHttpServer = (0, path_1.resolve)(pathToHttpServerPkgJson.replace('package.json', ''), pathToHttpServerBin);
const httpServerProcess = (0, node_child_process_1.fork)(pathToHttpServer, [
commonOutputDirectory,
`-p=${staticRemotesPort}`,
`-a=localhost`,
`--cors`,
], {
stdio: 'pipe',
cwd: root,
env: {
FORCE_COLOR: 'true',
...process.env,
},
});
process.on('SIGTERM', () => httpServerProcess.kill('SIGTERM'));
process.on('exit', () => httpServerProcess.kill('SIGTERM'));
}

View File

@@ -0,0 +1,7 @@
import type { ProjectGraph } from '@nx/devkit';
import type { WorkspaceLibrary } from './models';
export declare function getDependentPackagesForProject(projectGraph: ProjectGraph, name: string): {
workspaceLibraries: WorkspaceLibrary[];
npmPackages: string[];
};
//# sourceMappingURL=dependencies.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD,wBAAgB,8BAA8B,CAC5C,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,MAAM,GACX;IACD,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;IACvC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAUA"}

View File

@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDependentPackagesForProject = getDependentPackagesForProject;
const devkit_1 = require("@nx/devkit");
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
const typescript_1 = require("./typescript");
function getDependentPackagesForProject(projectGraph, name) {
const { npmPackages, workspaceLibraries } = collectDependencies(projectGraph, name);
return {
workspaceLibraries: [...workspaceLibraries.values()],
npmPackages: [...npmPackages],
};
}
function collectDependencies(projectGraph, name, dependencies = {
workspaceLibraries: new Map(),
npmPackages: new Set(),
}, seen = new Set()) {
if (seen.has(name)) {
return dependencies;
}
seen.add(name);
(projectGraph.dependencies[name] ?? []).forEach((dependency) => {
if (dependency.target.startsWith('npm:')) {
dependencies.npmPackages.add(dependency.target.replace('npm:', ''));
}
else if (!dependency.target.includes(':')) {
// Only process as workspace library if it's not an external node.
// External nodes have prefixes like 'npm:', 'cargo:', etc.
if (projectGraph.nodes[dependency.target]) {
dependencies.workspaceLibraries.set(dependency.target, {
name: dependency.target,
root: projectGraph.nodes[dependency.target].data.root,
importKey: getLibraryImportPath(dependency.target, projectGraph),
});
collectDependencies(projectGraph, dependency.target, dependencies, seen);
}
}
// Skip other external node types (cargo:, etc.)
});
return dependencies;
}
function getLibraryImportPath(library, projectGraph) {
let buildLibsFromSource = true;
if (process.env.NX_BUILD_LIBS_FROM_SOURCE) {
buildLibsFromSource = process.env.NX_BUILD_LIBS_FROM_SOURCE === 'true';
}
const libraryNode = projectGraph.nodes[library];
let sourceRoots = [(0, ts_solution_setup_1.getProjectSourceRoot)(libraryNode.data)];
if (!buildLibsFromSource && process.env.NX_BUILD_TARGET) {
const buildTarget = (0, devkit_1.parseTargetString)(process.env.NX_BUILD_TARGET, projectGraph);
sourceRoots = (0, devkit_1.getOutputsForTargetAndConfiguration)(buildTarget, {}, libraryNode);
}
const tsConfigPathMappings = (0, typescript_1.readTsPathMappings)();
for (const [key, value] of Object.entries(tsConfigPathMappings)) {
for (const src of sourceRoots) {
if (value.find((path) => path.startsWith(src))) {
return key;
}
}
}
// Return library name if not found in TS path mappings
// This supports TS Solution + PM Workspaces where libs use package.json instead
return library;
}

View File

@@ -0,0 +1,3 @@
import type { ProjectGraph } from '@nx/devkit';
export declare function isReactProject(projectName: string, projectGraph: ProjectGraph): boolean;
//# sourceMappingURL=framework-detection.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"framework-detection.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/framework-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,YAAY,GACzB,OAAO,CAsBT"}

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isReactProject = isReactProject;
const dependencies_1 = require("./dependencies");
function isReactProject(projectName, projectGraph) {
const project = projectGraph.nodes[projectName];
if (!project)
return false;
// Check if the project has React dependencies
const { npmPackages } = (0, dependencies_1.getDependentPackagesForProject)(projectGraph, projectName);
// Check for React-related packages
const reactPackages = [
'react',
'react-dom',
'@types/react',
'@types/react-dom',
];
const hasReactDependencies = reactPackages.some((pkg) => npmPackages.includes(pkg));
return hasReactDependencies;
}

View File

@@ -0,0 +1,18 @@
import { type ProjectConfiguration, type ProjectGraph } from '@nx/devkit';
import { ModuleFederationConfig } from './models';
interface ModuleFederationExecutorContext {
projectName: string;
projectGraph: ProjectGraph;
root: string;
}
export declare function getBuildTargetNameFromMFDevServer(projectConfig: ProjectConfiguration, projectGraph: ProjectGraph): string;
export declare function getRemotes(devRemotes: string[], skipRemotes: string[], config: ModuleFederationConfig, context: ModuleFederationExecutorContext, pathToManifestFile?: string): {
staticRemotes: string[];
devRemotes: any[];
dynamicRemotes: any[];
remotePorts: number[];
staticRemotePort: number;
};
export declare function getModuleFederationConfig(tsconfigPath: string | undefined, workspaceRoot: string, projectRoot: string, pluginName?: 'react' | 'angular'): any;
export {};
//# sourceMappingURL=get-remotes-for-host.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"get-remotes-for-host.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/get-remotes-for-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EAElB,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,UAAU,+BAA+B;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAsCD,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,oBAAoB,EACnC,YAAY,EAAE,YAAY,UA0B3B;AAoCD,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAAE,EACpB,WAAW,EAAE,MAAM,EAAE,EACrB,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,+BAA+B,EACxC,kBAAkB,CAAC,EAAE,MAAM;;;;;;EA0F5B;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,UAAU,GAAE,OAAO,GAAG,SAAmB,OAkD1C"}

View File

@@ -0,0 +1,155 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBuildTargetNameFromMFDevServer = getBuildTargetNameFromMFDevServer;
exports.getRemotes = getRemotes;
exports.getModuleFederationConfig = getModuleFederationConfig;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const internal_1 = require("@nx/js/src/internal");
const find_matching_projects_1 = require("nx/src/utils/find-matching-projects");
const pc = tslib_1.__importStar(require("picocolors"));
const path_1 = require("path");
const fs_1 = require("fs");
function extractRemoteProjectsFromConfig(config, pathToManifestFile) {
const remotes = [];
const dynamicRemotes = [];
if (pathToManifestFile && (0, fs_1.existsSync)(pathToManifestFile)) {
const moduleFederationManifestJson = (0, fs_1.readFileSync)(pathToManifestFile, 'utf-8');
if (moduleFederationManifestJson) {
/**
*
* This should have shape of
* {
* "remoteName": "remoteLocation",
* }
* But users might have their own, enforce only that the key is the remote name
*/
const parsedManifest = JSON.parse(moduleFederationManifestJson);
// Get keys once instead of calling Object.keys twice
const manifestKeys = Object.keys(parsedManifest);
if (manifestKeys.every((key) => typeof key === 'string')) {
dynamicRemotes.push(...manifestKeys);
}
}
}
const staticRemotes = config.remotes?.map((r) => (Array.isArray(r) ? r[0] : r)) ?? [];
remotes.push(...staticRemotes);
return { remotes, dynamicRemotes };
}
// Find the target that uses the module-federation-dev-server executor
function getBuildTargetNameFromMFDevServer(projectConfig, projectGraph) {
if (projectConfig.targets) {
for (const [targetKey, targetConfig] of Object.entries(projectConfig.targets)) {
const executor = targetConfig.executor || '';
// Extract the portion after the `:` in the executor name
const executorParts = executor.split(':');
const executorName = executorParts.length > 1 ? executorParts[1] : executor;
if (executorName === 'module-federation-dev-server') {
// Extract the buildTarget from the options
if (targetConfig.options?.buildTarget) {
const parsedTarget = (0, devkit_1.parseTargetString)(targetConfig.options.buildTarget, projectGraph);
return parsedTarget.target;
}
}
}
}
return 'build';
}
function collectRemoteProjects(remote, collected, context) {
const remoteProject = context.projectGraph.nodes[remote]?.data;
if (!context.projectGraph.nodes[remote] || collected.has(remote)) {
return;
}
collected.add(remote);
const remoteProjectRoot = remoteProject.root;
const buildTargetName = getBuildTargetNameFromMFDevServer(remoteProject, context.projectGraph);
let remoteProjectTsConfig = remoteProject.targets?.[buildTargetName]?.options?.tsConfig;
const remoteProjectConfig = getModuleFederationConfig(remoteProjectTsConfig, context.root, remoteProjectRoot);
const { remotes: remoteProjectRemotes } = extractRemoteProjectsFromConfig(remoteProjectConfig);
remoteProjectRemotes.forEach((r) => collectRemoteProjects(r, collected, context));
}
function getRemotes(devRemotes, skipRemotes, config, context, pathToManifestFile) {
const collectedRemotes = new Set();
const { remotes, dynamicRemotes } = extractRemoteProjectsFromConfig(config, pathToManifestFile);
remotes.forEach((r) => collectRemoteProjects(r, collectedRemotes, context));
const remotesToSkip = new Set((0, find_matching_projects_1.findMatchingProjects)(skipRemotes, context.projectGraph.nodes) ?? []);
if (remotesToSkip.size > 0) {
devkit_1.logger.info(`Remotes not served automatically: ${[...remotesToSkip.values()].join(', ')}`);
}
const knownRemotes = Array.from(collectedRemotes).filter((r) => !remotesToSkip.has(r));
// With dynamic remotes, the manifest file may contain the names with `_` due to MF limitations on naming
// The project graph might contain these names with `-` rather than `_`. Check for both.
// This can occur after migration of existing remotes past Nx 19.8
const normalizedDynamicRemotes = dynamicRemotes.map((r) => {
// Compute replacement once instead of twice
const normalizedName = r.replace(/_/g, '-');
return context.projectGraph.nodes[normalizedName] ? normalizedName : r;
});
const knownDynamicRemotes = normalizedDynamicRemotes.filter((r) => !remotesToSkip.has(r) && context.projectGraph.nodes[r]);
devkit_1.logger.info(`NX Starting module federation dev-server for ${pc.bold(context.projectName)} with ${[...knownRemotes, ...knownDynamicRemotes].length} remotes`);
// Normalize devRemotes to array and call findMatchingProjects once
const devServeApps = new Set(!devRemotes
? []
: (0, find_matching_projects_1.findMatchingProjects)(Array.isArray(devRemotes) ? devRemotes : [devRemotes], context.projectGraph.nodes));
const staticRemotes = knownRemotes.filter((r) => !devServeApps.has(r));
const devServeRemotes = [...knownRemotes, ...knownDynamicRemotes].filter((r) => devServeApps.has(r));
const staticDynamicRemotes = knownDynamicRemotes.filter((r) => !devServeApps.has(r));
// Helper to get port from remote project
const getRemotePort = (r) => context.projectGraph.nodes[r].data.targets['serve'].options.port;
// Collect ports for dev-served remotes (used in return value)
const remotePorts = [...devServeRemotes, ...staticDynamicRemotes].map(getRemotePort);
// Calculate max port in a single pass instead of creating intermediate arrays
let maxPort = -Infinity;
for (const port of remotePorts) {
if (port > maxPort)
maxPort = port;
}
for (const r of staticRemotes) {
const port = getRemotePort(r);
if (port > maxPort)
maxPort = port;
}
const staticRemotePort = staticRemotes.length === 0 && remotePorts.length === 0
? undefined
: maxPort + (remotesToSkip.size + 1);
return {
staticRemotes,
devRemotes: devServeRemotes,
dynamicRemotes: staticDynamicRemotes,
remotePorts,
staticRemotePort,
};
}
function getModuleFederationConfig(tsconfigPath, workspaceRoot, projectRoot, pluginName = 'react') {
const moduleFederationConfigPathJS = (0, path_1.join)(workspaceRoot, projectRoot, 'module-federation.config.js');
const moduleFederationConfigPathTS = (0, path_1.join)(workspaceRoot, projectRoot, 'module-federation.config.ts');
let moduleFederationConfigPath = moduleFederationConfigPathJS;
tsconfigPath =
tsconfigPath ??
[
(0, path_1.join)(projectRoot, 'tsconfig.app.json'),
(0, path_1.join)(projectRoot, 'tsconfig.json'),
(0, path_1.join)(workspaceRoot, 'tsconfig.json'),
(0, path_1.join)(workspaceRoot, 'tsconfig.base.json'),
].find((p) => (0, fs_1.existsSync)(p));
if (!tsconfigPath) {
throw new Error(`Could not find a tsconfig for remote project located at ${projectRoot}. Please add a tsconfig.app.json or tsconfig.json to the project.`);
}
// create a no-op so this can be called with issue
const fullTSconfigPath = tsconfigPath.startsWith(workspaceRoot)
? tsconfigPath
: (0, path_1.join)(workspaceRoot, tsconfigPath);
let cleanupTranspiler = () => { };
if ((0, fs_1.existsSync)(moduleFederationConfigPathTS)) {
cleanupTranspiler = (0, internal_1.registerTsProject)(fullTSconfigPath);
moduleFederationConfigPath = moduleFederationConfigPathTS;
}
try {
const config = require(moduleFederationConfigPath);
cleanupTranspiler();
return config.default || config;
}
catch {
throw new Error(`Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/${pluginName}:host"?\nSee: https://nx.dev/concepts/more-concepts/faster-builds-with-module-federation`);
}
}

View File

@@ -0,0 +1,12 @@
export * from './share';
export * from './dependencies';
export * from './package-json';
export * from './remotes';
export * from './models';
export * from './normalize-project-name';
export * from './get-remotes-for-host';
export * from './parse-static-remotes-config';
export * from './port-utils';
export * from './start-remote-proxies';
export * from './start-ssr-remote-proxies';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC"}

14
node_modules/@nx/module-federation/src/utils/index.js generated vendored Normal file
View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./share"), exports);
tslib_1.__exportStar(require("./dependencies"), exports);
tslib_1.__exportStar(require("./package-json"), exports);
tslib_1.__exportStar(require("./remotes"), exports);
tslib_1.__exportStar(require("./models"), exports);
tslib_1.__exportStar(require("./normalize-project-name"), exports);
tslib_1.__exportStar(require("./get-remotes-for-host"), exports);
tslib_1.__exportStar(require("./parse-static-remotes-config"), exports);
tslib_1.__exportStar(require("./port-utils"), exports);
tslib_1.__exportStar(require("./start-remote-proxies"), exports);
tslib_1.__exportStar(require("./start-ssr-remote-proxies"), exports);

View File

@@ -0,0 +1,48 @@
import type { moduleFederationPlugin } from '@module-federation/sdk';
import { NormalModuleReplacementPlugin as RspackNormalModuleReplacementPlugin } from '@rspack/core';
export type ModuleFederationLibrary = {
type: string;
name: string;
};
export type WorkspaceLibrary = {
name: string;
root: string;
importKey: string | undefined;
};
export type SharedWorkspaceLibraryConfig = {
getAliases: () => Record<string, string>;
getLibraries: (projectRoot: string, eager?: boolean) => Record<string, SharedLibraryConfig>;
getReplacementPlugin: () => InstanceType<typeof RspackNormalModuleReplacementPlugin> | import('webpack').NormalModuleReplacementPlugin;
};
export type Remotes = Array<string | [remoteName: string, remoteUrl: string]>;
export interface SharedLibraryConfig {
singleton?: boolean;
strictVersion?: boolean;
requiredVersion?: false | string;
eager?: boolean;
}
export type SharedFunction = (libraryName: string, sharedConfig: SharedLibraryConfig) => undefined | false | SharedLibraryConfig;
export type AdditionalSharedConfig = Array<string | [libraryName: string, sharedConfig: SharedLibraryConfig] | {
libraryName: string;
sharedConfig: SharedLibraryConfig;
}>;
export interface ModuleFederationConfig {
name: string;
remotes?: Remotes;
library?: ModuleFederationLibrary;
exposes?: Record<string, string>;
shared?: SharedFunction;
additionalShared?: AdditionalSharedConfig;
/**
* `nxRuntimeLibraryControlPlugin` is a runtime module federation plugin to ensure
* that shared libraries are resolved from a remote with live reload capabilities.
* If you run into any issues with loading shared libraries, try disabling this option.
*/
disableNxRuntimeLibraryControlPlugin?: boolean;
}
export type NxModuleFederationConfigOverride = Omit<moduleFederationPlugin.ModuleFederationPluginOptions, 'exposes' | 'remotes' | 'name' | 'shared' | 'filename'>;
export type WorkspaceLibrarySecondaryEntryPoint = {
name: string;
path: string;
};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/module-federation/src/utils/models/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,6BAA6B,IAAI,mCAAmC,EAAE,MAAM,cAAc,CAAC;AAEpG,MAAM,MAAM,uBAAuB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,YAAY,EAAE,CACZ,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,OAAO,KACZ,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACzC,oBAAoB,EAAE,MAClB,YAAY,CAAC,OAAO,mCAAmC,CAAC,GACxD,OAAO,SAAS,EAAE,6BAA6B,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,mBAAmB,KAC9B,SAAS,GAAG,KAAK,GAAG,mBAAmB,CAAC;AAE7C,MAAM,MAAM,sBAAsB,GAAG,KAAK,CACtC,MAAM,GACN,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,mBAAmB,CAAC,GACxD;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,mBAAmB,CAAA;CAAE,CAC7D,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C;;;;OAIG;IACH,oCAAoC,CAAC,EAAE,OAAO,CAAC;CAChD;AAED,MAAM,MAAM,gCAAgC,GAAG,IAAI,CACjD,sBAAsB,CAAC,6BAA6B,EACpD,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CACvD,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,58 @@
import { ProjectGraph } from '@nx/devkit';
import { ModuleFederationConfig, SharedLibraryConfig, shareWorkspaceLibraries } from './index';
/**
* Configuration options for module federation config generation.
*/
export interface ModuleFederationConfigOptions {
/** Whether this is for server-side rendering */
isServer?: boolean;
/** Custom function to determine remote URLs */
determineRemoteUrl?: (remote: string) => string;
}
/**
* Framework-specific configuration for module federation.
*/
export interface FrameworkConfig {
/** Bundler type affects shared library config */
bundler: 'webpack' | 'rspack';
/** Remote entry file extension */
remoteEntryExt: 'js' | 'mjs';
/** Whether to pass true as 4th param to mapRemotes */
mapRemotesExpose?: boolean;
/** Function to apply eager packages for this framework */
applyEagerPackages?: (sharedConfig: Record<string, SharedLibraryConfig>, projectGraph: ProjectGraph, projectName: string) => void;
/** Default npm packages to always share */
defaultPackagesToShare?: string[];
/** npm packages to exclude from sharing */
packagesToAvoid?: string[];
}
/**
* Result of getModuleFederationConfig
*/
export interface ModuleFederationConfigResult {
sharedLibraries: ReturnType<typeof shareWorkspaceLibraries>;
sharedDependencies: Record<string, SharedLibraryConfig>;
mappedRemotes: Record<string, string>;
}
/**
* Creates a default remote URL resolver function.
* This is extracted to avoid code duplication across bundler utils.
*/
declare function createDefaultRemoteUrlResolver(isServer?: boolean, remoteEntryExt?: 'js' | 'mjs'): (remote: string) => string;
/**
* Async version - tries cached graph first, falls back to creating new one.
* Used by webpack and angular async configs.
*/
export declare function getModuleFederationConfigAsync(mfConfig: ModuleFederationConfig, options: ModuleFederationConfigOptions, frameworkConfig: FrameworkConfig): Promise<ModuleFederationConfigResult>;
/**
* Sync version - only uses cached graph.
* Used by rspack and angular sync configs.
*/
export declare function getModuleFederationConfigSync(mfConfig: ModuleFederationConfig, options: ModuleFederationConfigOptions, frameworkConfig: FrameworkConfig): ModuleFederationConfigResult;
/**
* Clears the static remotes env cache.
* Useful for testing or when the env variable changes.
*/
export declare function clearStaticRemotesEnvCache(): void;
export { createDefaultRemoteUrlResolver };
//# sourceMappingURL=module-federation-config.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"module-federation-config.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/module-federation-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EAEb,MAAM,YAAY,CAAC;AACpB,OAAO,EAML,sBAAsB,EACtB,mBAAmB,EAEnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,OAAO,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC9B,kCAAkC;IAClC,cAAc,EAAE,IAAI,GAAG,KAAK,CAAC;IAC7B,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,CACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACjD,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,2CAA2C;IAC3C,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,eAAe,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IAC5D,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACxD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAmID;;;GAGG;AACH,iBAAS,8BAA8B,CACrC,QAAQ,GAAE,OAAe,EACzB,cAAc,GAAE,IAAI,GAAG,KAAY,GAClC,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAwC5B;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAClD,QAAQ,EAAE,sBAAsB,EAChC,OAAO,EAAE,6BAAkC,EAC3C,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,4BAA4B,CAAC,CAcvC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,sBAAsB,EAChC,OAAO,EAAE,6BAAkC,EAC3C,eAAe,EAAE,eAAe,GAC/B,4BAA4B,CAQ9B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD;AAGD,OAAO,EAAE,8BAA8B,EAAE,CAAC"}

View File

@@ -0,0 +1,143 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getModuleFederationConfigAsync = getModuleFederationConfigAsync;
exports.getModuleFederationConfigSync = getModuleFederationConfigSync;
exports.clearStaticRemotesEnvCache = clearStaticRemotesEnvCache;
exports.createDefaultRemoteUrlResolver = createDefaultRemoteUrlResolver;
const devkit_1 = require("@nx/devkit");
const index_1 = require("./index");
/**
* Core implementation for generating module federation configuration.
* This is used by webpack, rspack, and angular utils.
*
* @param mfConfig - Module federation configuration
* @param options - Configuration options
* @param frameworkConfig - Framework-specific configuration
* @param projectGraph - The Nx project graph
*/
function buildModuleFederationConfig(mfConfig, options, frameworkConfig, projectGraph) {
const { bundler, remoteEntryExt, mapRemotesExpose, applyEagerPackages, defaultPackagesToShare = [], packagesToAvoid = [], } = frameworkConfig;
const project = projectGraph.nodes[mfConfig.name]?.data;
if (!project) {
throw Error(`Cannot find project "${mfConfig.name}". Check that the name is correct in module-federation.config.js`);
}
const dependencies = (0, index_1.getDependentPackagesForProject)(projectGraph, mfConfig.name);
// Filter dependencies if shared function provided
if (mfConfig.shared) {
dependencies.workspaceLibraries = dependencies.workspaceLibraries.filter((lib) => mfConfig.shared(lib.importKey, {}) !== false);
dependencies.npmPackages = dependencies.npmPackages.filter((pkg) => mfConfig.shared(pkg, {}) !== false);
}
const sharedLibraries = (0, index_1.shareWorkspaceLibraries)(dependencies.workspaceLibraries, undefined, bundler);
// Build npm packages list with framework-specific defaults
let npmPackagesList = dependencies.npmPackages;
if (defaultPackagesToShare.length > 0 || packagesToAvoid.length > 0) {
npmPackagesList = Array.from(new Set([
...defaultPackagesToShare,
...dependencies.npmPackages.filter((pkg) => !packagesToAvoid.includes(pkg)),
]));
}
const npmPackages = (0, index_1.sharePackages)(npmPackagesList);
// Remove packages to avoid from final config
for (const pkgName of packagesToAvoid) {
if (pkgName in npmPackages) {
delete npmPackages[pkgName];
}
}
const sharedDependencies = {
...sharedLibraries.getLibraries(project.root),
...npmPackages,
};
// Apply framework-specific eager packages
if (applyEagerPackages) {
applyEagerPackages(sharedDependencies, projectGraph, mfConfig.name);
}
(0, index_1.applySharedFunction)(sharedDependencies, mfConfig.shared);
(0, index_1.applyAdditionalShared)(sharedDependencies, mfConfig.additionalShared, projectGraph);
// Map remotes
const mapRemotesFunction = options.isServer ? index_1.mapRemotesForSSR : index_1.mapRemotes;
let mappedRemotes = {};
if (mfConfig.remotes && mfConfig.remotes.length > 0) {
const determineRemoteUrlFn = options.determineRemoteUrl ||
createDefaultRemoteUrlResolver(options.isServer, remoteEntryExt);
mappedRemotes = mapRemotesFunction(mfConfig.remotes, remoteEntryExt, determineRemoteUrlFn, mapRemotesExpose);
}
return { sharedLibraries, sharedDependencies, mappedRemotes };
}
// Cache for parsed static remotes env variable
let cachedStaticRemotesEnv = undefined;
let cachedStaticRemotesMap = undefined;
/**
* Gets static remotes from env with caching.
* Invalidates cache if env variable changes.
*/
function getStaticRemotesFromEnv() {
const currentEnv = process.env.NX_MF_DEV_SERVER_STATIC_REMOTES;
if (currentEnv !== cachedStaticRemotesEnv) {
cachedStaticRemotesEnv = currentEnv;
cachedStaticRemotesMap = currentEnv ? JSON.parse(currentEnv) : undefined;
}
return cachedStaticRemotesMap;
}
/**
* Creates a default remote URL resolver function.
* This is extracted to avoid code duplication across bundler utils.
*/
function createDefaultRemoteUrlResolver(isServer = false, remoteEntryExt = 'js') {
const { readCachedProjectConfiguration, } = require('nx/src/project-graph/project-graph');
const target = 'serve';
const remoteEntry = isServer
? 'server/remoteEntry.js'
: `remoteEntry.${remoteEntryExt}`;
return function (remote) {
const mappedStaticRemotesFromEnv = getStaticRemotesFromEnv();
if (mappedStaticRemotesFromEnv && mappedStaticRemotesFromEnv[remote]) {
return `${mappedStaticRemotesFromEnv[remote]}/${remoteEntry}`;
}
let remoteConfiguration = null;
try {
remoteConfiguration = readCachedProjectConfiguration(remote);
}
catch (e) {
throw new Error(`Cannot find remote "${remote}". Check that the remote name is correct in your module federation config file.\n`);
}
const serveTarget = remoteConfiguration?.targets?.[target];
if (!serveTarget) {
throw new Error(`Cannot automatically determine URL of remote (${remote}). Looked for property "host" in the project's "serve" target.\n` +
`You can also use the tuple syntax in your config to configure your remotes. e.g. \`remotes: [['remote1', 'http://localhost:4201']]\``);
}
const host = serveTarget.options?.host ??
`http${serveTarget.options.ssl ? 's' : ''}://localhost`;
const port = serveTarget.options?.port ?? 4201;
return `${host.endsWith('/') ? host.slice(0, -1) : host}:${port}/${remoteEntry}`;
};
}
/**
* Async version - tries cached graph first, falls back to creating new one.
* Used by webpack and angular async configs.
*/
async function getModuleFederationConfigAsync(mfConfig, options = {}, frameworkConfig) {
let projectGraph;
try {
projectGraph = (0, devkit_1.readCachedProjectGraph)();
}
catch (e) {
projectGraph = await (0, devkit_1.createProjectGraphAsync)();
}
return buildModuleFederationConfig(mfConfig, options, frameworkConfig, projectGraph);
}
/**
* Sync version - only uses cached graph.
* Used by rspack and angular sync configs.
*/
function getModuleFederationConfigSync(mfConfig, options = {}, frameworkConfig) {
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
return buildModuleFederationConfig(mfConfig, options, frameworkConfig, projectGraph);
}
/**
* Clears the static remotes env cache.
* Useful for testing or when the env variable changes.
*/
function clearStaticRemotesEnvCache() {
cachedStaticRemotesEnv = undefined;
cachedStaticRemotesMap = undefined;
}

View File

@@ -0,0 +1,2 @@
export declare function normalizeProjectName(name: string): string;
//# sourceMappingURL=normalize-project-name.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"normalize-project-name.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/normalize-project-name.ts"],"names":[],"mappings":"AACA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,UAKhD"}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeProjectName = normalizeProjectName;
// normalize to allow only JavaScript var valid names
function normalizeProjectName(name) {
// Replace invalid starting characters with '_'
const normalized = name.replace(/^[^a-zA-Z_$]/, '_');
// Replace invalid subsequent characters with '_'
return normalized.replace(/[^a-zA-Z0-9_$]/g, '_');
}

View File

@@ -0,0 +1,3 @@
import type { PackageJson } from 'nx/src/utils/package-json';
export declare function readRootPackageJson(): PackageJson;
//# sourceMappingURL=package-json.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"package-json.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/package-json.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,wBAAgB,mBAAmB,IAAI,WAAW,CASjD"}

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.readRootPackageJson = readRootPackageJson;
const devkit_1 = require("@nx/devkit");
const fs_1 = require("fs");
function readRootPackageJson() {
const pkgJsonPath = (0, devkit_1.joinPathFragments)(devkit_1.workspaceRoot, 'package.json');
if (!(0, fs_1.existsSync)(pkgJsonPath)) {
throw new Error('NX MF: Could not find root package.json to determine dependency versions.');
}
return (0, devkit_1.readJsonFile)(pkgJsonPath);
}

View File

@@ -0,0 +1,14 @@
import { ExecutorContext } from '@nx/devkit';
export type StaticRemoteConfig = {
basePath: string;
outputPath: string;
urlSegment: string;
port: number;
};
export type StaticRemotesConfig = {
remotes: string[];
config: Record<string, StaticRemoteConfig> | undefined;
};
export declare function parseStaticRemotesConfig(staticRemotes: string[] | undefined, context: ExecutorContext): StaticRemotesConfig;
export declare function parseStaticSsrRemotesConfig(staticRemotes: string[] | undefined, context: ExecutorContext): StaticRemotesConfig;
//# sourceMappingURL=parse-static-remotes-config.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parse-static-remotes-config.d.ts","sourceRoot":"","sources":["../../../../../packages/module-federation/src/utils/parse-static-remotes-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAC;AAIhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AACF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,SAAS,CAAC;CACxD,CAAC;AAEF,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EAAE,GAAG,SAAS,EACnC,OAAO,EAAE,eAAe,GACvB,mBAAmB,CAgCrB;AAED,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EAAE,GAAG,SAAS,EACnC,OAAO,EAAE,eAAe,GACvB,mBAAmB,CAgCrB"}

Some files were not shown because too many files have changed in this diff Show More