Skip to content

Commit

Permalink
build: ship esm bundle
Browse files Browse the repository at this point in the history
* Now ships a Flat / ESM bundle (similar as for Angular 4+ releases)
* In future PRs we will remove the single ES-files and can just link to the ES bundle (as in angular/angular).
  • Loading branch information
devversion committed Mar 16, 2017
1 parent aa3360a commit f4eac4d
Show file tree
Hide file tree
Showing 14 changed files with 195 additions and 166 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
"glob": "^7.1.1",
"google-cloud": "^0.48.0",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.1",
"gulp-better-rollup": "^1.0.2",
"gulp-clean": "^0.3.2",
"gulp-clean-css": "^3.0.3",
Expand Down
33 changes: 0 additions & 33 deletions src/lib/tsconfig-srcs.json

This file was deleted.

6 changes: 2 additions & 4 deletions src/lib/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es6", "es2015", "dom"],
"module": "commonjs",
"module": "es2015",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": true,
"outDir": "../../dist/@angular/material",
"rootDir": ".",
"sourceMap": true,
"target": "es5",
"target": "es6",
"inlineSources": true,
"stripInternal": false,
"baseUrl": "",
"paths": {
},
"typeRoots": [
"../../node_modules/@types/!(node)"
],
Expand Down
9 changes: 0 additions & 9 deletions tools/gulp/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ export const DIST_COMPONENTS_ROOT = join(DIST_ROOT, '@angular/material');

export const COVERAGE_RESULT_FILE = join(DIST_ROOT, 'coverage', 'coverage-summary.json');

export const SASS_AUTOPREFIXER_OPTIONS = {
browsers: [
'last 2 versions',
'not ie <= 10',
'not ie_mob <= 10',
],
cascade: false,
};

export const HTML_MINIFIER_OPTIONS = {
collapseWhitespace: true,
removeComments: true,
Expand Down
2 changes: 1 addition & 1 deletion tools/gulp/tasks/aot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ task('aot:copy', [':build:devapp:scss', ':build:devapp:assets']);
*/
task('aot:prepare', sequenceTask(
'clean',
['aot:copy', 'build:components:release', ':build:components:ngc'])
['aot:copy', 'build:components', ':build:components:ngc'])
);

/** Builds the demo-app with the Angular compiler to verify that all components work. */
Expand Down
211 changes: 111 additions & 100 deletions tools/gulp/tasks/components.ts
Original file line number Diff line number Diff line change
@@ -1,139 +1,150 @@
import {task, watch, src, dest} from 'gulp';
import {ScriptTarget, ModuleKind} from 'typescript';
import * as path from 'path';

import {
DIST_COMPONENTS_ROOT, PROJECT_ROOT, COMPONENTS_DIR, HTML_MINIFIER_OPTIONS, LICENSE_BANNER
} from '../constants';
import {
sassBuildTask, tsBuildTask, execNodeTask, copyTask, sequenceTask,
sassBuildTask, tsBuildTask, execNodeTask, sequenceTask,
triggerLivereload
} from '../util/task_helpers';

// No typings for these.
// There are no type definitions available for these imports.
const inlineResources = require('../../../scripts/release/inline-resources');
const gulpRollup = require('gulp-better-rollup');
const gulpMinifyCss = require('gulp-clean-css');
const gulpMinifyHtml = require('gulp-htmlmin');
const gulpIf = require('gulp-if');

/** Path to tsconfig file for the components. */
const tsconfigPath = path.join(COMPONENTS_DIR, 'tsconfig.json');

// NOTE: there are two build "modes" in this file, based on which tsconfig is used.
// When `tsconfig.json` is used, we are outputting ES6 modules and a UMD bundle. This is used
// for serving and for release.
//
// When `tsconfig-spec.json` is used, we are outputting CommonJS modules. This is used
// for unit tests (karma).

/** Path to the tsconfig used for ESM output. */
const tsconfigPath = path.relative(PROJECT_ROOT, path.join(COMPONENTS_DIR, 'tsconfig-srcs.json'));
/** Asset files to be added to the components output. */
const assetFiles = [
path.join(COMPONENTS_DIR, '**/*.html'),
path.join(COMPONENTS_DIR, 'package.json'),
path.join(PROJECT_ROOT, 'README.md'),
path.join(PROJECT_ROOT, 'LICENSE'),
];

