Skip to content

Commit

Permalink
feat(angular): add module-federation-dev-server builder
Browse files Browse the repository at this point in the history
  • Loading branch information
Coly010 committed Apr 14, 2022
1 parent ad4233f commit c4eae88
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 1 deletion.
115 changes: 115 additions & 0 deletions docs/generated/packages/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -2963,6 +2963,121 @@
"aliases": [],
"hidden": false,
"path": "/packages/angular/src/builders/webpack-server/schema.json"
},
{
"name": "module-federation-dev-server",
"implementation": "/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts",
"schema": {
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Schema for Module Federation Dev Server",
"description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host.",
"type": "object",
"presets": [
{
"name": "Using a Different Port",
"keys": ["browserTarget", "port"]
}
],
"properties": {
"browserTarget": {
"type": "string",
"description": "A browser builder target to serve in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.",
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
},
"port": {
"type": "number",
"description": "Port to listen on.",
"default": 4200
},
"host": {
"type": "string",
"description": "Host to listen on.",
"default": "localhost"
},
"proxyConfig": {
"type": "string",
"description": "Proxy configuration file. For more information, see https://angular.io/guide/build#proxying-to-a-backend-server."
},
"ssl": {
"type": "boolean",
"description": "Serve using HTTPS.",
"default": false
},
"sslKey": {
"type": "string",
"description": "SSL key to use for serving HTTPS."
},
"sslCert": {
"type": "string",
"description": "SSL certificate to use for serving HTTPS."
},
"headers": {
"type": "object",
"description": "Custom HTTP headers to be added to all responses.",
"propertyNames": { "pattern": "^[-_A-Za-z0-9]+$" },
"additionalProperties": { "type": "string" }
},
"open": {
"type": "boolean",
"description": "Opens the url in default browser.",
"default": false,
"alias": "o"
},
"verbose": {
"type": "boolean",
"description": "Adds more details to output logging."
},
"liveReload": {
"type": "boolean",
"description": "Whether to reload the page on change, using live-reload.",
"default": true
},
"publicHost": {
"type": "string",
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies."
},
"allowedHosts": {
"type": "array",
"description": "List of hosts that are allowed to access the dev server.",
"default": [],
"items": { "type": "string" }
},
"servePath": {
"type": "string",
"description": "The pathname where the app will be served."
},
"disableHostCheck": {
"type": "boolean",
"description": "Don't verify connected clients are part of allowed hosts.",
"default": false
},
"hmr": {
"type": "boolean",
"description": "Enable hot module replacement.",
"default": false
},
"watch": {
"type": "boolean",
"description": "Rebuild on change.",
"default": true
},
"poll": {
"type": "number",
"description": "Enable and define the file watching poll time period in milliseconds."
},
"apps": {
"type": "array",
"items": { "type": "string" },
"description": "List of remote applications to serve in addition to the host application."
}
},
"additionalProperties": false,
"required": ["browserTarget"]
},
"description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host.",
"aliases": [],
"hidden": false,
"path": "/packages/angular/src/builders/module-federation-dev-server/schema.json"
}
]
}
3 changes: 2 additions & 1 deletion docs/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"ng-packagr-lite",
"package",
"webpack-browser",
"webpack-server"
"webpack-server",
"module-federation-dev-server"
],
"generators": [
"add-linting",
Expand Down
10 changes: 10 additions & 0 deletions packages/angular/executors.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
"implementation": "./src/builders/webpack-server/webpack-server.impl",
"schema": "./src/builders/webpack-server/schema.json",
"description": "The `webpack-server` executor is very similar to the standard `dev-server` builder provided by the Angular Devkit. It is usually used in tandem with `@nrwl/angular:webpack-browser` when your Angular application uses a custom webpack configuration."
},
"module-federation-dev-server": {
"implementation": "./src/builders/module-federation-dev-server/module-federation-dev-server.impl",
"schema": "./src/builders/module-federation-dev-server/schema.json",
"description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host."
}
},
"builders": {
Expand Down Expand Up @@ -51,6 +56,11 @@
"implementation": "./src/builders/webpack-server/webpack-server.impl",
"schema": "./src/builders/webpack-server/schema.json",
"description": "The `webpack-server` executor is very similar to the standard `dev-server` builder provided by the Angular Devkit. It is usually used in tandem with `@nrwl/angular:webpack-browser` when your Angular application uses a custom webpack configuration."
},
"module-federation-dev-server": {
"implementation": "./src/builders/module-federation-dev-server/module-federation-dev-server.impl",
"schema": "./src/builders/module-federation-dev-server/schema.json",
"description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host."
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type { Schema } from './schema';
import { ExecutorContext, Workspaces } from '@nrwl/devkit';
import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter';
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { join } from 'path';
import { webpackServer } from '../webpack-server/webpack-server.impl';

export function moduleFederationDevServer(
schema: Schema,
context: BuilderContext
) {
const workspaces = new Workspaces(context.workspaceRoot);
const workspaceConfig = workspaces.readWorkspaceConfiguration();
const executorContext: ExecutorContext = {
root: context.workspaceRoot,
projectName: context.target.project,
targetName: context.target.target,
configurationName: context.target.configuration,
workspace: workspaceConfig,
cwd: process.cwd(),
isVerbose: false,
};
if (context.target && context.target.project && context.target.target) {
executorContext.target =
workspaceConfig.projects[context.target.project].targets[
context.target.target
];
}

const p = workspaceConfig.projects[context.target.project];

const mfeConfigPath = join(context.workspaceRoot, p.root, 'mfe.config.js');

let mfeConfig: { remotes: string[] };
try {
mfeConfig = require(mfeConfigPath);
} catch {
throw new Error(
`Could not load ${mfeConfigPath}. Was this project generated with "@nrwl/angular:host"?`
);
}

const { apps, ...options } = schema;
const unparsedRemotes =
apps.length > 0
? apps
: mfeConfig.remotes.length > 0
? mfeConfig.remotes
: [];
const remotes = unparsedRemotes.map((a) => (Array.isArray(a) ? a[0] : a));

for (const remote of remotes) {
scheduleTarget(
context.workspaceRoot,
{
project: remote,
target: 'serve',
configuration: context.target.configuration,
runOptions: {},
executor: context.builder.builderName,
},
options.verbose
);
}

return webpackServer(options, context);
}

export default createBuilder<JsonObject & Schema>(moduleFederationDevServer);
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface Schema {
browserTarget: string;
port: number;
host: string;
proxyConfig?: string;
ssl: boolean;
sslKey?: string;
sslCert?: string;
headers?: Record<string, string>;
open: boolean;
verbose?: boolean;
liveReload: boolean;
publicHost?: string;
allowedHosts?: string[];
servePath?: string;
disableHostCheck?: boolean;
hmr?: boolean;
watch?: boolean;
poll?: number;
apps?: string[];
}
115 changes: 115 additions & 0 deletions packages/angular/src/builders/module-federation-dev-server/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Schema for Module Federation Dev Server",
"description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host.",
"type": "object",
"presets": [
{
"name": "Using a Different Port",
"keys": ["browserTarget", "port"]
}
],
"properties": {
"browserTarget": {
"type": "string",
"description": "A browser builder target to serve in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.",
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
},
"port": {
"type": "number",
"description": "Port to listen on.",
"default": 4200
},
"host": {
"type": "string",
"description": "Host to listen on.",
"default": "localhost"
},
"proxyConfig": {
"type": "string",
"description": "Proxy configuration file. For more information, see https://angular.io/guide/build#proxying-to-a-backend-server."
},
"ssl": {
"type": "boolean",
"description": "Serve using HTTPS.",
"default": false
},
"sslKey": {
"type": "string",
"description": "SSL key to use for serving HTTPS."
},
"sslCert": {
"type": "string",
"description": "SSL certificate to use for serving HTTPS."
},
"headers": {
"type": "object",
"description": "Custom HTTP headers to be added to all responses.",
"propertyNames": {
"pattern": "^[-_A-Za-z0-9]+$"
},
"additionalProperties": {
"type": "string"
}
},
"open": {
"type": "boolean",
"description": "Opens the url in default browser.",
"default": false,
"alias": "o"
},
"verbose": {
"type": "boolean",
"description": "Adds more details to output logging."
},
"liveReload": {
"type": "boolean",
"description": "Whether to reload the page on change, using live-reload.",
"default": true
},
"publicHost": {
"type": "string",
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies."
},
"allowedHosts": {
"type": "array",
"description": "List of hosts that are allowed to access the dev server.",
"default": [],
"items": {
"type": "string"
}
},
"servePath": {
"type": "string",
"description": "The pathname where the app will be served."
},
"disableHostCheck": {
"type": "boolean",
"description": "Don't verify connected clients are part of allowed hosts.",
"default": false
},
"hmr": {
"type": "boolean",
"description": "Enable hot module replacement.",
"default": false
},
"watch": {
"type": "boolean",
"description": "Rebuild on change.",
"default": true
},
"poll": {
"type": "number",
"description": "Enable and define the file watching poll time period in milliseconds."
},
"apps": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of remote applications to serve in addition to the host application."
}
},
"additionalProperties": false,
"required": ["browserTarget"]
}

0 comments on commit c4eae88

Please sign in to comment.