Skip to content

Commit fbcf453

Browse files
Charles Lydingfilipesilva
Charles Lyding
authored andcommitted
fix(serve): implement relevant live-reload options
1 parent db80d6c commit fbcf453

File tree

3 files changed

+60
-94
lines changed

3 files changed

+60
-94
lines changed

docs/documentation/serve.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,7 @@
1616

1717
`--live-reload` (`-lr`) flag to turn off live reloading
1818

19-
`--live-reload-host` (`-lrh`) specify the host for live reloading
20-
21-
`--live-reload-base-url` (`-lrbu`) specify the base URL for live reloading
22-
23-
`--live-reload-port` (`-lrp`) port for live reloading
24-
25-
`--live-reload-live-css` flag to live reload CSS
19+
`--live-reload-client` specify the URL that the live reload browser client will use
2620

2721
`--ssl` flag to turn on SSL
2822

packages/@angular/cli/commands/serve.ts

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,19 @@ import { ServeTaskOptions } from './serve';
88
const SilentError = require('silent-error');
99
const PortFinder = require('portfinder');
1010
const Command = require('../ember-cli/lib/models/command');
11-
const getPort = <any>denodeify(PortFinder.getPort);
12-
13-
PortFinder.basePort = 49152;
11+
const getPort = denodeify<{host: string, port: number}, number>(PortFinder.getPort);
1412

1513
const config = CliConfig.fromProject() || CliConfig.fromGlobal();
1614
const defaultPort = process.env.PORT || config.get('defaults.serve.port');
1715
const defaultHost = config.get('defaults.serve.host');
16+
PortFinder.basePort = defaultPort;
1817