/** Builds components to UMD bundle. */
task('build:components', [':build:components:bundle:umd']);

/** [Watch task] Rebuilds (ESM output) whenever ts, scss, or html sources change. */
task(':watch:components', () => {
watch(path.join(COMPONENTS_DIR, '**/*.ts'), ['build:components', triggerLivereload]);
watch(path.join(COMPONENTS_DIR, '**/*.scss'), ['build:components', triggerLivereload]);
watch(path.join(COMPONENTS_DIR, '**/*.html'), ['build:components', triggerLivereload]);
});

/** Builds components for Angular Material releases */
task(':build:components:release', sequenceTask(
':build:components:bundle:umd',
':build:components:bundle:esm',
':build:components:ngc'
));

/** Builds component typescript only (ESM output). */
task(':build:components:ts', tsBuildTask(path.join(COMPONENTS_DIR, 'tsconfig-srcs.json')));
/** Builds components typescript in ES5, ES6 target. For specs Karma needs CJS output. */
task(':build:components:ts:es5', tsBuildTask(tsconfigPath, { target: ScriptTarget.ES5 }));
task(':build:components:ts:es6', tsBuildTask(tsconfigPath, { target: ScriptTarget.ES6 }));
task(':build:components:ts:spec', tsBuildTask(tsconfigPath, {
target: ScriptTarget.ES5, module: ModuleKind.CommonJS
}));

/** Builds components typescript for tests (CJS output). */
task(':build:components:spec', tsBuildTask(COMPONENTS_DIR));
/** Tasks to create a UMD or ES bundle */
task(':build:components:bundle:umd', sequenceTask(
':build:components:ts:es5', ':build:components:inline', ':build:components:rollup:umd'
));

/** Copies assets (html, markdown) to build output. */
task(':build:components:assets', copyTask([
path.join(COMPONENTS_DIR, '**/*.!(ts|spec.ts)'),
path.join(PROJECT_ROOT, 'README.md'),
path.join(PROJECT_ROOT, 'LICENSE'),
], DIST_COMPONENTS_ROOT));
task(':build:components:bundle:esm', sequenceTask(
':build:components:ts:es6', ':build:components:inline', ':build:components:rollup:esm'
));

