diff --git a/packages/angular-cli/blueprints/ng2/files/angular-cli.json b/packages/angular-cli/blueprints/ng2/files/angular-cli.json index 4fd88b98c1cf..bee97bda2438 100644 --- a/packages/angular-cli/blueprints/ng2/files/angular-cli.json +++ b/packages/angular-cli/blueprints/ng2/files/angular-cli.json @@ -54,6 +54,11 @@ "module": false, "pipe": true, "service": true + }, + "serve": { + "port": 4200, + "liveReloadPort": 49152, + "host": "localhost" } } } diff --git a/packages/angular-cli/commands/serve.ts b/packages/angular-cli/commands/serve.ts index a9ce848d13ae..f68d3e6527d5 100644 --- a/packages/angular-cli/commands/serve.ts +++ b/packages/angular-cli/commands/serve.ts @@ -1,9 +1,14 @@ const PortFinder = require('portfinder'); const Command = require('../ember-cli/lib/models/command'); +import { CliConfig } from '../models/config'; -PortFinder.basePort = 49152; +const config = CliConfig.fromProject(); -const defaultPort = process.env.PORT || 4200; +const defaultLiveReloadPort = config.get('defaults.serve.liveReloadPort') || 49152; +const defaultPort = process.env.PORT || config.get('defaults.serve.port'); +const defaultHost = config.get('defaults.serve.host') || 'localhost'; + +PortFinder.basePort = defaultLiveReloadPort; export interface ServeTaskOptions { port?: number; @@ -42,9 +47,9 @@ const ServeCommand = Command.extend({ { name: 'host', type: String, - default: 'localhost', + default: defaultHost, aliases: ['H'], - description: 'Listens only on localhost by default' + description: `Listens only on ${defaultHost} by default` }, { name: 'proxy-config', type: 'Path', aliases: ['pc'] }, { name: 'watcher', type: String, default: 'events', aliases: ['w'] }, @@ -65,7 +70,7 @@ const ServeCommand = Command.extend({ name: 'live-reload-port', type: Number, aliases: ['lrp'], - description: '(Defaults to port number within [49152...65535])' + description: `Finds the first open port number within [${defaultLiveReloadPort}...65535]` }, { name: 'live-reload-live-css', @@ -103,7 +108,7 @@ const ServeCommand = Command.extend({ }, { name: 'i18n-file', type: String, default: null }, { name: 'i18n-format', type: String, default: null }, - { name: 'locale', type: String, default: null } + { name: 'locale', type: String, default: null } ], run: function(commandOptions: ServeTaskOptions) { diff --git a/packages/angular-cli/lib/config/schema.d.ts b/packages/angular-cli/lib/config/schema.d.ts index d323223b5f36..abe1e5ecdc1b 100644 --- a/packages/angular-cli/lib/config/schema.d.ts +++ b/packages/angular-cli/lib/config/schema.d.ts @@ -1,79 +1,84 @@ export interface CliConfig { + /** + * The global configuration of the project. + */ + project?: { + version?: string; + name?: string; + }; + /** + * Properties of the different applications in this project. + */ + apps?: { + root?: string; + outDir?: string; + assets?: string; + deployUrl?: string; + index?: string; + main?: string; + test?: string; + tsconfig?: string; + prefix?: string; + mobile?: boolean; /** - * The global configuration of the project. + * Global styles to be included in the build. */ - project?: { - version?: string; - name?: string; - }; - /** - * Properties of the different applications in this project. - */ - apps?: { - root?: string; - outDir?: string; - assets?: string; - deployUrl?: string; - index?: string; - main?: string; - test?: string; - tsconfig?: string; - prefix?: string; - mobile?: boolean; - /** - * Global styles to be included in the build. - */ - styles?: string[]; - /** - * Global scripts to be included in the build. - */ - scripts?: string[]; - /** - * Name and corresponding file for environment config. - */ - environments?: { - [name: string]: any; - }; - }[]; + styles?: string[]; /** - * Configuration reserved for installed third party addons. + * Global scripts to be included in the build. */ - addons?: { - [name: string]: any; - }[]; + scripts?: string[]; /** - * Configuration reserved for installed third party packages. + * Name and corresponding file for environment config. */ - packages?: { - [name: string]: any; - }[]; - e2e?: { - protractor?: { - config?: string; - }; + environments?: { + [name: string]: any; + }; + }[]; + /** + * Configuration reserved for installed third party addons. + */ + addons?: { + [name: string]: any; + }[]; + /** + * Configuration reserved for installed third party packages. + */ + packages?: { + [name: string]: any; + }[]; + e2e?: { + protractor?: { + config?: string; + }; + }; + test?: { + karma?: { + config?: string; }; - test?: { - karma?: { - config?: string; - }; + }; + defaults?: { + styleExt?: string; + prefixInterfaces?: boolean; + poll?: number; + viewEncapsulation?: string; + changeDetection?: string; + inline?: { + style?: boolean; + template?: boolean; }; - defaults?: { - styleExt?: string; - prefixInterfaces?: boolean; - poll?: number; - viewEncapsulation?: string; - changeDetection?: string; - inline?: { - style?: boolean; - template?: boolean; - }; - spec?: { - class?: boolean; - component?: boolean; - directive?: boolean; - module?: boolean; - pipe?: boolean; - service?: boolean; - }; + spec?: { + class?: boolean; + component?: boolean; + directive?: boolean; + module?: boolean; + pipe?: boolean; + service?: boolean; }; + serve?: { + port: number; + liveReloadPort: number; + host: string; + } + }; } diff --git a/packages/angular-cli/lib/config/schema.json b/packages/angular-cli/lib/config/schema.json index 3a2a1f02fcc9..5b8183a54da4 100644 --- a/packages/angular-cli/lib/config/schema.json +++ b/packages/angular-cli/lib/config/schema.json @@ -227,6 +227,23 @@ "default": true } } + }, + "serve": { + "type": "object", + "properties": { + "port": { + "type": "number", + "default": 4200 + }, + "liveReloadPort": { + "type": "number", + "default": 49152 + }, + "host": { + "type": "string", + "default": "localhost" + } + } } }, "additionalProperties": false diff --git a/tests/e2e/tests/misc/default-port.ts b/tests/e2e/tests/misc/default-port.ts new file mode 100644 index 000000000000..5f92d1d67cb8 --- /dev/null +++ b/tests/e2e/tests/misc/default-port.ts @@ -0,0 +1,20 @@ +import { request } from '../../utils/http'; +import { killAllProcesses } from '../../utils/process'; +import { ngServe } from '../../utils/project'; +import { updateJsonFile } from '../../utils/project'; + +export default function() { + return Promise.resolve() + .then(() => updateJsonFile('angular-cli.json', configJson => { + const app = configJson['defaults']['serve']; + app['port'] = 4201; + })) + .then(() => ngServe()) + .then(() => request('http://localhost:4201/')) + .then(body => { + if (!body.match(/Loading...<\/app-root>/)) { + throw new Error('Response does not match expected value.'); + } + }) + .then(() => killAllProcesses(), (err) => { killAllProcesses(); throw err; }); +}