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 6, 2017
1 parent 02f4bc3 commit 7dcb9fd
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 153 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@types/node": "^7.0.4",
"@types/run-sequence": "^0.0.28",
"@types/rx": "2.5.33",
"autoprefixer": "^6.7.6",
"axe-core": "^2.1.7",
"axe-webdriverjs": "^0.5.0",
"conventional-changelog": "^1.1.0",
Expand All @@ -62,7 +63,6 @@
"glob": "^7.1.1",
"google-cloud": "^0.45.1",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.1",
"gulp-better-rollup": "^1.0.2",
"gulp-clean": "^0.3.2",
"gulp-clean-css": "^2.3.2",
Expand All @@ -73,6 +73,7 @@
"gulp-htmlmin": "^3.0.0",
"gulp-if": "^2.0.2",
"gulp-markdown": "^1.2.0",
"gulp-postcss": "^6.3.0",
"gulp-rename": "^1.2.2",
"gulp-sass": "^3.1.0",
"gulp-sourcemaps": "^2.4.0",
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
25 changes: 16 additions & 9 deletions tools/gulp/task_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ import * as fs from 'fs';
import * as gulp from 'gulp';
import * as path from 'path';
import {NPM_VENDOR_FILES, PROJECT_ROOT, DIST_ROOT, SASS_AUTOPREFIXER_OPTIONS} from './constants';
import {compileProject} from './util/ts-compiler';
import {CompilerOptions} from 'typescript';


/** Those imports lack typings. */
/* Those imports lack typings. */
const gulpClean = require('gulp-clean');
const gulpMerge = require('merge2');
const gulpRunSequence = require('run-sequence');
const gulpSass = require('gulp-sass');
const gulpSourcemaps = require('gulp-sourcemaps');
const gulpAutoprefixer = require('gulp-autoprefixer');
const gulpPostcss = require('gulp-postcss');
const gulpConnect = require('gulp-connect');
const gulpIf = require('gulp-if');
const gulpCleanCss = require('gulp-clean-css');

const resolveBin = require('resolve-bin');
const firebaseAdmin = require('firebase-admin');
const gcloud = require('google-cloud');

const autoprefixer = require('autoprefixer');

/** If the string passed in is a glob, returns it, otherwise append '**\/*' to it. */
function _globify(maybeGlob: string, suffix = '**/*') {
Expand All @@ -34,18 +38,21 @@ function _globify(maybeGlob: string, suffix = '**/*') {


/** Creates a task that runs the TypeScript compiler */
export function tsBuildTask(tsConfigPath: string) {
return execNodeTask('typescript', 'tsc', ['-p', tsConfigPath]);
export function tsBuildTask(tsConfigPath: string, extraOptions?: CompilerOptions) {
return () => {
compileProject(tsConfigPath, extraOptions);
};
}


/** Create a SASS Build Task. */
export function sassBuildTask(dest: string, root: string) {
export function sassBuildTask(dest: string, root: string, minify = false) {
return () => {
return gulp.src(_globify(root, '**/*.scss'))
.pipe(gulpSourcemaps.init())
.pipe(gulpSourcemaps.init({ loadMaps: true }))
.pipe(gulpSass().on('error', gulpSass.logError))
.pipe(gulpAutoprefixer(SASS_AUTOPREFIXER_OPTIONS))
.pipe(gulpPostcss([autoprefixer(SASS_AUTOPREFIXER_OPTIONS)]))
.pipe(gulpIf(minify, gulpCleanCss()))
.pipe(gulpSourcemaps.write('.'))
.pipe(gulp.dest(dest));
};
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 '../task_helpers';

// No typings for these.
// These imports lack of types.
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:es',
':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:es', sequenceTask(
':build:components:ts:es6', ':build:components:inline', ':build:components:rollup:es'
));

/** 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:es', () => {
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);
}
Loading

0 comments on commit 7dcb9fd

Please sign in to comment.