diff --git a/packages/angular-cli/commands/build.ts b/packages/angular-cli/commands/build.ts index b1ab175f391b..97ba333527cf 100644 --- a/packages/angular-cli/commands/build.ts +++ b/packages/angular-cli/commands/build.ts @@ -13,6 +13,8 @@ export interface BuildOptions { aot?: boolean; sourcemap?: boolean; vendorChunk?: boolean; + verbose?: boolean; + progress?: boolean; } const BuildCommand = Command.extend({ @@ -35,7 +37,9 @@ const BuildCommand = Command.extend({ { name: 'base-href', type: String, default: null, aliases: ['bh'] }, { name: 'aot', type: Boolean, default: false }, { name: 'sourcemap', type: Boolean, default: true, aliases: ['sm'] }, - { name: 'vendor-chunk', type: Boolean, default: true } + { name: 'vendor-chunk', type: Boolean, default: true }, + { name: 'verbose', type: Boolean, default: false }, + { name: 'progress', type: Boolean, default: true } ], run: function (commandOptions: BuildOptions) { diff --git a/packages/angular-cli/commands/serve.ts b/packages/angular-cli/commands/serve.ts index 9beb8822920b..2105485af1a0 100644 --- a/packages/angular-cli/commands/serve.ts +++ b/packages/angular-cli/commands/serve.ts @@ -27,6 +27,8 @@ export interface ServeTaskOptions { sslCert?: string; aot?: boolean; sourcemap?: boolean; + verbose?: boolean; + progress?: boolean; open?: boolean; vendorChunk?: boolean; } @@ -85,6 +87,8 @@ const ServeCommand = Command.extend({ { name: 'aot', type: Boolean, default: false }, { name: 'sourcemap', type: Boolean, default: true, aliases: ['sm'] }, { name: 'vendor-chunk', type: Boolean, default: true }, + { name: 'verbose', type: Boolean, default: false }, + { name: 'progress', type: Boolean, default: true }, { name: 'open', type: Boolean, diff --git a/packages/angular-cli/commands/test.ts b/packages/angular-cli/commands/test.ts index cd4e23c87e21..3316c14e09d3 100644 --- a/packages/angular-cli/commands/test.ts +++ b/packages/angular-cli/commands/test.ts @@ -14,6 +14,7 @@ export interface TestOptions { reporters?: string; build?: boolean; sourcemap?: boolean; + progress?: boolean; } @@ -23,6 +24,7 @@ const NgCliTestCommand = TestCommand.extend({ { name: 'code-coverage', type: Boolean, default: false, aliases: ['cc'] }, { name: 'lint', type: Boolean, default: false, aliases: ['l'] }, { name: 'single-run', type: Boolean, default: false, aliases: ['sr'] }, + { name: 'progress', type: Boolean, default: true}, { name: 'browsers', type: String }, { name: 'colors', type: Boolean }, { name: 'log-level', type: String }, diff --git a/packages/angular-cli/models/webpack-build-common.ts b/packages/angular-cli/models/webpack-build-common.ts index 39bdd641e4f6..27b85cfad977 100644 --- a/packages/angular-cli/models/webpack-build-common.ts +++ b/packages/angular-cli/models/webpack-build-common.ts @@ -4,6 +4,7 @@ import {GlobCopyWebpackPlugin} from '../plugins/glob-copy-webpack-plugin'; import {packageChunkSort} from '../utilities/package-chunk-sort'; import {BaseHrefWebpackPlugin} from '@angular-cli/base-href-webpack'; +const ProgressPlugin = require('webpack/lib/ProgressPlugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const autoprefixer = require('autoprefixer'); @@ -14,7 +15,9 @@ export function getWebpackCommonConfig( appConfig: any, baseHref: string, sourcemap: boolean, - vendorChunk: boolean + vendorChunk: boolean, + verbose: boolean, + progress: boolean ) { const appRoot = path.resolve(projectRoot, appConfig.root); @@ -44,6 +47,13 @@ export function getWebpackCommonConfig( })); } + if (progress) { + extraPlugins.push(new ProgressPlugin({ + profile: verbose, + colors: true + })); + } + return { devtool: sourcemap ? 'source-map' : false, resolve: { diff --git a/packages/angular-cli/models/webpack-build-production.ts b/packages/angular-cli/models/webpack-build-production.ts index 79459858740b..7e0b73331d36 100644 --- a/packages/angular-cli/models/webpack-build-production.ts +++ b/packages/angular-cli/models/webpack-build-production.ts @@ -14,16 +14,18 @@ declare module 'webpack' { } } -export const getWebpackProdConfigPartial = function(projectRoot: string, appConfig: any) { +export const getWebpackProdConfigPartial = function(projectRoot: string, + appConfig: any, + verbose: any) { const appRoot = path.resolve(projectRoot, appConfig.root); const styles = appConfig.styles ? appConfig.styles.map((style: string) => path.resolve(appRoot, style)) : []; const cssLoaders = ['css-loader?sourcemap&minimize', 'postcss-loader']; + return { output: { path: path.resolve(projectRoot, appConfig.outDir), - publicPath: '/static/dist/', filename: '[name].[chunkhash].bundle.js', sourceMapFilename: '[name].[chunkhash].bundle.map', chunkFilename: '[id].[chunkhash].chunk.js' @@ -57,8 +59,8 @@ export const getWebpackProdConfigPartial = function(projectRoot: string, appConf 'process.env.NODE_ENV': JSON.stringify('production') }), new webpack.optimize.UglifyJsPlugin({ - mangle: { screw_ie8 : true, keep_fnames: true }, - compress: { screw_ie8: true }, + mangle: { screw_ie8 : true }, + compress: { screw_ie8: true, warnings: verbose }, sourceMap: true }), new CompressionPlugin({ diff --git a/packages/angular-cli/models/webpack-build-test.js b/packages/angular-cli/models/webpack-build-test.js index 3c4c390341b0..5c1541044e69 100644 --- a/packages/angular-cli/models/webpack-build-test.js +++ b/packages/angular-cli/models/webpack-build-test.js @@ -10,6 +10,7 @@ const webpackLoader = g['angularCliIsLocal'] ? g.angularCliPackages['@ngtools/webpack'].main : '@ngtools/webpack'; +const ProgressPlugin = require('webpack/lib/ProgressPlugin'); const getWebpackTestConfig = function (projectRoot, environment, appConfig, testConfig) { @@ -49,6 +50,10 @@ const getWebpackTestConfig = function (projectRoot, environment, appConfig, test })) } + if (testConfig.progress) { + extraPlugins.push(new ProgressPlugin({ colors: true })); + } + return { devtool: testConfig.sourcemap ? 'inline-source-map' : 'eval', context: path.resolve(__dirname, './'), diff --git a/packages/angular-cli/models/webpack-build-utils.ts b/packages/angular-cli/models/webpack-build-utils.ts index b1853ea5ae00..b2aa2148800e 100644 --- a/packages/angular-cli/models/webpack-build-utils.ts +++ b/packages/angular-cli/models/webpack-build-utils.ts @@ -4,20 +4,30 @@ export const ngAppResolve = (resolvePath: string): string => { return path.resolve(process.cwd(), resolvePath); }; -export const webpackOutputOptions = { +const webpackOutputOptions = { colors: true, + hash: true, + timings: true, chunks: true, + chunkModules: false, + children: false, // listing all children is very noisy in AOT and hides warnings/errors modules: false, reasons: false, - chunkModules: false + warnings: true, + assets: false, // listing all assets is very noisy when using assets directories + version: false }; -export const webpackDevServerOutputOptions = { +const verboseWebpackOutputOptions = { + children: true, assets: true, - colors: true, version: true, - hash: true, - timings: true, - chunks: false, - chunkModules: false + reasons: true, + chunkModules: false // TODO: set to true when console to file output is fixed }; + +export function getWebpackStatsConfig(verbose = false) { + return verbose + ? Object.assign(webpackOutputOptions, verboseWebpackOutputOptions) + : webpackOutputOptions; +} diff --git a/packages/angular-cli/models/webpack-config.ts b/packages/angular-cli/models/webpack-config.ts index 5f2f8a359a47..d605305bc96c 100644 --- a/packages/angular-cli/models/webpack-config.ts +++ b/packages/angular-cli/models/webpack-config.ts @@ -26,6 +26,8 @@ export class NgCliWebpackConfig { isAoT = false, sourcemap = true, vendorChunk = false, + verbose = false, + progress = true ) { const config: CliConfig = CliConfig.fromProject(); const appConfig = config.config.apps[0]; @@ -38,9 +40,11 @@ export class NgCliWebpackConfig { appConfig, baseHref, sourcemap, - vendorChunk + vendorChunk, + verbose, + progress ); - let targetConfigPartial = this.getTargetConfig(this.ngCliProject.root, appConfig); + let targetConfigPartial = this.getTargetConfig(this.ngCliProject.root, appConfig, verbose); const typescriptConfigPartial = isAoT ? getWebpackAotConfigPartial(this.ngCliProject.root, appConfig) : getWebpackNonAotConfigPartial(this.ngCliProject.root, appConfig); @@ -62,12 +66,12 @@ export class NgCliWebpackConfig { ); } - getTargetConfig(projectRoot: string, appConfig: any): any { + getTargetConfig(projectRoot: string, appConfig: any, verbose: boolean): any { switch (this.target) { case 'development': return getWebpackDevConfigPartial(projectRoot, appConfig); case 'production': - return getWebpackProdConfigPartial(projectRoot, appConfig); + return getWebpackProdConfigPartial(projectRoot, appConfig, verbose); default: throw new Error("Invalid build target. Only 'development' and 'production' are available."); } diff --git a/packages/angular-cli/plugins/karma.js b/packages/angular-cli/plugins/karma.js index 4f8ff7088ac9..1448b2bb4408 100644 --- a/packages/angular-cli/plugins/karma.js +++ b/packages/angular-cli/plugins/karma.js @@ -13,7 +13,8 @@ const init = (config) => { const testConfig = { codeCoverage: config.angularCli.codeCoverage || false, lint: config.angularCli.lint || false, - sourcemap: config.angularCli.sourcemap + sourcemap: config.angularCli.sourcemap, + progress: config.angularCli.progress } // add webpack config diff --git a/packages/angular-cli/tasks/build-webpack-watch.ts b/packages/angular-cli/tasks/build-webpack-watch.ts index 672da6965c1d..7e6958a90fbe 100644 --- a/packages/angular-cli/tasks/build-webpack-watch.ts +++ b/packages/angular-cli/tasks/build-webpack-watch.ts @@ -2,9 +2,8 @@ import * as rimraf from 'rimraf'; import * as path from 'path'; const Task = require('../ember-cli/lib/models/task'); import * as webpack from 'webpack'; -const ProgressPlugin = require('webpack/lib/ProgressPlugin'); import { NgCliWebpackConfig } from '../models/webpack-config'; -import { webpackOutputOptions } from '../models/'; +import { getWebpackStatsConfig } from '../models/'; import { BuildOptions } from '../commands/build'; import { CliConfig } from '../models/config'; @@ -26,13 +25,13 @@ export default Task.extend({ runTaskOptions.baseHref, runTaskOptions.aot, runTaskOptions.sourcemap, - runTaskOptions.vendorChunk + runTaskOptions.vendorChunk, + runTaskOptions.verbose, + runTaskOptions.progress ).config; const webpackCompiler: any = webpack(config); - webpackCompiler.apply(new ProgressPlugin({ - profile: true - })); + const statsConfig = getWebpackStatsConfig(runTaskOptions.verbose); return new Promise((resolve, reject) => { webpackCompiler.watch({}, (err: any, stats: any) => { @@ -45,7 +44,7 @@ export default Task.extend({ if (stats.hash !== lastHash) { lastHash = stats.hash; - process.stdout.write(stats.toString(webpackOutputOptions) + '\n'); + process.stdout.write(stats.toString(statsConfig) + '\n'); } }); }); diff --git a/packages/angular-cli/tasks/build-webpack.ts b/packages/angular-cli/tasks/build-webpack.ts index 9f519d4b57f5..770a9befe6e0 100644 --- a/packages/angular-cli/tasks/build-webpack.ts +++ b/packages/angular-cli/tasks/build-webpack.ts @@ -4,7 +4,7 @@ const Task = require('../ember-cli/lib/models/task'); import * as webpack from 'webpack'; import { BuildOptions } from '../commands/build'; import { NgCliWebpackConfig } from '../models/webpack-config'; -import { webpackOutputOptions } from '../models/'; +import { getWebpackStatsConfig } from '../models/'; import { CliConfig } from '../models/config'; // Configure build and output; @@ -25,16 +25,14 @@ export default Task.extend({ runTaskOptions.baseHref, runTaskOptions.aot, runTaskOptions.sourcemap, - runTaskOptions.vendorChunk + runTaskOptions.vendorChunk, + runTaskOptions.verbose, + runTaskOptions.progress ).config; const webpackCompiler: any = webpack(config); - const ProgressPlugin = require('webpack/lib/ProgressPlugin'); - - webpackCompiler.apply(new ProgressPlugin({ - profile: true - })); + const statsConfig = getWebpackStatsConfig(runTaskOptions.verbose); return new Promise((resolve, reject) => { webpackCompiler.run((err: any, stats: any) => { @@ -46,7 +44,7 @@ export default Task.extend({ if (stats.hash !== lastHash) { lastHash = stats.hash; - process.stdout.write(stats.toString(webpackOutputOptions) + '\n'); + process.stdout.write(stats.toString(statsConfig) + '\n'); } return stats.hasErrors() ? reject() : resolve(); diff --git a/packages/angular-cli/tasks/serve-webpack.ts b/packages/angular-cli/tasks/serve-webpack.ts index 936766633106..71cb640c070c 100644 --- a/packages/angular-cli/tasks/serve-webpack.ts +++ b/packages/angular-cli/tasks/serve-webpack.ts @@ -5,8 +5,7 @@ const SilentError = require('silent-error'); const Task = require('../ember-cli/lib/models/task'); import * as webpack from 'webpack'; const WebpackDevServer = require('webpack-dev-server'); -const ProgressPlugin = require('webpack/lib/ProgressPlugin'); -import { webpackDevServerOutputOptions } from '../models/'; +import { getWebpackStatsConfig } from '../models/'; import { NgCliWebpackConfig } from '../models/webpack-config'; import { ServeTaskOptions } from '../commands/serve'; import { CliConfig } from '../models/config'; @@ -15,37 +14,36 @@ import * as url from 'url'; const opn = require('opn'); export default Task.extend({ - run: function(commandOptions: ServeTaskOptions) { + run: function(serveTaskOptions: ServeTaskOptions) { const ui = this.ui; let webpackCompiler: any; let config = new NgCliWebpackConfig( this.project, - commandOptions.target, - commandOptions.environment, + serveTaskOptions.target, + serveTaskOptions.environment, undefined, undefined, - commandOptions.aot, - commandOptions.sourcemap, - commandOptions.vendorChunk + serveTaskOptions.aot, + serveTaskOptions.sourcemap, + serveTaskOptions.vendorChunk, + serveTaskOptions.verbose, + serveTaskOptions.progress ).config; // This allows for live reload of page when changes are made to repo. // https://webpack.github.io/docs/webpack-dev-server.html#inline-mode config.entry.main.unshift( - `webpack-dev-server/client?http://${commandOptions.host}:${commandOptions.port}/` + `webpack-dev-server/client?http://${serveTaskOptions.host}:${serveTaskOptions.port}/` ); webpackCompiler = webpack(config); - webpackCompiler.apply(new ProgressPlugin({ - profile: true, - colors: true - })); + const statsConfig = getWebpackStatsConfig(serveTaskOptions.verbose); let proxyConfig = {}; - if (commandOptions.proxyConfig) { - const proxyPath = path.resolve(this.project.root, commandOptions.proxyConfig); + if (serveTaskOptions.proxyConfig) { + const proxyPath = path.resolve(this.project.root, serveTaskOptions.proxyConfig); if (fs.existsSync(proxyPath)) { proxyConfig = require(proxyPath); } else { @@ -56,12 +54,12 @@ export default Task.extend({ let sslKey: string = null; let sslCert: string = null; - if (commandOptions.ssl) { - const keyPath = path.resolve(this.project.root, commandOptions.sslKey); + if (serveTaskOptions.ssl) { + const keyPath = path.resolve(this.project.root, serveTaskOptions.sslKey); if (fs.existsSync(keyPath)) { sslKey = fs.readFileSync(keyPath, 'utf-8'); } - const certPath = path.resolve(this.project.root, commandOptions.sslCert); + const certPath = path.resolve(this.project.root, serveTaskOptions.sslCert); if (fs.existsSync(certPath)) { sslCert = fs.readFileSync(certPath, 'utf-8'); } @@ -77,14 +75,14 @@ export default Task.extend({ disableDotRule: true, htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'] }, - stats: webpackDevServerOutputOptions, + stats: statsConfig, inline: true, proxy: proxyConfig, - compress: commandOptions.target === 'production', + compress: serveTaskOptions.target === 'production', watchOptions: { poll: CliConfig.fromProject().config.defaults.poll }, - https: commandOptions.ssl + https: serveTaskOptions.ssl }; if (sslKey != null && sslCert != null) { @@ -95,19 +93,21 @@ export default Task.extend({ ui.writeLine(chalk.green(oneLine` ** NG Live Development Server is running on - http${commandOptions.ssl ? 's' : ''}://${commandOptions.host}:${commandOptions.port}. + http${serveTaskOptions.ssl ? 's' : ''}://${serveTaskOptions.host}:${serveTaskOptions.port}. ** `)); const server = new WebpackDevServer(webpackCompiler, webpackDevServerConfiguration); return new Promise((resolve, reject) => { - server.listen(commandOptions.port, `${commandOptions.host}`, function(err: any, stats: any) { + server.listen(serveTaskOptions.port, + `${serveTaskOptions.host}`, + function(err: any, stats: any) { if (err) { console.error(err.stack || err); if (err.details) { console.error(err.details); } reject(err.details); } else { - const { open, host, port } = commandOptions; + const { open, host, port } = serveTaskOptions; if (open) { opn(url.format({ protocol: 'http', hostname: host, port: port.toString() })); } diff --git a/packages/angular-cli/tasks/test.ts b/packages/angular-cli/tasks/test.ts index 6714cf0e7601..648314d88764 100644 --- a/packages/angular-cli/tasks/test.ts +++ b/packages/angular-cli/tasks/test.ts @@ -26,7 +26,8 @@ export default Task.extend({ karmaOptions.angularCli = { codeCoverage: options.codeCoverage, lint: options.lint, - sourcemap: options.sourcemap + sourcemap: options.sourcemap, + progress: options.progress }; // Assign additional karmaConfig options to the local ngapp config diff --git a/tests/e2e/utils/process.ts b/tests/e2e/utils/process.ts index 4746453ec424..ab643865dc4d 100644 --- a/tests/e2e/utils/process.ts +++ b/tests/e2e/utils/process.ts @@ -101,8 +101,8 @@ export function silentExecAndWaitForOutputToMatch(cmd: string, args: string[], m } export function ng(...args: string[]) { - if (args[0] == 'build') { - return silentNg(...args); + if (args[0] == 'build' || args[0] == 'serve' || args[0] == 'test') { + return silentNg(...args, '--no-progress'); } else { return _exec({}, 'ng', args); }