/** Minifies the HTML and CSS assets in the distribution folder. */
task(':build:components:assets:minify', () => {
return src('**/*.+(html|css)', { cwd: DIST_COMPONENTS_ROOT})
.pipe(gulpIf(/.css$/, gulpMinifyCss(), gulpMinifyHtml(HTML_MINIFIER_OPTIONS)))
/** Copies all component assets to the build output. */
task(':build:components:assets', () => {
return src(assetFiles)
.pipe(gulpIf(/.html$/, gulpMinifyHtml(HTML_MINIFIER_OPTIONS)))
.pipe(dest(DIST_COMPONENTS_ROOT));
});

/** Builds scss into css. */
task(':build:components:scss', sassBuildTask(DIST_COMPONENTS_ROOT, COMPONENTS_DIR));

/** Builds the UMD bundle for all of Angular Material. */
task(':build:components:rollup', () => {
const globals: {[name: string]: string} = {
// Angular dependencies
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'@angular/forms': 'ng.forms',
'@angular/http': 'ng.http',
'@angular/platform-browser': 'ng.platformBrowser',
'@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',

// Rxjs dependencies
'rxjs/Subject': 'Rx',
'rxjs/add/observable/fromEvent': 'Rx.Observable',
'rxjs/add/observable/forkJoin': 'Rx.Observable',
'rxjs/add/observable/of': 'Rx.Observable',
'rxjs/add/observable/merge': 'Rx.Observable',
'rxjs/add/observable/throw': 'Rx.Observable',
'rxjs/add/operator/auditTime': 'Rx.Observable.prototype',
'rxjs/add/operator/toPromise': 'Rx.Observable.prototype',
'rxjs/add/operator/map': 'Rx.Observable.prototype',
'rxjs/add/operator/filter': 'Rx.Observable.prototype',
'rxjs/add/operator/do': 'Rx.Observable.prototype',
'rxjs/add/operator/share': 'Rx.Observable.prototype',
'rxjs/add/operator/finally': 'Rx.Observable.prototype',
'rxjs/add/operator/catch': 'Rx.Observable.prototype',
'rxjs/add/operator/first': 'Rx.Observable.prototype',
'rxjs/add/operator/startWith': 'Rx.Observable.prototype',
'rxjs/add/operator/switchMap': 'Rx.Observable.prototype',
'rxjs/Observable': 'Rx'
};

const rollupOptions = {
context: 'this',
external: Object.keys(globals)
};

const rollupGenerateOptions = {
// Keep the moduleId empty because we don't want to force developers to a specific moduleId.
moduleId: '',
moduleName: 'ng.material',
format: 'umd',
globals,
banner: LICENSE_BANNER,
dest: 'material.umd.js'
};
/** Compiles the components SCSS into minified CSS. */
task(':build:components:scss', sassBuildTask(DIST_COMPONENTS_ROOT, COMPONENTS_DIR, true));

/** Builds a ES6 bundle for all components. */
task(':build:components:rollup:esm', () => {
return src(path.join(DIST_COMPONENTS_ROOT, 'index.js'))
.pipe(gulpRollup(rollupOptions, rollupGenerateOptions))
.pipe(createRollupBundle('es', 'material.js'))
.pipe(dest(path.join(DIST_COMPONENTS_ROOT, 'bundles')));
});

/** Builds components with resources (html, css) inlined into the built JS (ESM output). */
/** Builds a UMD bundle (ES5) for all components. */
task(':build:components:rollup:umd', () => {
return src(path.join(DIST_COMPONENTS_ROOT, 'index.js'))
.pipe(createRollupBundle('umd', 'material.umd.js'))
.pipe(dest(path.join(DIST_COMPONENTS_ROOT, 'bundles')));
});


/** Builds components with resources (html, css) inlined into the built JS. */
task(':build:components:inline', sequenceTask(
[':build:components:ts', ':build:components:scss', ':build:components:assets'],
[':build:components:scss', ':build:components:assets'],
':inline-resources',
));

/** Builds components with minified HTML and CSS inlined into the built JS. */
task(':build:components:inline:release', sequenceTask(
[':build:components:ts', ':build:components:scss', ':build:components:assets'],
':build:components:assets:minify',
':inline-resources'
));

/** Inlines resources (html, css) into the JS output (for either ESM or CJS output). */
/** Inlines resources (html, css) into the JS output. */
task(':inline-resources', () => inlineResources(DIST_COMPONENTS_ROOT));

/** Builds components to ESM output and UMD bundle. */
task('build:components', sequenceTask(':build:components:inline', ':build:components:rollup'));
task('build:components:release', sequenceTask(
':build:components:inline:release', ':build:components:rollup'
));

/** Generates metadata.json files for all of the components. */
task(':build:components:ngc', ['build:components:release'], execNodeTask(
task(':build:components:ngc', ['build:components'], execNodeTask(
'@angular/compiler-cli', 'ngc', ['-p', tsconfigPath]
));

/** [Watch task] Rebuilds (ESM output) whenever ts, scss, or html sources change. */
task(':watch:components', () => {
watch(path.join(COMPONENTS_DIR, '**/*.ts'), ['build:components', triggerLivereload]);
watch(path.join(COMPONENTS_DIR, '**/*.scss'), ['build:components', triggerLivereload]);
watch(path.join(COMPONENTS_DIR, '**/*.html'), ['build:components', triggerLivereload]);
});

const ROLLUP_GLOBALS = {
// Angular dependencies
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'@angular/forms': 'ng.forms',
'@angular/http': 'ng.http',
'@angular/platform-browser': 'ng.platformBrowser',
'@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',

// Rxjs dependencies
'rxjs/Subject': 'Rx',
'rxjs/add/observable/fromEvent': 'Rx.Observable',
'rxjs/add/observable/forkJoin': 'Rx.Observable',
'rxjs/add/observable/of': 'Rx.Observable',
'rxjs/add/observable/merge': 'Rx.Observable',
'rxjs/add/observable/throw': 'Rx.Observable',
'rxjs/add/operator/auditTime': 'Rx.Observable.prototype',
'rxjs/add/operator/toPromise': 'Rx.Observable.prototype',
'rxjs/add/operator/map': 'Rx.Observable.prototype',
'rxjs/add/operator/filter': 'Rx.Observable.prototype',
'rxjs/add/operator/do': 'Rx.Observable.prototype',
'rxjs/add/operator/share': 'Rx.Observable.prototype',
'rxjs/add/operator/finally': 'Rx.Observable.prototype',
'rxjs/add/operator/catch': 'Rx.Observable.prototype',
'rxjs/add/operator/first': 'Rx.Observable.prototype',
'rxjs/add/operator/startWith': 'Rx.Observable.prototype',
'rxjs/add/operator/switchMap': 'Rx.Observable.prototype',
'rxjs/Observable': 'Rx'
};

/** Creates a rollup bundles of the Material components.*/
function createRollupBundle(format: string, outFile: string) {
let rollupOptions = {
context: 'this',
external: Object.keys(ROLLUP_GLOBALS)
};

let rollupGenerateOptions = {
// Keep the moduleId empty because we don't want to force developers to a specific moduleId.
moduleId: '',
moduleName: 'ng.material',
banner: LICENSE_BANNER,
format: format,
dest: outFile,
globals: ROLLUP_GLOBALS,
};

return gulpRollup(rollupOptions, rollupGenerateOptions);
}
4 changes: 3 additions & 1 deletion tools/gulp/tasks/development.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ task(':watch:devapp', () => {
watch(path.join(appDir, '**/*.html'), [':build:devapp:assets', triggerLivereload]);
});

/** Path to the demo-app tsconfig file. */
const tsconfigPath = path.join(appDir, 'tsconfig.json');

task(':build:devapp:vendor', vendorTask());
task(':build:devapp:ts', tsBuildTask(appDir));
task(':build:devapp:ts', tsBuildTask(tsconfigPath));
task(':build:devapp:scss', sassBuildTask(outDir, appDir));
task(':build:devapp:assets', copyTask(appDir, outDir));
task('build:devapp', buildAppTask('devapp'));
Expand Down
2 changes: 1 addition & 1 deletion tools/gulp/tasks/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Dgeni} from 'dgeni';
import * as path from 'path';
import {HTML_MINIFIER_OPTIONS} from '../constants';

// Node packages that lack of types.
// There are no type definitions available for these imports.
const markdown = require('gulp-markdown');
const transform = require('gulp-transform');
const highlight = require('gulp-highlight-files');
Expand Down
4 changes: 3 additions & 1 deletion tools/gulp/tasks/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const appDir = path.join(SOURCE_ROOT, 'e2e-app');
const outDir = DIST_ROOT;
const PROTRACTOR_CONFIG_PATH = path.join(PROJECT_ROOT, 'test/protractor.conf.js');

const tsconfigPath = path.join(appDir, 'tsconfig.json');

task(':watch:e2eapp', () => {
watch(path.join(appDir, '**/*.ts'), [':build:e2eapp:ts']);
watch(path.join(appDir, '**/*.html'), [':build:e2eapp:assets']);
Expand All @@ -23,7 +25,7 @@ task(':watch:e2eapp', () => {
task(':build:e2eapp:vendor', vendorTask());

/** Builds e2e app ts to js. */
task(':build:e2eapp:ts', tsBuildTask(appDir));
task(':build:e2eapp:ts', tsBuildTask(tsconfigPath));

/** Copies e2e app assets (html, css) to build output. */
task(':build:e2eapp:assets', copyTask(appDir, outDir));
Expand Down
2 changes: 1 addition & 1 deletion tools/gulp/tasks/payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {spawnSync} from 'child_process';
import {isTravisPushBuild} from '../util/travis-ci';
import {openFirebaseDashboardDatabase} from '../util/firebase';

// Those imports lack types.
// There are no type definitions available for these imports.
const uglifyJs = require('uglify-js');

const BUNDLE_PATH = join(DIST_COMPONENTS_ROOT, 'bundles', 'material.umd.js');
Expand Down
2 changes: 1 addition & 1 deletion tools/gulp/tasks/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ task('build:release', function(done: () => void) {
// Synchronously run those tasks.
gulpRunSequence(
'clean',
':build:components:ngc',
':build:components:release',
':build:release:clean-spec',
done
);
Expand Down
Loading

0 comments on commit f4eac4d

Please sign in to comment.