1918
export interface ServeTaskOptions extends BuildOptions {
2019
port?: number;
2120
host?: string;
2221
proxyConfig?: string;
2322
liveReload?: boolean;
24-
liveReloadHost?: string;
25-
liveReloadPort?: number;
26-
liveReloadBaseUrl?: string;
27-
liveReloadLiveCss?: boolean;
23+
liveReloadClient?: string;
2824
ssl?: boolean;
2925
sslKey?: string;
3026
sslCert?: string;
@@ -63,28 +59,9 @@ const ServeCommand = Command.extend({
6359
availableOptions: baseServeCommandOptions.concat([
6460
{ name: 'live-reload', type: Boolean, default: true, aliases: ['lr'] },
6561
{
66-
name: 'live-reload-host',
62+
name: 'live-reload-client',
6763
type: String,
68-
aliases: ['lrh'],
69-
description: 'Defaults to host'
70-
},
71-
{
72-
name: 'live-reload-base-url',
73-
type: String,
74-
aliases: ['lrbu'],
75-
description: 'Defaults to baseURL'
76-
},
77-
{
78-
name: 'live-reload-port',
79-
type: Number,
80-
aliases: ['lrp'],
81-
description: '(Defaults to port number within [49152...65535])'
82-
},
83-
{
84-
name: 'live-reload-live-css',
85-
type: Boolean,
86-
default: true,
87-
description: 'Whether to live reload CSS (default true)'
64+
description: 'specify the URL that the live reload browser client will use'
8865
},
8966
{
9067
name: 'hmr',
@@ -104,10 +81,8 @@ const ServeCommand = Command.extend({
10481
commandOptions = Object.assign({}, additionalDefaults, commandOptions);
10582

10683
Version.assertAngularVersionIs2_3_1OrHigher(this.project.root);
107-
commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host;
10884

10985
return checkExpressPort(commandOptions)
110-
.then(() => autoFindLiveReloadPort(commandOptions))
11186
.then((opts: ServeTaskOptions) => {
11287
const serve = new ServeTask({
11388
ui: this.ui,
@@ -136,26 +111,4 @@ function checkExpressPort(commandOptions: ServeTaskOptions) {
136111
});
137112
}
138113

139-
function autoFindLiveReloadPort(commandOptions: ServeTaskOptions) {
140-
return getPort({ port: commandOptions.liveReloadPort, host: commandOptions.liveReloadHost })
141-
.then((foundPort: number) => {
142-
143-
// if live reload port matches express port, try one higher
144-
if (foundPort === commandOptions.port) {
145-
commandOptions.liveReloadPort = foundPort + 1;
146-
return autoFindLiveReloadPort(commandOptions);
147-
}
148-
149-
// port was already open
150-
if (foundPort === commandOptions.liveReloadPort) {
151-
return commandOptions;
152-
}
153-
154-
// use found port as live reload port
155-
commandOptions.liveReloadPort = foundPort;
156-
return commandOptions;
157-
158-
});
159-
}
160-
161114
export default ServeCommand;

packages/@angular/cli/tasks/serve.ts

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,52 @@ export default Task.extend({
4141

4242
let webpackConfig = new NgCliWebpackConfig(serveTaskOptions).config;
4343

44-
// This allows for live reload of page when changes are made to repo.
45-
// https://webpack.github.io/docs/webpack-dev-server.html#inline-mode
46-
let entryPoints = [
47-
`webpack-dev-server/client?http://${serveTaskOptions.host}:${serveTaskOptions.port}/`
48-
];
49-
if (serveTaskOptions.hmr) {
50-
const webpackHmrLink = 'https://webpack.github.io/docs/hot-module-replacement.html';
51-
ui.writeLine(oneLine`
52-
${chalk.yellow('NOTICE')} Hot Module Replacement (HMR) is enabled for the dev server.
53-
`);
54-
ui.writeLine(' The project will still live reload when HMR is enabled,');
55-
ui.writeLine(' but to take advantage of HMR additional application code is required');
56-
ui.writeLine(' (not included in an Angular CLI project by default).');
57-
ui.writeLine(` See ${chalk.blue(webpackHmrLink)}`);
58-
ui.writeLine(' for information on working with HMR for Webpack.');
59-
entryPoints.push('webpack/hot/dev-server');
60-
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
61-
webpackConfig.plugins.push(new webpack.NamedModulesPlugin());
62-
if (serveTaskOptions.extractCss) {
44+
const serverAddress = url.format({
45+
protocol: serveTaskOptions.ssl ? 'https' : 'http',
46+
hostname: serveTaskOptions.host,
47+
port: serveTaskOptions.port.toString()
48+
});
49+
let clientAddress = serverAddress;
50+
if (serveTaskOptions.liveReloadClient) {
51+
const clientUrl = url.parse(serveTaskOptions.liveReloadClient);
52+
// very basic sanity check
53+
if (!clientUrl.host) {
54+
return Promise.reject(new SilentError(`'live-reload-client' must be a full URL.`));
55+
}
56+
clientAddress = clientUrl.href;
57+
}
58+
59+
if (serveTaskOptions.liveReload) {
60+
// This allows for live reload of page when changes are made to repo.
61+
// https://webpack.github.io/docs/webpack-dev-server.html#inline-mode
62+
let entryPoints = [
63+
`webpack-dev-server/client?${clientAddress}`
64+
];
65+
if (serveTaskOptions.hmr) {
66+
const webpackHmrLink = 'https://webpack.github.io/docs/hot-module-replacement.html';
6367
ui.writeLine(oneLine`
64-
${chalk.yellow('NOTICE')} (HMR) does not allow for CSS hot reload when used
65-
together with '--extract-css'.
68+
${chalk.yellow('NOTICE')} Hot Module Replacement (HMR) is enabled for the dev server.
6669
`);
70+
ui.writeLine(' The project will still live reload when HMR is enabled,');
71+
ui.writeLine(' but to take advantage of HMR additional application code is required');
72+
ui.writeLine(' (not included in an Angular CLI project by default).');
73+
ui.writeLine(` See ${chalk.blue(webpackHmrLink)}`);
74+
ui.writeLine(' for information on working with HMR for Webpack.');
75+
entryPoints.push('webpack/hot/dev-server');
76+
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
77+
webpackConfig.plugins.push(new webpack.NamedModulesPlugin());
78+
if (serveTaskOptions.extractCss) {
79+
ui.writeLine(oneLine`
80+
${chalk.yellow('NOTICE')} (HMR) does not allow for CSS hot reload when used
81+
together with '--extract-css'.
82+
`);
83+
}
6784
}
85+
if (!webpackConfig.entry.main) { webpackConfig.entry.main = []; }
86+
webpackConfig.entry.main.unshift(...entryPoints);
87+
} else if (serveTaskOptions.hmr) {
88+
ui.writeLine(chalk.yellow('Live reload is disabled. HMR option ignored.'));
6889
}
69-
if (!webpackConfig.entry.main) { webpackConfig.entry.main = []; }
70-
webpackConfig.entry.main.unshift(...entryPoints);
7190

7291
if (!serveTaskOptions.watch) {
7392
// There's no option to turn off file watching in webpack-dev-server, but
@@ -151,26 +170,26 @@ export default Task.extend({
151170

152171
ui.writeLine(chalk.green(oneLine`
153172
**
154-
NG Live Development Server is running on
155-
http${serveTaskOptions.ssl ? 's' : ''}://${serveTaskOptions.host}:${serveTaskOptions.port}.
173+
NG Live Development Server is running on ${serverAddress}
156174
**
157175
`));
158176

159177
const server = new WebpackDevServer(webpackCompiler, webpackDevServerConfiguration);
160178
return new Promise((resolve, reject) => {
161-
server.listen(serveTaskOptions.port, `${serveTaskOptions.host}`, (err: any, stats: any) => {
179+
server.listen(serveTaskOptions.port, serveTaskOptions.host, (err: any, stats: any) => {
162180
if (err) {
163-
console.error(err.stack || err);
164-
if (err.details) { console.error(err.details); }
165-
reject(err.details);
166-
} else {
167-
const { open, ssl, host, port } = serveTaskOptions;
168-
if (open) {
169-
let protocol = ssl ? 'https' : 'http';
170-
opn(url.format({ protocol: protocol, hostname: host, port: port.toString() }));
171-
}
181+
return reject(err);
182+
}
183+
if (serveTaskOptions.open) {
184+
opn(serverAddress);
172185
}
173186
});
187+
})
188+
.catch((err: Error) => {
189+
if (err) {
190+
this.ui.writeError('\nAn error occured during the build:\n' + ((err && err.stack) || err));
191+
}
192+
throw err;
174193
});
175194
}
176195
});

0 commit comments

Comments
 (0)