Skip to content

Commit 06f5624

Browse files
hanslmgechev
authored andcommitted
feat(@angular-devkit/build-webpack): add API builder for dev server
It outputs the port and address that it is bound to.
1 parent 318a0a3 commit 06f5624

File tree

5 files changed

+111
-15
lines changed

5 files changed

+111
-15
lines changed

packages/_/devkit/package/schema.d.ts

-13
This file was deleted.

packages/angular_devkit/build_webpack/builders.json

+7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
"schema": "./src/webpack/schema.json",
88
"description": "Build a webpack app."
99
},
10+
"dev-server": {
11+
"implementation": "./src/webpack-dev-server/index2",
12+
"class": "./src/webpack-dev-server",
13+
"schema": "./src/webpack-dev-server/schema.json",
14+
"description": "Serve a webpack app."
15+
},
1016
"webpack-dev-server": {
17+
"implementation": "./src/webpack-dev-server/index2",
1118
"class": "./src/webpack-dev-server",
1219
"schema": "./src/webpack-dev-server/schema.json",
1320
"description": "Serve a webpack app."

packages/angular_devkit/build_webpack/src/webpack-dev-server/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { concatMap } from 'rxjs/operators';
1919
import * as webpack from 'webpack';
2020
import * as WebpackDevServer from 'webpack-dev-server';
2121
import { LoggingCallback, defaultLoggingCb } from '../webpack';
22-
import { WebpackDevServerBuilderSchema } from './schema';
22+
import { Schema as WebpackDevServerBuilderSchema } from './schema';
2323

2424
export interface DevServerResult {
2525
port: number;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect/src/index2';
9+
import { getSystemPath, json, normalize, resolve } from '@angular-devkit/core';
10+
import * as net from 'net';
11+
import { Observable, from, of } from 'rxjs';
12+
import { switchMap } from 'rxjs/operators';
13+
import * as webpack from 'webpack';
14+
import * as WebpackDevServer from 'webpack-dev-server';
15+
import { ArchitectPlugin } from '../plugins/architect';
16+
import { WebpackFactory, WebpackLoggingCallback } from '../webpack/index2';
17+
import { Schema as WebpackDevServerBuilderSchema } from './schema';
18+
19+
const webpackMerge = require('webpack-merge');
20+
21+
22+
export type DevServerBuildResult = BuilderOutput & {
23+
port: number;
24+
family: string;
25+
address: string;
26+
};
27+
28+
export function runWebpackDevServer(
29+
config: webpack.Configuration,
30+
context: BuilderContext,
31+
options: {
32+
devServerConfig?: WebpackDevServer.Configuration,
33+
logging?: WebpackLoggingCallback,
34+
webpackFactory?: WebpackFactory,
35+
} = {},
36+
): Observable<BuilderOutput> {
37+
const createWebpack = options.webpackFactory || (config => of(webpack(config)));
38+
const log: WebpackLoggingCallback = options.logging
39+
|| ((stats, config) => context.logger.info(stats.toString(config.stats)));
40+
41+
config = webpackMerge(config, {
42+
plugins: [
43+
new ArchitectPlugin(context),
44+
],
45+
});
46+
47+
const devServerConfig = options.devServerConfig || config.devServer || {};
48+
if (devServerConfig.stats) {
49+
config.stats = devServerConfig.stats as webpack.Stats.ToStringOptionsObject;
50+
}
51+
// Disable stats reporting by the devserver, we have our own logger.
52+
devServerConfig.stats = false;
53+
54+
return createWebpack(config).pipe(
55+
switchMap(webpackCompiler => new Observable<BuilderOutput>(obs => {
56+
const server = new WebpackDevServer(webpackCompiler, devServerConfig);
57+
let result: DevServerBuildResult;
58+
59+
webpackCompiler.hooks.done.tap('build-webpack', (stats) => {
60+
// Log stats.
61+
log(stats, config);
62+
63+
obs.next({
64+
...result,
65+
success: !stats.hasErrors(),
66+
} as DevServerBuildResult);
67+
});
68+
69+
server.listen(
70+
devServerConfig.port === undefined ? 8080 : devServerConfig.port,
71+
devServerConfig.host === undefined ? 'localhost' : devServerConfig.host,
72+
function (this: net.Server, err) {
73+
if (err) {
74+
obs.error(err);
75+
} else {
76+
result = {
77+
success: true,
78+
port: this.address().port,
79+
family: this.address().family,
80+
address: this.address().address,
81+
};
82+
}
83+
},
84+
);
85+
86+
// Teardown logic. Close the server when unsubscribed from.
87+
return () => server.close();
88+
})),
89+
);
90+
}
91+
92+
93+
export default createBuilder<
94+
json.JsonObject & WebpackDevServerBuilderSchema, DevServerBuildResult
95+
>((options, context) => {
96+
const configPath = resolve(normalize(context.workspaceRoot), normalize(options.webpackConfig));
97+
98+
return from(import(getSystemPath(configPath))).pipe(
99+
switchMap((config: webpack.Configuration) => runWebpackDevServer(config, context)),
100+
);
101+
});

packages/angular_devkit/build_webpack/src/webpack-dev-server/schema.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "http://json-schema.org/schema",
23
"title": "Webpack Dev-Server Builder",
34
"description": "Webpack Dev-Server Builder schema for Architect.",
45
"type": "object",
@@ -12,4 +13,4 @@
1213
"required": [
1314
"webpackConfig"
1415
]
15-
}
16+
}

0 commit comments

Comments
 (0)