feat(angular): add executor to allow custom webpack config with serve (#6359)

Add a builder to allow the user to pass a custom webpack config with serve. It should fetch the
custom webpack config from the build target.
This commit is contained in:
Colum Ferry 2021-07-15 11:09:59 +01:00 committed by GitHub
parent 776bd277b7
commit ec414e5840
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 969 additions and 0 deletions

View File

@ -0,0 +1,211 @@
# webpack-server
Serves a browser application with support for a custom webpack configuration.
Options can be configured in `angular.json` when defining the executor, or when invoking it.
## Options
### browserTarget (_**required**_)
Type: `string`
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`.
### allowedHosts
Type: `array`
List of hosts that are allowed to access the dev server.
### ~~aot~~
Type: `boolean`
**Deprecated:** Use the "aot" option in the browser builder instead.
Build using Ahead of Time compilation.
### ~~baseHref~~
Type: `string`
**Deprecated:** Use the "baseHref" option in the browser builder instead.
Base url for the application being built.
### ~~commonChunk~~
Type: `boolean`
**Deprecated:** Use the "commonChunk" option in the browser builder instead.
Generate a seperate bundle containing code used across multiple bundles.
### ~~deployUrl~~
Type: `string`
**Deprecated:** Use the "deployUrl" option in the browser builder instead.
URL where files will be deployed.
### disableHostCheck
Default: `false`
Type: `boolean`
Don't verify connected clients are part of allowed hosts.
### hmr
Default: `false`
Type: `boolean`
Enable hot module replacement.
### ~~hmrWarning~~
Default: `true`
Type: `boolean`
**Deprecated:** No longer has an effect.
Show a warning when the --hmr option is enabled.
### host
Default: `localhost`
Type: `string`
Host to listen on.
### liveReload
Default: `true`
Type: `boolean`
Whether to reload the page on change, using live-reload.
### open
Alias(es): o
Default: `false`
Type: `boolean`
Opens the url in default browser.
### ~~optimization~~
Type: `boolean`
**Deprecated:** Use the "optimization" option in the browser builder instead.
Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, tree-shaking and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.
### poll
Type: `number`
Enable and define the file watching poll time period in milliseconds.
### port
Default: `4200`
Type: `number`
Port to listen on.
### ~~progress~~
Type: `boolean`
**Deprecated:** Use the "progress" option in the browser builder instead.
Log progress to the console while building.
### proxyConfig
Type: `string`
Proxy configuration file. For more information, see https://angular.io/guide/build#proxying-to-a-backend-server.
### publicHost
Type: `string`
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.
### servePath
Type: `string`
The pathname where the app will be served.
### ~~servePathDefaultWarning~~
Default: `true`
Type: `boolean`
**Deprecated:** No longer has an effect.
Show a warning when deploy-url/base-href use unsupported serve path values.
### ~~sourceMap~~
Type: `boolean`
**Deprecated:** Use the "sourceMap" option in the browser builder instead.
Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.
### ssl
Default: `false`
Type: `boolean`
Serve using HTTPS.
### sslCert
Type: `string`
SSL certificate to use for serving HTTPS.
### sslKey
Type: `string`
SSL key to use for serving HTTPS.
### ~~vendorChunk~~
Type: `boolean`
**Deprecated:** Use the "vendorChunk" option in the browser builder instead.
Generate a seperate bundle containing only vendor libraries. This option should only used for development.
### verbose
Type: `boolean`
Adds more details to output logging.
### watch
Default: `true`
Type: `boolean`
Rebuild on change.

View File

@ -481,6 +481,11 @@
"name": "webpack-browser executor",
"id": "webpack-browser",
"file": "angular/api-angular/executors/webpack-browser"
},
{
"name": "webpack-server executor",
"id": "webpack-server",
"file": "angular/api-angular/executors/webpack-server"
}
]
},
@ -1642,6 +1647,11 @@
"name": "webpack-browser executor",
"id": "webpack-browser",
"file": "react/api-angular/executors/webpack-browser"
},
{
"name": "webpack-server executor",
"id": "webpack-server",
"file": "react/api-angular/executors/webpack-server"
}
]
},
@ -2767,6 +2777,11 @@
"name": "webpack-browser executor",
"id": "webpack-browser",
"file": "node/api-angular/executors/webpack-browser"
},
{
"name": "webpack-server executor",
"id": "webpack-server",
"file": "node/api-angular/executors/webpack-server"
}
]
},

View File

@ -0,0 +1,212 @@
# webpack-server
Serves a browser application with support for a custom webpack configuration.
Options can be configured in `workspace.json` when defining the executor, or when invoking it.
Read more about how to use executors and the CLI here: https://nx.dev/node/getting-started/nx-cli#running-tasks.
## Options
### browserTarget (_**required**_)
Type: `string`
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`.
### allowedHosts
Type: `array`
List of hosts that are allowed to access the dev server.
### ~~aot~~
Type: `boolean`
**Deprecated:** Use the "aot" option in the browser builder instead.
Build using Ahead of Time compilation.
### ~~baseHref~~
Type: `string`
**Deprecated:** Use the "baseHref" option in the browser builder instead.
Base url for the application being built.
### ~~commonChunk~~
Type: `boolean`
**Deprecated:** Use the "commonChunk" option in the browser builder instead.
Generate a seperate bundle containing code used across multiple bundles.
### ~~deployUrl~~
Type: `string`
**Deprecated:** Use the "deployUrl" option in the browser builder instead.
URL where files will be deployed.
### disableHostCheck
Default: `false`
Type: `boolean`
Don't verify connected clients are part of allowed hosts.
### hmr
Default: `false`
Type: `boolean`
Enable hot module replacement.
### ~~hmrWarning~~
Default: `true`
Type: `boolean`
**Deprecated:** No longer has an effect.
Show a warning when the --hmr option is enabled.
### host
Default: `localhost`
Type: `string`
Host to listen on.
### liveReload
Default: `true`
Type: `boolean`
Whether to reload the page on change, using live-reload.
### open
Alias(es): o
Default: `false`
Type: `boolean`
Opens the url in default browser.
### ~~optimization~~
Type: `boolean`
**Deprecated:** Use the "optimization" option in the browser builder instead.
Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, tree-shaking and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.
### poll
Type: `number`
Enable and define the file watching poll time period in milliseconds.
### port
Default: `4200`
Type: `number`
Port to listen on.
### ~~progress~~
Type: `boolean`
**Deprecated:** Use the "progress" option in the browser builder instead.
Log progress to the console while building.
### proxyConfig
Type: `string`
Proxy configuration file. For more information, see https://angular.io/guide/build#proxying-to-a-backend-server.
### publicHost
Type: `string`
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.
### servePath
Type: `string`
The pathname where the app will be served.
### ~~servePathDefaultWarning~~
Default: `true`
Type: `boolean`
**Deprecated:** No longer has an effect.
Show a warning when deploy-url/base-href use unsupported serve path values.
### ~~sourceMap~~
Type: `boolean`
**Deprecated:** Use the "sourceMap" option in the browser builder instead.
Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.
### ssl
Default: `false`
Type: `boolean`
Serve using HTTPS.
### sslCert
Type: `string`
SSL certificate to use for serving HTTPS.
### sslKey
Type: `string`
SSL key to use for serving HTTPS.
### ~~vendorChunk~~
Type: `boolean`
**Deprecated:** Use the "vendorChunk" option in the browser builder instead.
Generate a seperate bundle containing only vendor libraries. This option should only used for development.
### verbose
Type: `boolean`
Adds more details to output logging.
### watch
Default: `true`
Type: `boolean`
Rebuild on change.

View File

@ -0,0 +1,212 @@
# webpack-server
Serves a browser application with support for a custom webpack configuration.
Options can be configured in `workspace.json` when defining the executor, or when invoking it.
Read more about how to use executors and the CLI here: https://nx.dev/react/getting-started/nx-cli#running-tasks.
## Options
### browserTarget (_**required**_)
Type: `string`
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`.
### allowedHosts
Type: `array`
List of hosts that are allowed to access the dev server.
### ~~aot~~
Type: `boolean`
**Deprecated:** Use the "aot" option in the browser builder instead.
Build using Ahead of Time compilation.
### ~~baseHref~~
Type: `string`
**Deprecated:** Use the "baseHref" option in the browser builder instead.
Base url for the application being built.
### ~~commonChunk~~
Type: `boolean`
**Deprecated:** Use the "commonChunk" option in the browser builder instead.
Generate a seperate bundle containing code used across multiple bundles.
### ~~deployUrl~~
Type: `string`
**Deprecated:** Use the "deployUrl" option in the browser builder instead.
URL where files will be deployed.
### disableHostCheck
Default: `false`
Type: `boolean`
Don't verify connected clients are part of allowed hosts.
### hmr
Default: `false`
Type: `boolean`
Enable hot module replacement.
### ~~hmrWarning~~
Default: `true`
Type: `boolean`
**Deprecated:** No longer has an effect.
Show a warning when the --hmr option is enabled.
### host
Default: `localhost`
Type: `string`
Host to listen on.
### liveReload
Default: `true`
Type: `boolean`
Whether to reload the page on change, using live-reload.
### open
Alias(es): o
Default: `false`
Type: `boolean`
Opens the url in default browser.
### ~~optimization~~
Type: `boolean`
**Deprecated:** Use the "optimization" option in the browser builder instead.
Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, tree-shaking and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.
### poll
Type: `number`
Enable and define the file watching poll time period in milliseconds.
### port
Default: `4200`
Type: `number`
Port to listen on.
### ~~progress~~
Type: `boolean`
**Deprecated:** Use the "progress" option in the browser builder instead.
Log progress to the console while building.
### proxyConfig
Type: `string`
Proxy configuration file. For more information, see https://angular.io/guide/build#proxying-to-a-backend-server.
### publicHost
Type: `string`
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.
### servePath
Type: `string`
The pathname where the app will be served.
### ~~servePathDefaultWarning~~
Default: `true`
Type: `boolean`
**Deprecated:** No longer has an effect.
Show a warning when deploy-url/base-href use unsupported serve path values.
### ~~sourceMap~~
Type: `boolean`
**Deprecated:** Use the "sourceMap" option in the browser builder instead.
Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.
### ssl
Default: `false`
Type: `boolean`
Serve using HTTPS.
### sslCert
Type: `string`
SSL certificate to use for serving HTTPS.
### sslKey
Type: `string`
SSL key to use for serving HTTPS.
### ~~vendorChunk~~
Type: `boolean`
**Deprecated:** Use the "vendorChunk" option in the browser builder instead.
Generate a seperate bundle containing only vendor libraries. This option should only used for development.
### verbose
Type: `boolean`
Adds more details to output logging.
### watch
Default: `true`
Type: `boolean`
Rebuild on change.

View File

@ -19,6 +19,11 @@
"implementation": "./src/builders/webpack-browser/webpack-browser.impl",
"schema": "./src/builders/webpack-browser/schema.json",
"description": "Builds a browser application with support for incremental builds and custom webpack configuration."
},
"webpack-server": {
"implementation": "./src/builders/webpack-server/webpack-server.impl",
"schema": "./src/builders/webpack-server/schema.json",
"description": "Serves a browser application with support for a custom webpack configuration."
}
},
"builders": {
@ -41,6 +46,11 @@
"implementation": "./src/builders/webpack-browser/webpack-browser.impl",
"schema": "./src/builders/webpack-browser/schema.json",
"description": "Builds a browser application with support for incremental builds and custom webpack configuration."
},
"webpack-server": {
"implementation": "./src/builders/webpack-server/webpack-server.impl",
"schema": "./src/builders/webpack-server/schema.json",
"description": "Serves a browser application with support for a custom webpack configuration."
}
}
}

View File

@ -0,0 +1 @@
export * from './normalize-options';

View File

@ -0,0 +1,12 @@
import type { Schema } from '../schema';
export function normalizeOptions(schema: Schema): Schema {
return {
host: 'localhost',
port: 4200,
liveReload: true,
open: false,
ssl: false,
...schema,
};
}

View File

@ -0,0 +1,32 @@
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;
hmrWarning?: boolean;
servePathDefaultWarning?: boolean;
optimization?: boolean | { scripts: boolean; styles: boolean };
aot?: boolean;
sourceMap?:
| boolean
| { scripts: boolean; styles: boolean; hidden: boolean; vendor: boolean };
vendorChunk?: boolean;
commonChunk?: boolean;
baseHref?: string;
deployUrl?: string;
progress?: boolean;
poll?: number;
}

View File

@ -0,0 +1,206 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Webpack Server Target",
"description": "Dev Server target options for Build Facade.",
"type": "object",
"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
},
"hmrWarning": {
"type": "boolean",
"description": "Show a warning when the --hmr option is enabled.",
"default": true,
"x-deprecated": "No longer has an effect."
},
"servePathDefaultWarning": {
"type": "boolean",
"description": "Show a warning when deploy-url/base-href use unsupported serve path values.",
"default": true,
"x-deprecated": "No longer has an effect."
},
"optimization": {
"description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, tree-shaking and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.",
"x-user-analytics": 16,
"oneOf": [
{
"type": "object",
"properties": {
"scripts": {
"type": "boolean",
"description": "Enables optimization of the scripts output.",
"default": true
},
"styles": {
"type": "boolean",
"description": "Enables optimization of the styles output.",
"default": true
}
},
"additionalProperties": false
},
{
"type": "boolean"
}
],
"x-deprecated": "Use the \"optimization\" option in the browser builder instead."
},
"aot": {
"type": "boolean",
"description": "Build using Ahead of Time compilation.",
"x-user-analytics": 13,
"x-deprecated": "Use the \"aot\" option in the browser builder instead."
},
"sourceMap": {
"description": "Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.",
"oneOf": [
{
"type": "object",
"properties": {
"scripts": {
"type": "boolean",
"description": "Output source maps for all scripts.",
"default": true
},
"styles": {
"type": "boolean",
"description": "Output source maps for all styles.",
"default": true
},
"hidden": {
"type": "boolean",
"description": "Output source maps used for error reporting tools.",
"default": false
},
"vendor": {
"type": "boolean",
"description": "Resolve vendor packages source maps.",
"default": false
}
},
"additionalProperties": false
},
{
"type": "boolean"
}
],
"x-deprecated": "Use the \"sourceMap\" option in the browser builder instead."
},
"vendorChunk": {
"type": "boolean",
"description": "Generate a seperate bundle containing only vendor libraries. This option should only used for development.",
"x-deprecated": "Use the \"vendorChunk\" option in the browser builder instead."
},
"commonChunk": {
"type": "boolean",
"description": "Generate a seperate bundle containing code used across multiple bundles.",
"x-deprecated": "Use the \"commonChunk\" option in the browser builder instead."
},
"baseHref": {
"type": "string",
"description": "Base url for the application being built.",
"x-deprecated": "Use the \"baseHref\" option in the browser builder instead."
},
"deployUrl": {
"type": "string",
"description": "URL where files will be deployed.",
"x-deprecated": "Use the \"deployUrl\" option in the browser builder instead."
},
"progress": {
"type": "boolean",
"description": "Log progress to the console while building.",
"x-deprecated": "Use the \"progress\" option in the browser builder instead."
},
"poll": {
"type": "number",
"description": "Enable and define the file watching poll time period in milliseconds."
}
},
"additionalProperties": false,
"required": ["browserTarget"]
}

View File

@ -0,0 +1,58 @@
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import type { Schema } from './schema';
import { parseTargetString, joinPathFragments } from '@nrwl/devkit';
import { Workspaces } from '@nrwl/tao/src/shared/workspace';
import {
DevServerBuilderOptions,
serveWebpackBrowser,
} from '@angular-devkit/build-angular/src/dev-server';
import { existsSync } from 'fs';
import { merge } from 'webpack-merge';
import { normalizeOptions } from './lib';
export function webpackServer(schema: Schema, context: BuilderContext) {
const options = normalizeOptions(schema);
const workspaceConfig = new Workspaces(
context.workspaceRoot
).readWorkspaceConfiguration();
const parsedBrowserTarget = parseTargetString(options.browserTarget);
const buildTarget =
workspaceConfig.projects[parsedBrowserTarget.project].targets[
parsedBrowserTarget.target
];
const selectedConfiguration = parsedBrowserTarget.configuration
? buildTarget.configurations[parsedBrowserTarget.configuration]
: buildTarget.configurations[buildTarget.defaultConfiguration];
const customWebpackConfig: { path: string } =
selectedConfiguration.customWebpackConfig ??
buildTarget.options.customWebpackConfig;
if (customWebpackConfig && customWebpackConfig.path) {
const pathToWebpackConfig = joinPathFragments(
context.workspaceRoot,
customWebpackConfig.path
);
if (existsSync(pathToWebpackConfig)) {
return serveWebpackBrowser(options as DevServerBuilderOptions, context, {
webpackConfiguration: (baseWebpackConfig) => {
const customWebpackConfiguration = require(pathToWebpackConfig);
return merge(baseWebpackConfig, customWebpackConfiguration);
},
});
} else {
throw new Error(
`Custom Webpack Config File Not Found!\nTo use a custom webpack config, please ensure the path to the custom webpack file is correct: \n${pathToWebpackConfig}`
);
}
}
return serveWebpackBrowser(options as DevServerBuilderOptions, context);
}
export default createBuilder<JsonObject & Schema>(webpackServer);