diff --git a/gulpfile.js b/gulpfile.js
index 3781f7378a..d1fafbbd42 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -46,10 +46,36 @@ var dartSdk = require('./tools/build/dart');
var browserProvidersConf = require('./browser-providers.conf.js');
var os = require('os');
-require('./tools/check-environment')({
- requiredNpmVersion: '>=2.14.7',
- requiredNodeVersion: '>=4.2.1'
-});
+require('./tools/check-environment')(
+ {requiredNpmVersion: '>=2.14.7', requiredNodeVersion: '>=4.2.1'});
+
+var cliArgs = minimist(process.argv.slice(2));
+
+if (cliArgs.projects) {
+ // normalize for analytics
+ cliArgs.projects.split(',').sort().join(',');
+}
+
+// --projects=angular2,angular2_material => {angular2: true, angular2_material: true}
+var allProjects =
+ 'angular1_router,angular2,angular2_material,benchmarks,benchmarks_external,benchpress,playground';
+var cliArgsProjects = (cliArgs.projects || allProjects)
+ .split(',')
+ .reduce((map, projectName) => {
+ map[projectName] = true;
+ return map;
+ }, {});
+
+function printModulesWarning() {
+ if (!cliArgs.projects && !process.env.CI) {
+ // if users didn't specify projects to build, tell them why and how they should
+ console.warn(
+ "Pro Tip: Did you know that you can speed up your build by specifying project name(s)?");
+ console.warn(" It's like pressing the turbo button in the old days, but better!");
+ console.warn(" Examples: --project=angular2 or --project=angular2,angular2_material");
+ }
+}
+
// Make it easy to quiet down portions of the build.
// --logs=all -> log everything (This is the default)
@@ -162,7 +188,7 @@ gulp.task('build/tree.dart', ['build/clean.dart', 'build.tools'],
gulp.task('!build/tree.dart',
- function() { return angularBuilder.rebuildDartTree(); });
+ function() { return angularBuilder.rebuildDartTree(cliArgsProjects); });
// ------------
@@ -444,15 +470,19 @@ function getBrowsersFromCLI(provider) {
}
gulp.task('test.unit.js', ['build.js.dev'], function(done) {
+ printModulesWarning();
runSequence('!test.unit.js/karma-server', function() {
watch('modules/**', {ignoreInitial: true}, ['!broccoli.js.dev', '!test.unit.js/karma-run']);
});
});
-gulp.task('watch.js.dev', ['build.js.dev'],
- function(done) { watch('modules/**', ['!broccoli.js.dev']); });
+gulp.task('watch.js.dev', ['build.js.dev'], function(done) {
+ printModulesWarning();
+ watch('modules/**', ['!broccoli.js.dev']);
+});
gulp.task('test.unit.js.sauce', ['build.js.dev'], function(done) {
+ printModulesWarning();
var browserConf = getBrowsersFromCLI('SL');
if (browserConf.isProvider) {
launchKarmaWithExternalBrowsers(['dots'], browserConf.browsersToRun, done);
@@ -462,6 +492,7 @@ gulp.task('test.unit.js.sauce', ['build.js.dev'], function(done) {
});
gulp.task('test.unit.js.browserstack', ['build.js.dev'], function(done) {
+ printModulesWarning();
var browserConf = getBrowsersFromCLI('BS');
if (browserConf.isProvider) {
launchKarmaWithExternalBrowsers(['dots'], browserConf.browsersToRun, done);
@@ -535,6 +566,7 @@ gulp.task('!test.unit.router/karma-run', function(done) {
gulp.task('buildRouter.dev', function() { buildRouter(); });
gulp.task('test.unit.dart', function(done) {
+ printModulesWarning();
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css',
'!test.unit.dart/karma-server', '!test.unit.dart/karma-run', function(error) {
@@ -632,12 +664,9 @@ gulp.task('test.unit.cjs/ci', function(done) {
gulp.task('test.unit.cjs', ['build/clean.js', 'build.tools'], function(neverDone) {
-
+ printModulesWarning();
treatTestErrorsAsFatal = false;
-
- var buildAndTest = ['!build.js.cjs', 'test.unit.cjs/ci'];
-
- watch('modules/**', buildAndTest);
+ watch('modules/**', ['!build.js.cjs', 'test.unit.cjs/ci']);
});
// Use this target to continuously run dartvm unit-tests (such as transformer
@@ -812,12 +841,11 @@ gulp.task('!build.tools', function() {
gulp.task('broccoli.js.dev', ['build.tools'],
function(done) { runSequence('!broccoli.js.dev', sequenceComplete(done)); });
-gulp.task('!broccoli.js.dev', () => {
- return angularBuilder.rebuildBrowserDevTree();
-});
+gulp.task('!broccoli.js.dev',
+ () => { return angularBuilder.rebuildBrowserDevTree(cliArgsProjects); });
gulp.task('!broccoli.js.prod',
- function() { return angularBuilder.rebuildBrowserProdTree(); });
+ function() { return angularBuilder.rebuildBrowserProdTree(cliArgsProjects); });
gulp.task('build.js.dev', ['build/clean.js'], function(done) {
runSequence('broccoli.js.dev', 'build.css.material', sequenceComplete(done));
@@ -840,7 +868,7 @@ var firstBuildJsCjs = true;
* private task
*/
gulp.task('!build.js.cjs', function() {
- return angularBuilder.rebuildNodeTree()
+ return angularBuilder.rebuildNodeTree(cliArgsProjects)
.then(function() {
if (firstBuildJsCjs) {
firstBuildJsCjs = false;
diff --git a/modules/angular2/manual_typings/globals-es6.d.ts b/modules/angular2/manual_typings/globals-es6.d.ts
index 02540be14c..43d437ad64 100644
--- a/modules/angular2/manual_typings/globals-es6.d.ts
+++ b/modules/angular2/manual_typings/globals-es6.d.ts
@@ -8,8 +8,14 @@
///
///
///
+
+// TODO: ideally the node.d.ts reference should be scoped only for files that need and not to all
+// the code including client code
+///
+
declare var assert: any;
+
interface BrowserNodeGlobal {
Object: typeof Object;
Array: typeof Array;
diff --git a/tools/broccoli/angular_builder.ts b/tools/broccoli/angular_builder.ts
index ae45e1ef57..699c3d6a02 100644
--- a/tools/broccoli/angular_builder.ts
+++ b/tools/broccoli/angular_builder.ts
@@ -7,6 +7,10 @@ var path = require('path');
var printSlowTrees = require('broccoli-slow-trees');
var Q = require('q');
+type ProjectMap = {
+ [key: string]: boolean
+};
+
/**
* BroccoliBuilder facade for all of our build pipelines.
*/
@@ -21,26 +25,26 @@ export class AngularBuilder {
constructor(public options: AngularBuilderOptions) { this.outputPath = options.outputPath; }
- public rebuildBrowserDevTree(): Promise {
- this.browserDevBuilder = this.browserDevBuilder || this.makeBrowserDevBuilder();
+ public rebuildBrowserDevTree(projects: ProjectMap): Promise {
+ this.browserDevBuilder = this.browserDevBuilder || this.makeBrowserDevBuilder(projects);
return this.rebuild(this.browserDevBuilder, 'js.dev');
}
- public rebuildBrowserProdTree(): Promise {
- this.browserProdBuilder = this.browserProdBuilder || this.makeBrowserProdBuilder();
+ public rebuildBrowserProdTree(projects: ProjectMap): Promise {
+ this.browserProdBuilder = this.browserProdBuilder || this.makeBrowserProdBuilder(projects);
return this.rebuild(this.browserProdBuilder, 'js.prod');
}
- public rebuildNodeTree(): Promise {
- this.nodeBuilder = this.nodeBuilder || this.makeNodeBuilder();
+ public rebuildNodeTree(projects: ProjectMap): Promise {
+ this.nodeBuilder = this.nodeBuilder || this.makeNodeBuilder(projects);
return this.rebuild(this.nodeBuilder, 'js.cjs');
}
- public rebuildDartTree(): Promise {
- this.dartBuilder = this.dartBuilder || this.makeDartBuilder();
+ public rebuildDartTree(projects: ProjectMap): Promise {
+ this.dartBuilder = this.dartBuilder || this.makeDartBuilder(projects);
return this.rebuild(this.dartBuilder, 'dart');
}
@@ -54,31 +58,32 @@ export class AngularBuilder {
}
- private makeBrowserDevBuilder(): BroccoliBuilder {
- let tree = makeBrowserTree({name: 'dev', typeAssertions: true},
+ private makeBrowserDevBuilder(projects: ProjectMap): BroccoliBuilder {
+ let tree = makeBrowserTree({name: 'dev', typeAssertions: true, projects: projects},
path.join(this.outputPath, 'js', 'dev'));
return new broccoli.Builder(tree);
}
- private makeBrowserProdBuilder(): BroccoliBuilder {
- let tree = makeBrowserTree({name: 'prod', typeAssertions: false},
+ private makeBrowserProdBuilder(projects: ProjectMap): BroccoliBuilder {
+ let tree = makeBrowserTree({name: 'prod', typeAssertions: false, projects: projects},
path.join(this.outputPath, 'js', 'prod'));
return new broccoli.Builder(tree);
}
- private makeNodeBuilder(): BroccoliBuilder {
- let tree = makeNodeTree(path.join(this.outputPath, 'js', 'cjs'));
+ private makeNodeBuilder(projects: ProjectMap): BroccoliBuilder {
+ let tree = makeNodeTree(projects, path.join(this.outputPath, 'js', 'cjs'));
return new broccoli.Builder(tree);
}
- private makeDartBuilder(): BroccoliBuilder {
+ private makeDartBuilder(projects: ProjectMap): BroccoliBuilder {
let options = {
outputPath: path.join(this.outputPath, 'dart'),
dartSDK: this.options.dartSDK,
- logs: this.options.logs
+ logs: this.options.logs,
+ projects: projects
};
let tree = makeDartTree(options);
return new broccoli.Builder(tree);
diff --git a/tools/broccoli/broccoli-typescript.ts b/tools/broccoli/broccoli-typescript.ts
index 5156422e8f..c90db682a8 100644
--- a/tools/broccoli/broccoli-typescript.ts
+++ b/tools/broccoli/broccoli-typescript.ts
@@ -47,6 +47,12 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
// in tsc 1.7.x this api was renamed to parseJsonConfigFileContent
// the conversion is a bit awkward, see https://github.com/Microsoft/TypeScript/issues/5276
this.tsOpts = ts.parseConfigFile({compilerOptions: options, files: []}, null, null).options;
+
+ // TODO: the above turns rootDir set to './' into an empty string - looks like a tsc bug
+ // check back when we upgrade to 1.7.x
+ if (this.tsOpts.rootDir === '') {
+ this.tsOpts.rootDir = './';
+ }
this.tsOpts.outDir = this.cachePath;
this.tsServiceHost = new CustomLanguageServiceHost(this.tsOpts, this.rootFilePaths,
diff --git a/tools/broccoli/trees/browser_tree.ts b/tools/broccoli/trees/browser_tree.ts
index ad02214e91..b736c25b63 100644
--- a/tools/broccoli/trees/browser_tree.ts
+++ b/tools/broccoli/trees/browser_tree.ts
@@ -70,26 +70,55 @@ const kServedPaths = [
module.exports = function makeBrowserTree(options, destinationPath) {
- var modulesTree = new Funnel('modules', {
- include: ['**/**'],
- exclude: [
- '**/*.cjs',
- 'benchmarks/e2e_test/**',
- 'angular1_router/**',
- // Exclude ES6 polyfill typings when tsc target=ES6
- 'angular2/typings/es6-*/**',
- ],
- destDir: '/'
- });
+ var modules = options.projects;
+
+ if (modules.angular2) {
+ var angular2Tree = new Funnel('modules/angular2', {
+ include: ['**/**'],
+ exclude: [
+ // Exclude ES6 polyfill typings when tsc target=ES6
+ 'typings/es6-*/**',
+ ],
+ destDir: '/angular2/'
+ });
+ }
+
+ if (modules.angular2_material) {
+ var angular2MaterialTree =
+ new Funnel('modules/angular2_material',
+ {include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/angular2_material/'});
+ }
+
+ if (modules.benchmarks) {
+ var benchmarksTree =
+ new Funnel('modules/benchmarks',
+ {include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchmarks/'});
+ }
+
+ if (modules.benchmarks_external) {
+ var benchmarksExternalTree = new Funnel(
+ 'modules/benchmarks_external',
+ {include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchmarks_external/'});
+ }
+
+ if (modules.playground) {
+ var playgroundTree =
+ new Funnel('modules/playground',
+ {include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/playground/'});
+ }
+
+ var modulesTree = mergeTrees(
+ [angular2Tree, angular2MaterialTree, benchmarksTree, benchmarksExternalTree, playgroundTree]);
var clientModules = new Funnel(
'node_modules', {include: ['@reactivex/**/**', 'parse5/**/**', 'css/**/**'], destDir: '/'});
- var es5ModulesTree = new Funnel('modules', {
- include: ['**/**'],
- exclude: ['**/*.cjs', 'angular1_router/**', 'benchmarks/e2e_test/**'],
- destDir: '/'
- });
+ var es6PolyfillTypings =
+ new Funnel('modules', {include: ['angular2/typings/es6-*/**'], destDir: '/'});
+
+ var es5ModulesTree = mergeTrees([modulesTree, es6PolyfillTypings]);
+
+ es5ModulesTree = stew.debug(es5ModulesTree, {name: 'debug-es5'});
var scriptPathPatternReplacement = {
match: '@@PATH',
@@ -119,7 +148,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
experimentalDecorators: true,
mapRoot: '', // force sourcemaps to use relative path
noEmitOnError: false,
- rootDir: '.',
+ rootDir: './',
rootFilePaths: ['angular2/manual_typings/globals-es6.d.ts'],
sourceMap: true,
sourceRoot: '.',
@@ -127,7 +156,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
});
// Use TypeScript to transpile the *.ts files to ES5
- var typescriptOptions = {
+ var es5Tree = compileWithTypescript(es5ModulesTree, {
declaration: false,
emitDecoratorMetadata: true,
experimentalDecorators: true,
@@ -135,13 +164,12 @@ module.exports = function makeBrowserTree(options, destinationPath) {
module: 'commonjs',
moduleResolution: 'classic',
noEmitOnError: true,
- rootDir: '.',
+ rootDir: './',
rootFilePaths: ['angular2/manual_typings/globals.d.ts'],
sourceMap: true,
sourceRoot: '.',
target: 'es5'
- };
- var es5Tree = compileWithTypescript(es5ModulesTree, typescriptOptions);
+ });
var vendorScriptsTree = flatten(new Funnel('.', {
files: [
@@ -173,61 +201,80 @@ module.exports = function makeBrowserTree(options, destinationPath) {
return funnels;
}
+
+ if (modules.angular2_material || modules.benchmarks || modules.benchmarks_external ||
+ modules.playground) {
+ var assetsTree = new Funnel(
+ modulesTree, {include: ['**/*'], exclude: ['**/*.{html,ts,dart}'], destDir: '/'});
+ }
+
var htmlTree = new Funnel(
modulesTree, {include: ['*/src/**/*.html', '**/playground/**/*.html'], destDir: '/'});
- htmlTree = replace(htmlTree, {
- files: ['playground*/**/*.html'],
- patterns: [
- {match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS')},
- scriptPathPatternReplacement,
- scriptFilePatternReplacement
- ]
- });
+ if (modules.benchmarks || modules.benchmarks_external || modules.playground) {
+ htmlTree = replace(htmlTree, {
+ files: ['playground*/**/*.html'],
+ patterns: [
+ {match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS')},
+ scriptPathPatternReplacement,
+ scriptFilePatternReplacement
+ ]
+ });
+ }
- htmlTree = replace(htmlTree, {
- files: ['benchmarks/**'],
- patterns: [
- {match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks')},
- scriptPathPatternReplacement,
- scriptFilePatternReplacement
- ]
- });
+ if (modules.benchmarks) {
+ htmlTree = replace(htmlTree, {
+ files: ['benchmarks/**'],
+ patterns: [
+ {match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks')},
+ scriptPathPatternReplacement,
+ scriptFilePatternReplacement
+ ]
+ });
+ }
- htmlTree = replace(htmlTree, {
- files: ['benchmarks_external/**'],
- patterns: [
- {match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks_external')},
- scriptPathPatternReplacement,
- scriptFilePatternReplacement
- ]
- });
+ if (modules.benchmarks_external) {
+ htmlTree = replace(htmlTree, {
+ files: ['benchmarks_external/**'],
+ patterns: [
+ {match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks_external')},
+ scriptPathPatternReplacement,
+ scriptFilePatternReplacement
+ ]
+ });
+ }
- // We need to replace the regular angular bundle with the web-worker bundle
- // for web-worker e2e tests.
- htmlTree = replace(htmlTree, {
- files: ['playground*/**/web_workers/**/*.html'],
- patterns: [{match: "/bundle/angular2.dev.js", replacement: "/bundle/web_worker/ui.dev.js"}]
- });
+ if (modules.playground) {
+ // We need to replace the regular angular bundle with the web-worker bundle
+ // for web-worker e2e tests.
+ htmlTree = replace(htmlTree, {
+ files: ['playground*/**/web_workers/**/*.html'],
+ patterns: [{match: "/bundle/angular2.dev.js", replacement: "/bundle/web_worker/ui.dev.js"}]
+ });
+ }
- var assetsTree =
- new Funnel(modulesTree, {include: ['**/*'], exclude: ['**/*.{html,ts,dart}'], destDir: '/'});
+ if (modules.benchmarks || modules.benchmarks_external) {
+ var scripts = mergeTrees(servingTrees);
+ }
- var scripts = mergeTrees(servingTrees);
- var polymerFiles = new Funnel('.', {
- files: [
- 'bower_components/polymer/polymer.html',
- 'bower_components/polymer/polymer-micro.html',
- 'bower_components/polymer/polymer-mini.html',
- 'tools/build/snippets/url_params_to_form.js'
- ]
- });
- var polymer = stew.mv(flatten(polymerFiles), 'benchmarks_external/src/tree/polymer');
+ if (modules.benchmarks_external) {
+ var polymerFiles = new Funnel('.', {
+ files: [
+ 'bower_components/polymer/polymer.html',
+ 'bower_components/polymer/polymer-micro.html',
+ 'bower_components/polymer/polymer-mini.html',
+ 'tools/build/snippets/url_params_to_form.js'
+ ]
+ });
+ var polymer = stew.mv(flatten(polymerFiles), 'benchmarks_external/src/tree/polymer');
- var reactFiles = new Funnel('.', {files: ['node_modules/react/dist/react.min.js']});
- var react = stew.mv(flatten(reactFiles), 'benchmarks_external/src/tree/react');
+ var reactFiles = new Funnel('.', {files: ['node_modules/react/dist/react.min.js']});
+ var react = stew.mv(flatten(reactFiles), 'benchmarks_external/src/tree/react');
+ }
- htmlTree = mergeTrees([htmlTree, scripts, polymer, react]);
+ if (modules.benchmarks || modules.benchmarks_external || modules.playground) {
+ htmlTree = mergeTrees([htmlTree, scripts, polymer, react]);
+ }
es5Tree = mergeTrees([es5Tree, htmlTree, assetsTree, clientModules]);
es6Tree = mergeTrees([es6Tree, htmlTree, assetsTree, clientModules]);
diff --git a/tools/broccoli/trees/node_tree.ts b/tools/broccoli/trees/node_tree.ts
index 3ff5f7c1f8..ef45433c5c 100644
--- a/tools/broccoli/trees/node_tree.ts
+++ b/tools/broccoli/trees/node_tree.ts
@@ -12,7 +12,7 @@ var stew = require('broccoli-stew');
var projectRootDir = path.normalize(path.join(__dirname, '..', '..', '..', '..'));
-module.exports = function makeNodeTree(destinationPath) {
+module.exports = function makeNodeTree(projects, destinationPath) {
// list of npm packages that this build will create
var outputPackages = ['angular2', 'benchpress'];