From 76c99e978c5879b34b860f55bab49185ee872c83 Mon Sep 17 00:00:00 2001 From: Torgeir Helgevold Date: Sun, 16 Oct 2016 16:18:12 -0400 Subject: [PATCH 01/31] docs(cb-third-party-lib) create a third party lib s s s s s c s c s s s s s s s s s s s s s s s s s s s s s s s s s --- gulpfile.js | 4 +- .../docs/_examples/_boilerplate/package.json | 1 + .../_boilerplate/src/systemjs.config.js | 3 +- .../_examples/cb-third-party-lib/.gitignore | 9 + .../_examples/cb-third-party-lib/e2e-spec.ts | 22 ++ .../hero-profile/hero-profile.component.css | 6 + .../hero-profile/hero-profile.component.html | 7 + .../hero-profile/hero-profile.component.ts | 14 + .../hero-profile/hero-profile.module.ts | 12 + .../cb-third-party-lib/hero-profile/hero.ts | 4 + .../cb-third-party-lib/hero-profile/index.ts | 4 + .../hero-profile/inline-resources.js | 137 ++++++++++ .../hero-profile/package.json | 14 + .../hero-profile/publish.js | 59 +++++ .../hero-profile/rollup-config.js | 10 + .../hero-profile/tsconfig-aot.json | 22 ++ .../ts/app-aot/app.component.ts | 14 + .../ts/app-aot/app.module.ts | 13 + .../cb-third-party-lib/ts/app-aot/main-aot.ts | 3 + .../ts/app/app.component.ts | 14 + .../cb-third-party-lib/ts/app/app.module.ts | 13 + .../cb-third-party-lib/ts/app/main.ts | 5 + .../cb-third-party-lib/ts/example-config.json | 3 + .../cb-third-party-lib/ts/index.html | 32 +++ .../cb-third-party-lib/ts/rollup-config.js | 23 ++ .../cb-third-party-lib/ts/tsconfig-aot.json | 26 ++ .../ts/tsconfig.json | 3 +- public/docs/ts/latest/cookbook/_data.json | 5 + .../ts/latest/cookbook/third-party-lib.jade | 247 ++++++++++++++++++ .../third-party-lib/third-party-lib.png | Bin 0 -> 58016 bytes 30 files changed, 726 insertions(+), 3 deletions(-) create mode 100644 public/docs/_examples/cb-third-party-lib/.gitignore create mode 100644 public/docs/_examples/cb-third-party-lib/e2e-spec.ts create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.css create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.html create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.ts create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.module.ts create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/hero.ts create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/index.ts create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/package.json create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/publish.js create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json create mode 100644 public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/app/main.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/example-config.json create mode 100644 public/docs/_examples/cb-third-party-lib/ts/index.html create mode 100644 public/docs/_examples/cb-third-party-lib/ts/rollup-config.js create mode 100644 public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json create mode 100644 public/docs/ts/latest/cookbook/third-party-lib.jade create mode 100644 public/resources/images/cookbooks/third-party-lib/third-party-lib.png diff --git a/gulpfile.js b/gulpfile.js index daf7dadf7e..ef893868d6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -51,6 +51,8 @@ var regularPlunker = require(path.resolve(TOOLS_PATH, 'plunker-builder/regularPl var embeddedPlunker = require(path.resolve(TOOLS_PATH, 'plunker-builder/embeddedPlunker')); var fsUtils = require(path.resolve(TOOLS_PATH, 'fs-utils/fsUtils')); +var publish = require(path.resolve(EXAMPLES_PATH + '/cb-third-party-lib/hero-profile/publish')); + const WWW = argv.page ? 'www-pages' : 'www' const isSilent = !!argv.silent; @@ -446,7 +448,7 @@ gulp.task('add-example-boilerplate', function() { fsUtils.addSymlink(realPath, linkPath); }); - return copyExampleBoilerplate(); + publish().then(() => copyExampleBoilerplate()); }); diff --git a/public/docs/_examples/_boilerplate/package.json b/public/docs/_examples/_boilerplate/package.json index 2e4bc19f91..d7866e6665 100644 --- a/public/docs/_examples/_boilerplate/package.json +++ b/public/docs/_examples/_boilerplate/package.json @@ -25,6 +25,7 @@ "build:cli": "ng build --no-progress", "serve:cli": "http-server dist/", "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js", + "build:aot:jit": "npm run build:aot && npm run tsc", "serve:aot": "lite-server -c bs-config.aot.json", "start:webpack": "webpack-dev-server --inline --progress --port 8080", "test:webpack": "karma start karma.webpack.conf.js", diff --git a/public/docs/_examples/_boilerplate/src/systemjs.config.js b/public/docs/_examples/_boilerplate/src/systemjs.config.js index ea7a3879ac..6d062ef918 100644 --- a/public/docs/_examples/_boilerplate/src/systemjs.config.js +++ b/public/docs/_examples/_boilerplate/src/systemjs.config.js @@ -31,7 +31,8 @@ // other libraries 'rxjs': 'npm:rxjs', - 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js', + 'hero-profile': 'npm:hero-profile/bundles/hero-profile.umd.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { diff --git a/public/docs/_examples/cb-third-party-lib/.gitignore b/public/docs/_examples/cb-third-party-lib/.gitignore new file mode 100644 index 0000000000..b8c17ad953 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/.gitignore @@ -0,0 +1,9 @@ +**/*.ngfactory.ts +**/*.metadata.json +**/*.css.shim.ts +*.js +!/hero-profile/rollup-config.js +!/hero-profile/publish.js +!/hero-profile/inline-resources.js +!/hero-profile/package.json +!ts/rollup-config.js \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/e2e-spec.ts b/public/docs/_examples/cb-third-party-lib/e2e-spec.ts new file mode 100644 index 0000000000..1bcc69f45d --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/e2e-spec.ts @@ -0,0 +1,22 @@ +'use strict'; // necessary for es6 output in node + +import { browser, element, by } from 'protractor'; + +describe('Third Party Lib Cookbook', function () { + + let expectedMsgAoT = 'Library consumed by AoT application'; + let expectedMsgJiT = 'Library consumed by JiT application'; + + beforeEach(function () { + browser.get(''); + }); + + it(`should load AoT compiled version`, function () { + expect(element(by.css('.aot')).getText()).toEqual(expectedMsgAoT); + }); + + it('should load JiT compiled version', function () { + expect(element(by.css('.jit')).getText()).toEqual(expectedMsgJiT); + }); + +}); diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.css b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.css new file mode 100644 index 0000000000..9f906ea720 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.css @@ -0,0 +1,6 @@ +/*#docregion*/ +.bio { + border: 1px solid black; + padding: 10px; + width: 300px; +} \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.html b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.html new file mode 100644 index 0000000000..3b7ef9c2c2 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.html @@ -0,0 +1,7 @@ + +
+

Featured Hero

+ +

{{hero.name}}

+
{{hero.bio}}
+
\ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.ts new file mode 100644 index 0000000000..82c451d017 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.ts @@ -0,0 +1,14 @@ +// #docregion +import { Component, Input } from '@angular/core'; + +import { Hero } from './hero'; + +@Component({ + moduleId: module.id, + selector: 'hero-profile', + templateUrl: 'hero-profile.component.html', + styleUrls: ['hero-profile.component.css'] +}) +export class HeroProfileComponent { + @Input() hero: Hero; +} diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.module.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.module.ts new file mode 100644 index 0000000000..692bdd6806 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.module.ts @@ -0,0 +1,12 @@ +// #docregion +import { NgModule } from '@angular/core'; + +import { HeroProfileComponent } from './hero-profile.component'; + +@NgModule({ + declarations: [HeroProfileComponent], + exports: [HeroProfileComponent] +}) +export class HeroProfileModule { + +} diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/hero.ts new file mode 100644 index 0000000000..09d04629f5 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/hero.ts @@ -0,0 +1,4 @@ +// #docregion +export class Hero { + constructor(public name: string, public bio: string) {} +} diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/index.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/index.ts new file mode 100644 index 0000000000..70556487f5 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/index.ts @@ -0,0 +1,4 @@ +// #docregion +export { HeroProfileComponent } from './hero-profile.component'; +export { HeroProfileModule } from './hero-profile.module'; +export { Hero } from './hero'; diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js b/public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js new file mode 100644 index 0000000000..61b5d4b36e --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js @@ -0,0 +1,137 @@ +// #docregion +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const glob = require('glob'); + +/** + * Simple Promiseify function that takes a Node API and return a version that supports promises. + * We use promises instead of synchronized functions to make the process less I/O bound and + * faster. It also simplify the code. + */ +function promiseify(fn) { + return function() { + const args = [].slice.call(arguments, 0); + return new Promise((resolve, reject) => { + fn.apply(this, args.concat([function (err, value) { + if (err) { + reject(err); + } else { + resolve(value); + } + }])); + }); + }; +} + +const readFile = promiseify(fs.readFile); +const writeFile = promiseify(fs.writeFile); + + +function inlineResources(globs) { + if (typeof globs == 'string') { + globs = [globs]; + } + + /** + * For every argument, inline the templates and styles under it and write the new file. + */ + return Promise.all(globs.map(pattern => { + if (pattern.indexOf('*') < 0) { + // Argument is a directory target, add glob patterns to include every files. + pattern = path.join(pattern, '**', '*'); + } + + const files = glob.sync(pattern, {}) + .filter(name => /\.js$/.test(name)); // Matches only JavaScript files. + + // Generate all files content with inlined templates. + return Promise.all(files.map(filePath => { + return readFile(filePath, 'utf-8') + .then(content => inlineResourcesFromString(content, url => { + return path.join(path.dirname(filePath), url); + })) + .then(content => writeFile(filePath, content)) + .catch(err => { + console.error('An error occured: ', err); + }); + })); + })); +} + +/** + * Inline resources from a string content. + * @param content {string} The source file's content. + * @param urlResolver {Function} A resolver that takes a URL and return a path. + * @returns {string} The content with resources inlined. + */ +function inlineResourcesFromString(content, urlResolver) { + // Curry through the inlining functions. + return [ + inlineTemplate, + inlineStyle, + removeModuleId + ].reduce((content, fn) => fn(content, urlResolver), content); +} + +if (require.main === module) { + inlineResources(process.argv.slice(2)); +} + + +/** + * Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and + * replace with `template: ...` (with the content of the file included). + * @param content {string} The source file's content. + * @param urlResolver {Function} A resolver that takes a URL and return a path. + * @return {string} The content with all templates inlined. + */ +function inlineTemplate(content, urlResolver) { + return content.replace(/templateUrl:\s*'([^']+?\.html)'/g, function(m, templateUrl) { + const templateFile = urlResolver(templateUrl); + const templateContent = fs.readFileSync(templateFile, 'utf-8'); + const shortenedTemplate = templateContent + .replace(/([\n\r]\s*)+/gm, ' ') + .replace(/"/g, '\\"'); + return `template: "${shortenedTemplate}"`; + }); +} + + +/** + * Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and + * replace with `styles: [...]` (with the content of the file included). + * @param urlResolver {Function} A resolver that takes a URL and return a path. + * @param content {string} The source file's content. + * @return {string} The content with all styles inlined. + */ +function inlineStyle(content, urlResolver) { + return content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, function(m, styleUrls) { + const urls = eval(styleUrls); + return 'styles: [' + + urls.map(styleUrl => { + const styleFile = urlResolver(styleUrl); + const styleContent = fs.readFileSync(styleFile, 'utf-8'); + const shortenedStyle = styleContent + .replace(/([\n\r]\s*)+/gm, ' ') + .replace(/"/g, '\\"'); + return `"${shortenedStyle}"`; + }) + .join(',\n') + + ']'; + }); +} + + +/** + * Remove every mention of `moduleId: module.id`. + * @param content {string} The source file's content. + * @returns {string} The content with all moduleId: mentions removed. + */ +function removeModuleId(content) { + return content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, ''); +} + +module.exports = inlineResources; +module.exports.inlineResourcesFromString = inlineResourcesFromString; \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/package.json b/public/docs/_examples/cb-third-party-lib/hero-profile/package.json new file mode 100644 index 0000000000..467a117c77 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/package.json @@ -0,0 +1,14 @@ +{ + "name": "hero-profile", + "version": "0.0.1", + "main": "bundles/hero-profile.umd.js", + "module": "index.js", + "typings": "index.d.ts", + "author": "", + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/angular/angular.io/blob/master/LICENSE" + } + ] +} \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/publish.js b/public/docs/_examples/cb-third-party-lib/hero-profile/publish.js new file mode 100644 index 0000000000..ec370ec220 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/publish.js @@ -0,0 +1,59 @@ +// #docregion +function publish() { + var inlineResources = require('./inline-resources'); + + // AoT compile + var spawnNgc = require( 'child_process' ).spawnSync; + var ngc = spawnNgc('./public/docs/_examples/node_modules/.bin/ngc', ['-p', './public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json']); + + // Copy to node_modules + var fs = require('fs'); + var del = require('del'); + + var node_modules_root = './public/docs/_examples/node_modules/hero-profile/'; + + del.sync(node_modules_root, {force:true}); + + fs.mkdirSync(node_modules_root); + fs.mkdirSync(node_modules_root + 'bundles'); + + var aotFiles = [ + 'hero-profile.component.html', + 'hero-profile.component.css', + + 'hero-profile.component.d.ts', + 'hero-profile.module.d.ts', + 'hero.d.ts', + 'index.d.ts', + + 'hero-profile.component.js', + 'hero-profile.module.js', + 'hero.js', + 'index.js', + + 'index.metadata.json', + 'hero-profile.module.metadata.json', + 'hero-profile.component.metadata.json', + + 'package.json' + ] + + aotFiles.map(function(f) { + var path = f.split('/'); + var release = node_modules_root + path[path.length-1]; + fs.createReadStream('./public/docs/_examples/cb-third-party-lib/hero-profile/' + f).pipe(fs.createWriteStream(release)); + }); + + return inlineResources('./public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.*').then(function(){ + + // Create umd bundle + var spawnRollup = require( 'child_process' ).spawnSync; + var rollup = spawnRollup('./public/docs/_examples/node_modules/.bin/rollup', ['-c', './public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js']); + + var umd = './public/docs/_examples/cb-third-party-lib/hero-profile/bundles/hero-profile.umd.js'; + fs.createReadStream(umd).pipe(fs.createWriteStream(node_modules_root + 'bundles/hero-profile.umd.js')); + + }); +} + +module.exports = publish; diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js b/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js new file mode 100644 index 0000000000..2e02133362 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js @@ -0,0 +1,10 @@ +// #docregion +export default { + entry: './public/docs/_examples/cb-third-party-lib/hero-profile/index.js', + dest: './public/docs/_examples/cb-third-party-lib/hero-profile/bundles/hero-profile.umd.js', + format: 'umd', + moduleName: 'ng.heroProfile', + globals: { + '@angular/core': 'ng.core' + } +} \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json b/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json new file mode 100644 index 0000000000..5e3cca7517 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "sourceMap": true, + "declaration": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "noImplicitAny": true, + "typeRoots": [ + "../../node_modules/@types/" + ] + }, + "files": [ + "index.ts" + ], + "angularCompilerOptions": { + "genDir": "aot", + "skipMetadataEmit" : false + } +} \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts b/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts new file mode 100644 index 0000000000..6fce027213 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; + +import { Hero } from 'hero-profile'; + +@Component({ + selector: 'my-aot-app', + template: `
+

Library consumed by AoT application

+ +
` +}) +export class AppComponent { + hero = new Hero('Bombasto', 'Bombastic at times'); +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts b/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts new file mode 100644 index 0000000000..bf8970d57c --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { AppComponent } from './app.component'; +import { HeroProfileModule } from 'hero-profile'; + +@NgModule({ + imports: [HeroProfileModule, BrowserModule], + declarations: [AppComponent], + bootstrap: [AppComponent] +}) +export class AppModule { +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts b/public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts new file mode 100644 index 0000000000..ada092b67b --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts @@ -0,0 +1,3 @@ +import { platformBrowser } from '@angular/platform-browser'; +import { AppModuleNgFactory } from '../aot/app-aot/app.module.ngfactory'; +platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts b/public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts new file mode 100644 index 0000000000..3a7dadfe65 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; + +import { Hero } from 'hero-profile'; + +@Component({ + selector: 'my-jit-app', + template: `
+

Library consumed by JiT application

+ +
` +}) +export class AppComponent { + hero = new Hero('Magneta', 'Brave as they come'); +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts b/public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts new file mode 100644 index 0000000000..bf8970d57c --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { AppComponent } from './app.component'; +import { HeroProfileModule } from 'hero-profile'; + +@NgModule({ + imports: [HeroProfileModule, BrowserModule], + declarations: [AppComponent], + bootstrap: [AppComponent] +}) +export class AppModule { +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app/main.ts b/public/docs/_examples/cb-third-party-lib/ts/app/main.ts new file mode 100644 index 0000000000..4acf5de663 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/app/main.ts @@ -0,0 +1,5 @@ +// #docregion +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app.module'; + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/public/docs/_examples/cb-third-party-lib/ts/example-config.json b/public/docs/_examples/cb-third-party-lib/ts/example-config.json new file mode 100644 index 0000000000..85a9a43ad0 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/example-config.json @@ -0,0 +1,3 @@ +{ + "build": "build:aot:jit" +} \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/ts/index.html b/public/docs/_examples/cb-third-party-lib/ts/index.html new file mode 100644 index 0000000000..52aaa60641 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/index.html @@ -0,0 +1,32 @@ + + + + + + Third Party Lib + + + + + + + + + + + + + + + + + Loading app... + + Loading app... + + + + + diff --git a/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js b/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js new file mode 100644 index 0000000000..603d33408f --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js @@ -0,0 +1,23 @@ +// #docregion +import rollup from 'rollup' +import nodeResolve from 'rollup-plugin-node-resolve' +import commonjs from 'rollup-plugin-commonjs'; +import uglify from 'rollup-plugin-uglify' + +//paths are relative to the execution path +export default { + entry: 'app-aot/main-aot.js', + dest: 'dist/build.js', // output a single application bundle + sourceMap: true, + sourceMapFile: 'dist/build.js.map', + format: 'iife', + plugins: [ + // #docregion nodeResolve + nodeResolve({jsnext: true, module: true}), + // #enddocregion nodeResolve + commonjs({ + include: ['node_modules/rxjs/**'] + }), + uglify() + ] +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json b/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json new file mode 100644 index 0000000000..85ab089d23 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true, + "typeRoots": [ + "../../node_modules/@types/" + ] + }, + + "files": [ + "app-aot/app.module.ts", + "app-aot/main-aot.ts" + ], + + "angularCompilerOptions": { + "genDir": "aot", + "skipMetadataEmit" : true + } +} diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json index f267800f14..2dfccc22d1 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json @@ -16,6 +16,7 @@ "compileOnSave": true, "exclude": [ "node_modules/*", - "**/*-aot.ts" + "**/*-aot.ts", + "app-aot" ] } diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json index 1aed135fa8..1ba6ac01d3 100644 --- a/public/docs/ts/latest/cookbook/_data.json +++ b/public/docs/ts/latest/cookbook/_data.json @@ -56,6 +56,11 @@ "intro": "Setting the document or window title using the Title service." }, + "third-party-lib": { + "title": "Third Party Library", + "intro": "Create a third party library with support for AoT, JiT and Tree Shaking" + }, + "ts-to-js": { "title": "TypeScript to JavaScript", "intro": "Convert Angular TypeScript examples into ES6 and ES5 JavaScript." diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade new file mode 100644 index 0000000000..1bbaee8c06 --- /dev/null +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -0,0 +1,247 @@ +include ../_util-fns + +:marked + Traditionally, third party JavaScript libraries have been published in the form of a single minified JavaScript file. + Consumers of the library have then included the minified JavaScript file, "as is", somewhere on the page using a `script` tag. + + Modern web development has changed this process. Instead of publishing a "one size fits all" bundle, developers want to only include the parts of the library they actually need. + + This cookbook will show how to publish a third party library in a way that makes it possible to take advantage of techniques like Ahead of Time Compilation (AoT) and Tree shaking. + + +:marked + ## Table of contents + + [Creating a Third Party Library](#third-party-lib) + + [Supporting AoT](#aot) + + [Preparing the library for Tree Shaking](#tree-shaking) + + [Supporting JiT](#jit) + + [Publish](#publish) + + [Integrate with Application](#integrate-with-app) + + [Final Application](#final-app) + +.l-main-section + +:marked + ## Creating a Third Party Library + + This cookbook will show how to create a simple Hero-Profile library and publish it with support for AoT compilation and Tree Shaking. + + A version of the library intended for JiT compiled applications will also be included. + + The code for the Hero-Profile library can be found below. + + To support both AoT and JiT compilation there are two different tsconfig files. + + `tsconfig.json` for JiT compilation and `tsconfig-aot.json` for AoT compilation. + ++makeTabs( + `cb-third-party-lib/hero-profile/hero-profile.module.ts, + cb-third-party-lib/hero-profile/tsconfig-aot.json, + cb-third-party-lib/ts/tsconfig.json, + cb-third-party-lib/hero-profile/hero-profile.component.html, + cb-third-party-lib/hero-profile/hero-profile.component.ts, + cb-third-party-lib/hero-profile/hero-profile.component.css, + cb-third-party-lib/hero-profile/hero.ts, + cb-third-party-lib/hero-profile/package.json`, + null, + `hero-profile.module.ts, + tsconfig-aot.json, + tsconfig.json, + hero-profile.component.html, + hero-profile.component.ts, + hero-profile.component.css, + hero.ts, + package.json` +)(format='.') + +.l-main-section + +:marked + ## Supporting AoT + + AoT plays an important role in optimizing Angular applications. It's therefore important that third party libraries be published in a format compatible with AoT compilation. Otherwise it will not be possible to include the library in an AoT compiled application. + + Only code written in TypeScript can be AoT compiled. + + Before publishing the library must first be compiled using the `ngc` compiler. + + `ngc` extends the `tsc` compiler by adding extensions to support AoT compilation in addition to regular TypeScript compilation. + +:marked + AoT compilation outputs three files that must be included in order to be compatible with AoT. + + *Transpiled JavaScript* + + As usual the original TypeScript is transpiled to regular JavaScript. + + *Typings files* + + JavaScript has no way of representing typings. In order to preserve the original typings, `ngc` will generate .d.ts typings files. + + *Meta Data JSON files* + + `ngc` outputs a metadata.json file for every `Component` and `NgModule`. These meta data files represent the information in the original `NgModule` and `Component` decorators. + + The meta data may reference external templates or css files. These external files must be included with the library. + + ### NgFactories + + `ngc` generates a series of files with an `.ngfactory` suffix as well. These files represent the AoT compiled source, but should not be included with the published library. + + Instead the `ngc` compiler in the consuming application will generate `.ngfactory` files based on the JavaScript, Typings and meta data shipped with the library. + + ### Why not publish TypeScript? + + Why not ship TypeScript source instead? After all the library will be part of another TypeScript compilation step when the library is imported by the consuming application? + + Generally it's discouraged to ship TypeScript with third party libraries. It would require the consumer to replicate the complete build environment of the library. Not only typings, but potentially a specific version of `ngc` as well. + + Publishing plain JavaScript with typings and meta data allows the consuming application to remain agnostic of the library's build environment. + + +:marked + ## Preparing the library for Tree Shaking + + In addition to supporting AoT, the library code should also be "Tree Shakable". + + Thee Shakers work best with `ES2015` JavaScript. + + `ES2015` `import` and `export` statements make it easier to statically analyse the code to determine which modules are in use by the application. + + By setting the `module` attribute in `tsconfig-aot.json` to `es2015`, the transpiled JavaScript will use `ES2015` modules. + + The library is made up of several independent files. Bundler frameworks like `Rollup` and `Webpack` need a way to determine the entry point to the module. In this example the entry point is `index.js`, the transpiled version of the index.ts TypeScript barrel. + + The entry point to the module is configured using the `module` attribute in `package.json`. In this case `module` is defined as `"module": "index.js"`. + + +:marked + ## Supporting JiT + + AoT compiled code is the prefered format for production builds, but due to the long compilation time, it may not be practical to use AoT during development. + + To create a more flexible developer experience, a JiT compatible build of the library should be published as well. The format of the JiT bundle is `umd`, which stands for Universal Module Definition. Shipping the bundle as `umd` ensures compatability with most common module loading formats. + + The `umd` bundle will ship as a single file containing the JavaScript and inlined versions of any external templates or css. + + The path to the `umd` file identified in package.json as `"main": "bundles/hero-profile.umd.js"` + + In `tsconfig.json` the module for the `umd` bundle is specified as `commonjs`, not `es2015`. This is done to ensure that the bundle can be executed "as is", without further transpilation or bundling. + + To generate the bundle we will be using a framework called `Rollup`. + + The JiT build assumes the following Rollup and TypeScript configuration. + ++makeTabs( + `cb-third-party-lib/hero-profile/rollup-config.js, + cb-third-party-lib/ts/tsconfig.json`, + null, + `rollup-config.js, + tsconfig.json` +)(format='.') +:marked + Generate the `umd` bundle by running `node_modules/.bin/rollup -c rollup-config.js`. + + +:marked + ## Publish + +:marked + `Rollup` wil create the `umd` bundle, but but prior to bundling, all external templates or css files must be inlined. + + There are a few options for how to do inlining. This cookbook uses an approach borrowed from `Angular Material 2`. + + The idea is to create a node script that will walk the component code and replace `templateUrl` and `styleUrls` references with inlined html and css. + + Additionally the script will remove references to `module.id` since it's no longer needed after templates and css have been inlined. + + Angular ships with its own set of `umd` bundles. These bundles can be referenced by Rollup when generating the `umd` bundle. + + In this example there is a dependency on `@angular/core`. + + By listing `@angular/core` as a `global` in the configuration, `Rollup` will point to the `@angular/core` umd bundle. + + Normally third party libraries will be published to `npm`. This cookbook simulates publishing by executing all required steps in the `publish.js` script. + + `publish.js` will do the following: + + 1) AoT compile the Hero-Profile library by running `node_modules/.bin/ngc -p tsconfig-aot.json` + + 2) Inline templates and css using the `inline-resources.js` script + + 3) Create an `umd` bundle by running `node_modules/.bin/rollup -c rollup-config.js` + ++makeTabs( + `cb-third-party-lib/hero-profile/publish.js, + cb-third-party-lib/hero-profile/inline-resources.js`, + null, + `publish.js, + inline-resources.js` +)(format='.') + +.l-main-section + +:marked + ## Integrate with Application + + The library is now ready to be integrated with either AoT compiled applications or JiT compiled applications. The following sections describes how to configure both. + + For the purposes of this demo the JiT and the AoT versions are loaded using the same index.html page. + + ### AoT + + AoT compiled applications will integrate the library in the compilation of the application as a whole. + + As in the AoT compilation Cookbook `ngc` is used in combination with `Rollup` to AoT and Tree Shake the application. + + Run the command `ngc -p tsconfig-aot.json && rollup -c rollup-config.js` to execute the combined steps of AoT compilation and Tree Shaking. + + `tsconfig-aot.json` and `rollup-config.js` contain the necessary configuration. + ++makeTabs( + `cb-third-party-lib/ts/rollup-config.js, + cb-third-party-lib/ts/tsconfig-aot.json`, + null, + `rollup-config.js, + tsconfig-aot.json` +)(format='.') + +:marked + Inside `rollup-config` there is a `nodeResolve` section. This is where the `module` setting from `package.json` comes into play. + + `nodeResolve` will look for either `module` or `jsnext` in `package.json` to determine how to bundle external libraries. + ++makeExample('cb-third-party-lib/ts/rollup-config.js', 'nodeResolve', 'rollup-config.js')(format=".") + +:marked + The combined output of `ngc` and `Rollup` is a single `build.js` JavaScript file. + + `build.js` contains the entire application including all Angular dependencies and the third party Hero-Profile library. + + To run the application in AoT mode, include `build.js` as a script tag and the `my-aot-app` root level component tag in `index.html` + + ### JiT + + JiT applications load the `umd` bundle using `SystemJS`. This requires a minor tweak to `systemjs.config.js` to register the `umd` bundle with `SystemJS`. + + Simply add `'hero-profile': 'npm:hero-profile/bundles/hero-profile.umd.js'` to the map section of `systemjs.config.js`. + +.l-main-section + +:marked + ## Final Application + + If you have cloned the `Angular.io` repo, all the steps described in this cookbook can be executed by running the following command: + + `gulp add-example-boilerplate && npm run build:aot:jit && npm run lite` + + After loading both the JiT and AoT versions of the library the final application looks like this: +figure.image-display + img(src="/resources/images/cookbooks/third-party-lib/third-party-lib.png" alt="Third-Party-Library") \ No newline at end of file diff --git a/public/resources/images/cookbooks/third-party-lib/third-party-lib.png b/public/resources/images/cookbooks/third-party-lib/third-party-lib.png new file mode 100644 index 0000000000000000000000000000000000000000..525a27b88d696a4f8b096dae454c2e03a2c1f8a4 GIT binary patch literal 58016 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 literal 0 HcmV?d00001 From 38a90003a7f5adae72931d1fe4998852e940fd27 Mon Sep 17 00:00:00 2001 From: Torgeir Helgevold Date: Mon, 7 Nov 2016 18:26:57 -0500 Subject: [PATCH 02/31] addressing PR review items --- .../docs/ts/latest/cookbook/third-party-lib.jade | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 1bbaee8c06..68200ca119 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -1,12 +1,12 @@ include ../_util-fns :marked - Traditionally, third party JavaScript libraries have been published in the form of a single minified JavaScript file. - Consumers of the library have then included the minified JavaScript file, "as is", somewhere on the page using a `script` tag. + Traditionally, third party JavaScript libraries have been published in the form of a single JavaScript file. + Consumers of the library have then included the library, "as is", somewhere on the page using a `script` tag. Modern web development has changed this process. Instead of publishing a "one size fits all" bundle, developers want to only include the parts of the library they actually need. - This cookbook will show how to publish a third party library in a way that makes it possible to take advantage of techniques like Ahead of Time Compilation (AoT) and Tree shaking. + This cookbook shows how to publish a third party library in a way that makes it possible to take advantage of techniques like Ahead of Time Compilation (AoT) and Tree Shaking. :marked @@ -31,7 +31,7 @@ include ../_util-fns :marked ## Creating a Third Party Library - This cookbook will show how to create a simple Hero-Profile library and publish it with support for AoT compilation and Tree Shaking. + This cookbook shows how to create a simple Hero-Profile library and publish it with support for AoT compilation and Tree Shaking. A version of the library intended for JiT compiled applications will also be included. @@ -111,7 +111,7 @@ include ../_util-fns In addition to supporting AoT, the library code should also be "Tree Shakable". - Thee Shakers work best with `ES2015` JavaScript. + Tree Shakers work best with `ES2015` JavaScript. `ES2015` `import` and `export` statements make it easier to statically analyse the code to determine which modules are in use by the application. @@ -127,7 +127,7 @@ include ../_util-fns AoT compiled code is the prefered format for production builds, but due to the long compilation time, it may not be practical to use AoT during development. - To create a more flexible developer experience, a JiT compatible build of the library should be published as well. The format of the JiT bundle is `umd`, which stands for Universal Module Definition. Shipping the bundle as `umd` ensures compatability with most common module loading formats. + To create a more flexible developer experience, a JiT compatible build of the library should be published as well. The format of the JiT bundle is `umd`, which stands for Universal Module Definition. Shipping the bundle as `umd` ensures compatibility with most common module loading formats. The `umd` bundle will ship as a single file containing the JavaScript and inlined versions of any external templates or css. @@ -154,7 +154,7 @@ include ../_util-fns ## Publish :marked - `Rollup` wil create the `umd` bundle, but but prior to bundling, all external templates or css files must be inlined. + `Rollup` outputs the `umd` bundle, but prior to bundling, all external templates or css files must be inlined. There are a few options for how to do inlining. This cookbook uses an approach borrowed from `Angular Material 2`. From 21bc5eb2282207a51baec5ca64acd42935a1b94c Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Tue, 28 Feb 2017 10:29:31 +0000 Subject: [PATCH 03/31] minor copy-edits --- public/docs/ts/latest/cookbook/third-party-lib.jade | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 68200ca119..fde94b7062 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -83,7 +83,7 @@ include ../_util-fns *Typings files* - JavaScript has no way of representing typings. In order to preserve the original typings, `ngc` will generate .d.ts typings files. + JavaScript has no way of representing typings. In order to preserve the original typings, `ngc` will generate `.d.ts` typings files. *Meta Data JSON files* @@ -135,7 +135,7 @@ include ../_util-fns In `tsconfig.json` the module for the `umd` bundle is specified as `commonjs`, not `es2015`. This is done to ensure that the bundle can be executed "as is", without further transpilation or bundling. - To generate the bundle we will be using a framework called `Rollup`. + To generate the bundle you will be using a framework called `Rollup`. The JiT build assumes the following Rollup and TypeScript configuration. @@ -244,4 +244,4 @@ include ../_util-fns After loading both the JiT and AoT versions of the library the final application looks like this: figure.image-display - img(src="/resources/images/cookbooks/third-party-lib/third-party-lib.png" alt="Third-Party-Library") \ No newline at end of file + img(src="/resources/images/cookbooks/third-party-lib/third-party-lib.png" alt="Third-Party-Library") From e1423e71d44796baba5e7cb78644db179631fd60 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Thu, 2 Mar 2017 17:25:34 +0000 Subject: [PATCH 04/31] update example --- gulpfile.js | 4 +- .../hero-profile/.gitignore | 8 + .../hero-profile/.npmignore | 9 ++ .../cb-third-party-lib/hero-profile/index.ts | 4 - .../hero-profile/inline-resources.js | 137 ------------------ .../hero-profile/package.json | 38 +++-- .../hero-profile/publish.js | 59 -------- .../hero-profile/rollup-config.js | 15 +- .../hero-profile/src/index.ts | 4 + .../{ => src/lib}/hero-profile.component.css | 0 .../{ => src/lib}/hero-profile.component.html | 0 .../{ => src/lib}/hero-profile.component.ts | 0 .../{ => src/lib}/hero-profile.module.ts | 0 .../hero-profile/{ => src/lib}/hero.ts | 0 .../{tsconfig-aot.json => tsconfig.json} | 15 +- .../cb-third-party-lib/ts/.gitignore | 8 + .../cb-third-party-lib/ts/aot/index.html | 22 +++ .../cb-third-party-lib/ts/aot/styles.css | 116 +++++++++++++++ .../ts/app-aot/app.component.ts | 14 -- .../ts/app-aot/app.module.ts | 13 -- .../ts/app/app.component.ts | 14 -- .../cb-third-party-lib/ts/bs-config.aot.json | 14 ++ .../cb-third-party-lib/ts/rollup-config.js | 17 ++- .../ts/src/app/app.component.ts | 16 ++ .../ts/{ => src}/app/app.module.ts | 3 +- .../ts/{ => src}/index.html | 20 +-- .../ts/{app-aot => src}/main-aot.ts | 5 +- .../ts/{app => src}/main.ts | 2 +- .../cb-third-party-lib/ts/tsconfig-aot.json | 6 +- 29 files changed, 273 insertions(+), 290 deletions(-) create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/.gitignore create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/.npmignore delete mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/index.ts delete mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js delete mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/publish.js create mode 100644 public/docs/_examples/cb-third-party-lib/hero-profile/src/index.ts rename public/docs/_examples/cb-third-party-lib/hero-profile/{ => src/lib}/hero-profile.component.css (100%) rename public/docs/_examples/cb-third-party-lib/hero-profile/{ => src/lib}/hero-profile.component.html (100%) rename public/docs/_examples/cb-third-party-lib/hero-profile/{ => src/lib}/hero-profile.component.ts (100%) rename public/docs/_examples/cb-third-party-lib/hero-profile/{ => src/lib}/hero-profile.module.ts (100%) rename public/docs/_examples/cb-third-party-lib/hero-profile/{ => src/lib}/hero.ts (100%) rename public/docs/_examples/cb-third-party-lib/hero-profile/{tsconfig-aot.json => tsconfig.json} (67%) create mode 100644 public/docs/_examples/cb-third-party-lib/ts/.gitignore create mode 100644 public/docs/_examples/cb-third-party-lib/ts/aot/index.html create mode 100644 public/docs/_examples/cb-third-party-lib/ts/aot/styles.css delete mode 100644 public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts delete mode 100644 public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts delete mode 100644 public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts create mode 100644 public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json create mode 100644 public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts rename public/docs/_examples/cb-third-party-lib/ts/{ => src}/app/app.module.ts (92%) rename public/docs/_examples/cb-third-party-lib/ts/{ => src}/index.html (56%) rename public/docs/_examples/cb-third-party-lib/ts/{app-aot => src}/main-aot.ts (62%) rename public/docs/_examples/cb-third-party-lib/ts/{app => src}/main.ts (75%) diff --git a/gulpfile.js b/gulpfile.js index ef893868d6..daf7dadf7e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -51,8 +51,6 @@ var regularPlunker = require(path.resolve(TOOLS_PATH, 'plunker-builder/regularPl var embeddedPlunker = require(path.resolve(TOOLS_PATH, 'plunker-builder/embeddedPlunker')); var fsUtils = require(path.resolve(TOOLS_PATH, 'fs-utils/fsUtils')); -var publish = require(path.resolve(EXAMPLES_PATH + '/cb-third-party-lib/hero-profile/publish')); - const WWW = argv.page ? 'www-pages' : 'www' const isSilent = !!argv.silent; @@ -448,7 +446,7 @@ gulp.task('add-example-boilerplate', function() { fsUtils.addSymlink(realPath, linkPath); }); - publish().then(() => copyExampleBoilerplate()); + return copyExampleBoilerplate(); }); diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/.gitignore b/public/docs/_examples/cb-third-party-lib/hero-profile/.gitignore new file mode 100644 index 0000000000..5cd429260d --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/.gitignore @@ -0,0 +1,8 @@ +bundles/ +dist/ +node_modules/ +src/**/*.ngfactory.ts +src/**/*.ngsummary.json +src/**/*.ngstyle.ts +debug.log +npm-debug.log diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/.npmignore b/public/docs/_examples/cb-third-party-lib/hero-profile/.npmignore new file mode 100644 index 0000000000..2ce13e072f --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/.npmignore @@ -0,0 +1,9 @@ +# Ignore eveything by default. +/* + +# Only publish these files/folders: +!bundles/ +!dist/ +!LICENSE +!package.json +!README.md diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/index.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/index.ts deleted file mode 100644 index 70556487f5..0000000000 --- a/public/docs/_examples/cb-third-party-lib/hero-profile/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// #docregion -export { HeroProfileComponent } from './hero-profile.component'; -export { HeroProfileModule } from './hero-profile.module'; -export { Hero } from './hero'; diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js b/public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js deleted file mode 100644 index 61b5d4b36e..0000000000 --- a/public/docs/_examples/cb-third-party-lib/hero-profile/inline-resources.js +++ /dev/null @@ -1,137 +0,0 @@ -// #docregion -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const glob = require('glob'); - -/** - * Simple Promiseify function that takes a Node API and return a version that supports promises. - * We use promises instead of synchronized functions to make the process less I/O bound and - * faster. It also simplify the code. - */ -function promiseify(fn) { - return function() { - const args = [].slice.call(arguments, 0); - return new Promise((resolve, reject) => { - fn.apply(this, args.concat([function (err, value) { - if (err) { - reject(err); - } else { - resolve(value); - } - }])); - }); - }; -} - -const readFile = promiseify(fs.readFile); -const writeFile = promiseify(fs.writeFile); - - -function inlineResources(globs) { - if (typeof globs == 'string') { - globs = [globs]; - } - - /** - * For every argument, inline the templates and styles under it and write the new file. - */ - return Promise.all(globs.map(pattern => { - if (pattern.indexOf('*') < 0) { - // Argument is a directory target, add glob patterns to include every files. - pattern = path.join(pattern, '**', '*'); - } - - const files = glob.sync(pattern, {}) - .filter(name => /\.js$/.test(name)); // Matches only JavaScript files. - - // Generate all files content with inlined templates. - return Promise.all(files.map(filePath => { - return readFile(filePath, 'utf-8') - .then(content => inlineResourcesFromString(content, url => { - return path.join(path.dirname(filePath), url); - })) - .then(content => writeFile(filePath, content)) - .catch(err => { - console.error('An error occured: ', err); - }); - })); - })); -} - -/** - * Inline resources from a string content. - * @param content {string} The source file's content. - * @param urlResolver {Function} A resolver that takes a URL and return a path. - * @returns {string} The content with resources inlined. - */ -function inlineResourcesFromString(content, urlResolver) { - // Curry through the inlining functions. - return [ - inlineTemplate, - inlineStyle, - removeModuleId - ].reduce((content, fn) => fn(content, urlResolver), content); -} - -if (require.main === module) { - inlineResources(process.argv.slice(2)); -} - - -/** - * Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and - * replace with `template: ...` (with the content of the file included). - * @param content {string} The source file's content. - * @param urlResolver {Function} A resolver that takes a URL and return a path. - * @return {string} The content with all templates inlined. - */ -function inlineTemplate(content, urlResolver) { - return content.replace(/templateUrl:\s*'([^']+?\.html)'/g, function(m, templateUrl) { - const templateFile = urlResolver(templateUrl); - const templateContent = fs.readFileSync(templateFile, 'utf-8'); - const shortenedTemplate = templateContent - .replace(/([\n\r]\s*)+/gm, ' ') - .replace(/"/g, '\\"'); - return `template: "${shortenedTemplate}"`; - }); -} - - -/** - * Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and - * replace with `styles: [...]` (with the content of the file included). - * @param urlResolver {Function} A resolver that takes a URL and return a path. - * @param content {string} The source file's content. - * @return {string} The content with all styles inlined. - */ -function inlineStyle(content, urlResolver) { - return content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, function(m, styleUrls) { - const urls = eval(styleUrls); - return 'styles: [' - + urls.map(styleUrl => { - const styleFile = urlResolver(styleUrl); - const styleContent = fs.readFileSync(styleFile, 'utf-8'); - const shortenedStyle = styleContent - .replace(/([\n\r]\s*)+/gm, ' ') - .replace(/"/g, '\\"'); - return `"${shortenedStyle}"`; - }) - .join(',\n') - + ']'; - }); -} - - -/** - * Remove every mention of `moduleId: module.id`. - * @param content {string} The source file's content. - * @returns {string} The content with all moduleId: mentions removed. - */ -function removeModuleId(content) { - return content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, ''); -} - -module.exports = inlineResources; -module.exports.inlineResourcesFromString = inlineResourcesFromString; \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/package.json b/public/docs/_examples/cb-third-party-lib/hero-profile/package.json index 467a117c77..4f0bf534cf 100644 --- a/public/docs/_examples/cb-third-party-lib/hero-profile/package.json +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/package.json @@ -1,14 +1,32 @@ { "name": "hero-profile", - "version": "0.0.1", + "version": "1.0.0", + "description": "", "main": "bundles/hero-profile.umd.js", - "module": "index.js", - "typings": "index.d.ts", + "module": "dist/index.js", + "typings": "dist/index.d.ts", "author": "", - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/angular/angular.io/blob/master/LICENSE" - } - ] -} \ No newline at end of file + "license": "MIT", + "repository": {}, + "scripts": { + "prebuild": "npm run clean", + "build": "ngc && node copy-dist-files.js && rollup -c rollup-config.js", + "clean": "rimraf bundles dist dist-spec src/**/*.ngfactory.ts src/**/*.ngsummary.json src/**/*.ngstyle.ts" + }, + "peerDependencies": { + "@angular/core": ">=2.0.0 <5.0.0 || >=4.0.0-beta <5.0.0" + }, + "devDependencies": { + "@angular/compiler": "^2.4.8", + "@angular/compiler-cli": "^2.4.8", + "@angular/core": "^2.4.8", + "@types/node": "^7.0.5", + "glob": "^7.1.1", + "rimraf": "^2.6.1", + "rollup": "^0.36.0", + "rollup-plugin-angular-inline": "^1.0.0", + "rxjs": "^5.0.1", + "typescript": "~2.0.10", + "zone.js": "^0.7.2" + } +} diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/publish.js b/public/docs/_examples/cb-third-party-lib/hero-profile/publish.js deleted file mode 100644 index ec370ec220..0000000000 --- a/public/docs/_examples/cb-third-party-lib/hero-profile/publish.js +++ /dev/null @@ -1,59 +0,0 @@ -// #docregion -function publish() { - var inlineResources = require('./inline-resources'); - - // AoT compile - var spawnNgc = require( 'child_process' ).spawnSync; - var ngc = spawnNgc('./public/docs/_examples/node_modules/.bin/ngc', ['-p', './public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json']); - - // Copy to node_modules - var fs = require('fs'); - var del = require('del'); - - var node_modules_root = './public/docs/_examples/node_modules/hero-profile/'; - - del.sync(node_modules_root, {force:true}); - - fs.mkdirSync(node_modules_root); - fs.mkdirSync(node_modules_root + 'bundles'); - - var aotFiles = [ - 'hero-profile.component.html', - 'hero-profile.component.css', - - 'hero-profile.component.d.ts', - 'hero-profile.module.d.ts', - 'hero.d.ts', - 'index.d.ts', - - 'hero-profile.component.js', - 'hero-profile.module.js', - 'hero.js', - 'index.js', - - 'index.metadata.json', - 'hero-profile.module.metadata.json', - 'hero-profile.component.metadata.json', - - 'package.json' - ] - - aotFiles.map(function(f) { - var path = f.split('/'); - var release = node_modules_root + path[path.length-1]; - fs.createReadStream('./public/docs/_examples/cb-third-party-lib/hero-profile/' + f).pipe(fs.createWriteStream(release)); - }); - - return inlineResources('./public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.*').then(function(){ - - // Create umd bundle - var spawnRollup = require( 'child_process' ).spawnSync; - var rollup = spawnRollup('./public/docs/_examples/node_modules/.bin/rollup', ['-c', './public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js']); - - var umd = './public/docs/_examples/cb-third-party-lib/hero-profile/bundles/hero-profile.umd.js'; - fs.createReadStream(umd).pipe(fs.createWriteStream(node_modules_root + 'bundles/hero-profile.umd.js')); - - }); -} - -module.exports = publish; diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js b/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js index 2e02133362..36cfff13d8 100644 --- a/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js @@ -1,10 +1,15 @@ // #docregion +import angularInline from 'rollup-plugin-angular-inline'; + export default { - entry: './public/docs/_examples/cb-third-party-lib/hero-profile/index.js', - dest: './public/docs/_examples/cb-third-party-lib/hero-profile/bundles/hero-profile.umd.js', + entry: './dist/index.js', + dest: './bundles/hero-profile.umd.js', format: 'umd', - moduleName: 'ng.heroProfile', + moduleName: 'heroProfile', globals: { '@angular/core': 'ng.core' - } -} \ No newline at end of file + }, + plugins: [ + angularInline({ include: './dist/**/*.component.js' }) + ] +} diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/src/index.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/src/index.ts new file mode 100644 index 0000000000..1ed133aaee --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/src/index.ts @@ -0,0 +1,4 @@ +// #docregion +export { HeroProfileComponent } from './lib/hero-profile.component'; +export { HeroProfileModule } from './lib/hero-profile.module'; +export { Hero } from './lib/hero'; diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.css b/public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.component.css similarity index 100% rename from public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.css rename to public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.component.css diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.html b/public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.component.html similarity index 100% rename from public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.html rename to public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.component.html diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.component.ts similarity index 100% rename from public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.ts rename to public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.component.ts diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.module.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.module.ts similarity index 100% rename from public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.module.ts rename to public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero-profile.module.ts diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/hero.ts b/public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero.ts similarity index 100% rename from public/docs/_examples/cb-third-party-lib/hero-profile/hero.ts rename to public/docs/_examples/cb-third-party-lib/hero-profile/src/lib/hero.ts diff --git a/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json b/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig.json similarity index 67% rename from public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json rename to public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig.json index 5e3cca7517..4c4d18f603 100644 --- a/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json +++ b/public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "outDir": "dist/", "target": "es5", "module": "es2015", "moduleResolution": "node", @@ -8,15 +9,13 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "noImplicitAny": true, - "typeRoots": [ - "../../node_modules/@types/" + "suppressImplicitAnyIndexErrors": true, + "lib": [ + "es2015", + "dom" ] }, - "files": [ - "index.ts" - ], "angularCompilerOptions": { - "genDir": "aot", - "skipMetadataEmit" : false + "skipMetadataEmit": false } -} \ No newline at end of file +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/.gitignore b/public/docs/_examples/cb-third-party-lib/ts/.gitignore new file mode 100644 index 0000000000..804879d44a --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/.gitignore @@ -0,0 +1,8 @@ +aot/**/*.ts +**/*.ngfactory.ts +**/*.ngsummary.json +**/*.metadata.json +**/*.js +dist +!app/tsconfig.json +!rollup-config.js diff --git a/public/docs/_examples/cb-third-party-lib/ts/aot/index.html b/public/docs/_examples/cb-third-party-lib/ts/aot/index.html new file mode 100644 index 0000000000..1a64ca8cac --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/aot/index.html @@ -0,0 +1,22 @@ + + + + + + Angular Tour of Heroes + + + + + + + + + + + + + Loading... + + + diff --git a/public/docs/_examples/cb-third-party-lib/ts/aot/styles.css b/public/docs/_examples/cb-third-party-lib/ts/aot/styles.css new file mode 100644 index 0000000000..d81835d0cd --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/aot/styles.css @@ -0,0 +1,116 @@ +/* #docregion , quickstart, toh */ +/* Master Styles */ +h1 { + color: #369; + font-family: Arial, Helvetica, sans-serif; + font-size: 250%; +} +h2, h3 { + color: #444; + font-family: Arial, Helvetica, sans-serif; + font-weight: lighter; +} +body { + margin: 2em; +} +/* #enddocregion quickstart */ +body, input[text], button { + color: #888; + font-family: Cambria, Georgia; +} +/* #enddocregion toh */ +a { + cursor: pointer; + cursor: hand; +} +button { + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + cursor: hand; +} +button:hover { + background-color: #cfd8dc; +} +button:disabled { + background-color: #eee; + color: #aaa; + cursor: auto; +} + +/* Navigation link styles */ +nav a { + padding: 5px 10px; + text-decoration: none; + margin-right: 10px; + margin-top: 10px; + display: inline-block; + background-color: #eee; + border-radius: 4px; +} +nav a:visited, a:link { + color: #607D8B; +} +nav a:hover { + color: #039be5; + background-color: #CFD8DC; +} +nav a.active { + color: #039be5; +} + +/* items class */ +.items { + margin: 0 0 2em 0; + list-style-type: none; + padding: 0; + width: 24em; +} +.items li { + cursor: pointer; + position: relative; + left: 0; + background-color: #EEE; + margin: .5em; + padding: .3em 0; + height: 1.6em; + border-radius: 4px; +} +.items li:hover { + color: #607D8B; + background-color: #DDD; + left: .1em; +} +.items li.selected { + background-color: #CFD8DC; + color: white; +} +.items li.selected:hover { + background-color: #BBD8DC; +} +.items .text { + position: relative; + top: -3px; +} +.items .badge { + display: inline-block; + font-size: small; + color: white; + padding: 0.8em 0.7em 0 0.7em; + background-color: #607D8B; + line-height: 1em; + position: relative; + left: -1px; + top: -4px; + height: 1.8em; + margin-right: .8em; + border-radius: 4px 0 0 4px; +} +/* #docregion toh */ +/* everywhere else */ +* { + font-family: Arial, Helvetica, sans-serif; +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts b/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts deleted file mode 100644 index 6fce027213..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component } from '@angular/core'; - -import { Hero } from 'hero-profile'; - -@Component({ - selector: 'my-aot-app', - template: `
-

Library consumed by AoT application

- -
` -}) -export class AppComponent { - hero = new Hero('Bombasto', 'Bombastic at times'); -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts b/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts deleted file mode 100644 index bf8970d57c..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/app-aot/app.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { AppComponent } from './app.component'; -import { HeroProfileModule } from 'hero-profile'; - -@NgModule({ - imports: [HeroProfileModule, BrowserModule], - declarations: [AppComponent], - bootstrap: [AppComponent] -}) -export class AppModule { -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts b/public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts deleted file mode 100644 index 3a7dadfe65..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/app/app.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component } from '@angular/core'; - -import { Hero } from 'hero-profile'; - -@Component({ - selector: 'my-jit-app', - template: `
-

Library consumed by JiT application

- -
` -}) -export class AppComponent { - hero = new Hero('Magneta', 'Brave as they come'); -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json b/public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json new file mode 100644 index 0000000000..e59a7403a0 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json @@ -0,0 +1,14 @@ +{ + "open": false, + "logLevel": "silent", + "port": 8080, + "server": { + "baseDir": "aot", + "routes": { + "/node_modules": "node_modules" + }, + "middleware": { + "0": null + } + } +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js b/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js index 603d33408f..8d40a6c910 100644 --- a/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js +++ b/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js @@ -6,11 +6,22 @@ import uglify from 'rollup-plugin-uglify' //paths are relative to the execution path export default { - entry: 'app-aot/main-aot.js', - dest: 'dist/build.js', // output a single application bundle + entry: 'src/main-aot.js', + dest: 'aot/dist/build.js', // output a single application bundle sourceMap: true, - sourceMapFile: 'dist/build.js.map', + sourceMapFile: 'aot/dist/build.js.map', format: 'iife', + onwarn: function(warning) { + // Skip certain warnings + + // should intercept ... but doesn't in some rollup versions + if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; } + // intercepts in some rollup versions + if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; } + + // console.warn everything else + console.warn( warning.message ); + }, plugins: [ // #docregion nodeResolve nodeResolve({jsnext: true, module: true}), diff --git a/public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts b/public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts new file mode 100644 index 0000000000..b4b4d02be6 --- /dev/null +++ b/public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; + +import { Hero } from 'hero-profile'; + +@Component({ + selector: 'my-app', + template: ` +
+

Library Consumer

+ +
+ ` +}) +export class AppComponent { + hero = new Hero('Magneta', 'Brave as they come'); +} diff --git a/public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts b/public/docs/_examples/cb-third-party-lib/ts/src/app/app.module.ts similarity index 92% rename from public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts rename to public/docs/_examples/cb-third-party-lib/ts/src/app/app.module.ts index bf8970d57c..dadd2faf1c 100644 --- a/public/docs/_examples/cb-third-party-lib/ts/app/app.module.ts +++ b/public/docs/_examples/cb-third-party-lib/ts/src/app/app.module.ts @@ -9,5 +9,4 @@ import { HeroProfileModule } from 'hero-profile'; declarations: [AppComponent], bootstrap: [AppComponent] }) -export class AppModule { -} +export class AppModule { } diff --git a/public/docs/_examples/cb-third-party-lib/ts/index.html b/public/docs/_examples/cb-third-party-lib/ts/src/index.html similarity index 56% rename from public/docs/_examples/cb-third-party-lib/ts/index.html rename to public/docs/_examples/cb-third-party-lib/ts/src/index.html index 52aaa60641..447671e9a3 100644 --- a/public/docs/_examples/cb-third-party-lib/ts/index.html +++ b/public/docs/_examples/cb-third-party-lib/ts/src/index.html @@ -1,32 +1,26 @@ + - Third Party Lib + - - + + - - - - Loading app... - - Loading app... - - + + Loading... - diff --git a/public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts b/public/docs/_examples/cb-third-party-lib/ts/src/main-aot.ts similarity index 62% rename from public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts rename to public/docs/_examples/cb-third-party-lib/ts/src/main-aot.ts index ada092b67b..bd2ca604a3 100644 --- a/public/docs/_examples/cb-third-party-lib/ts/app-aot/main-aot.ts +++ b/public/docs/_examples/cb-third-party-lib/ts/src/main-aot.ts @@ -1,3 +1,6 @@ +// #docregion import { platformBrowser } from '@angular/platform-browser'; -import { AppModuleNgFactory } from '../aot/app-aot/app.module.ngfactory'; + +import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory'; + platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/public/docs/_examples/cb-third-party-lib/ts/app/main.ts b/public/docs/_examples/cb-third-party-lib/ts/src/main.ts similarity index 75% rename from public/docs/_examples/cb-third-party-lib/ts/app/main.ts rename to public/docs/_examples/cb-third-party-lib/ts/src/main.ts index 4acf5de663..6b6532d428 100644 --- a/public/docs/_examples/cb-third-party-lib/ts/app/main.ts +++ b/public/docs/_examples/cb-third-party-lib/ts/src/main.ts @@ -1,5 +1,5 @@ // #docregion import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from './app.module'; +import { AppModule } from './app/app.module'; platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json b/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json index 85ab089d23..667ba0df42 100644 --- a/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json +++ b/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json @@ -6,7 +6,7 @@ "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "removeComments": false, + "lib": ["es2015", "dom"], "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ @@ -15,8 +15,8 @@ }, "files": [ - "app-aot/app.module.ts", - "app-aot/main-aot.ts" + "src/app/app.module.ts", + "src/main-aot.ts" ], "angularCompilerOptions": { From 9435b652ab921ecafe5b4d90a429f078a3c3c1c7 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 12:00:25 +0000 Subject: [PATCH 05/31] add intro, download --- .../ts/latest/cookbook/third-party-lib.jade | 162 +++++++++++++++++- 1 file changed, 161 insertions(+), 1 deletion(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index fde94b7062..b85fba61ba 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -1,10 +1,15 @@ include ../_util-fns :marked + Libraries are the backbone of the Angular ecosystem. + They add functionality that would otherwise take a long time to implement from scratch and keep it up to date. + Everyone benifits from a healthy library ecosystem. + Traditionally, third party JavaScript libraries have been published in the form of a single JavaScript file. Consumers of the library have then included the library, "as is", somewhere on the page using a `script` tag. - Modern web development has changed this process. Instead of publishing a "one size fits all" bundle, developers want to only include the parts of the library they actually need. + Modern web development has changed this process. + Instead of publishing a "one size fits all" bundle, developers want to only include the parts of the library they actually need and in the format they need it in. This cookbook shows how to publish a third party library in a way that makes it possible to take advantage of techniques like Ahead of Time Compilation (AoT) and Tree Shaking. @@ -26,6 +31,161 @@ include ../_util-fns [Final Application](#final-app) + TODO finish this + +a#develop-locally +:marked + ## Setup a local development environment + + Setting up a new library project on your machine is quick and easy with the **QuickStart Library seed**, + maintained [on github](https://github.com/angular/quickstart-lib "Install the github QuickStart Library repo"). + +:marked + Make sure you have at least Node 6.9 and NPM 3.0 installed. + Then ... + 1. Create a project folder (you can call it `quickstart-lib` and rename it later). + 1. [Clone](#clone "Clone it from github") or [download](#download "download it from github") the **QuickStart Library seed** into your project folder. + 1. Install npm packages. + 1. Run `npm start` to launch the sample application. + +a#clone +:marked + ### Clone + + Perform the _clone-to-launch_ steps with these terminal commands. + +code-example(language="sh" class="code-shell"). + git clone https://github.com/angular/quickstart-lib.git quickstart-lib + cd quickstart-lib + npm install + npm start + +a#download +:marked + ### Download + Download the QuickStart Library seed + and unzip it into your project folder. Then perform the remaining steps with these terminal commands. + +code-example(language="sh" class="code-shell"). + cd quickstart-lib + npm install + npm start + +.l-main-section +:marked + ## Initialize your repository + + If you cloned the package from github, it has a `.git` folder where the official repository's history lives. + + You don't want that git history though - you'll want to make your own. + + Delete this folder and initialize this one as a new repository: + +code-example(language="sh" class="code-shell"). + rm -rf .git # use rmdir .git on Windows + git init + +.alert.is-important + :marked + Do this only in the beginning to avoid accidentally deleting your own git setup! + +a#seed +.l-main-section +:marked + ## What's in the QuickStart seed? + +block qs-seed + :marked + The **QuickStart seed** contains the same application as the QuickStart playground. + But its true purpose is to provide a solid foundation for _local_ development. + Consequently, there are _many more files_ in the project folder on your machine, + most of which you can [learn about later](setup-systemjs-anatomy.html "Setup Anatomy"). + +block core-files + a#app-files + :marked + Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder. + + .filetree + .file src + .children + .file app + .children + .file app.component.ts + .file app.module.ts + .file main.ts + + +makeTabs(` + setup/ts/src/app/app.component.ts, + setup/ts/src/app/app.module.ts, + setup/ts/src/main.ts + `, '', ` + src/app/app.component.ts, + src/app/app.module.ts, + src/main.ts + `)(format='.') + +:marked + Each file has a distinct purpose and evolves independently as the application grows. + + Files outside `src/` concern building, deploying, and testing your app. + They include configuration files and external dependencies. + + Files inside `src/` "belong" to your app. + Add new Typescript, HTML and CSS files inside the `src/` directory, most of them inside `src/app`, + unless told to do otherwise. + + The following are all in `src/` + +style td, th {vertical-align: top} +table(width="100%") + col(width="20%") + col(width="80%") + tr + th File + th Purpose + tr + td app/app.component.ts + td + :marked + Defines the same `AppComponent` as the one in the QuickStart. + It is the **root** component of what will become a tree of nested components + as the application evolves. + tr(if-docs="ts") + td app/app.module.ts + td + :marked + Defines `AppModule`, the [root module](appmodule.html "AppModule: the root module") that tells Angular how to assemble the application. + Right now it declares only the `AppComponent`. + Soon there will be more components to declare. + tr + td main.ts + td + :marked + Compiles the application with the [JIT compiler](../glossary.html#jit) and + [bootstraps](appmodule.html#main "bootstrap the application") + the application's main module (`AppModule`) to run in the browser. + The JIT compiler is a reasonable choice during the development of most projects and + it's the only viable choice for a sample running in a _live-coding_ environment like Plunker. + You'll learn about alternative compiling and [deployment](deployment.html) options later in the documentation. + + +.l-main-section +:marked + ## Rename your library + + Every package on NPM has a unique name, and so should yours. + + -- rename lib + +.l-sub-section + :marked + ### Next Step + + If you're new to Angular, we recommend staying on the [learning path](learning-angular.html "Angular learning path"). + +============= + .l-main-section :marked From 1f24d04d591235a523e127696923f1ef2cd6b8ae Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 12:34:48 +0000 Subject: [PATCH 06/31] add core file descriptions --- .../ts/latest/cookbook/third-party-lib.jade | 121 +++++++++++------- 1 file changed, 78 insertions(+), 43 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index b85fba61ba..0b582c365a 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -92,38 +92,51 @@ code-example(language="sh" class="code-shell"). a#seed .l-main-section :marked - ## What's in the QuickStart seed? + ## What's in the QuickStart Library seed? -block qs-seed - :marked - The **QuickStart seed** contains the same application as the QuickStart playground. - But its true purpose is to provide a solid foundation for _local_ development. - Consequently, there are _many more files_ in the project folder on your machine, - most of which you can [learn about later](setup-systemjs-anatomy.html "Setup Anatomy"). + The **QuickStart Library seed** contains a similar structure to the **Quickstart seed*. + It's modified to build and test a library instead of an application. + + Consequently, there are _many different files_ in the project, + most of which you can [learn about later](library-setup-anatomy.html "Library Setup Anatomy"). -block core-files - a#app-files - :marked - Focus on the following three TypeScript (`.ts`) files in the **`/src`** folder. + Focus on the following TypeScript (`.ts`) files in the **`/src`** folder. - .filetree - .file src +.filetree + .file src + .children + .file demo .children .file app .children .file app.component.ts .file app.module.ts - .file main.ts - - +makeTabs(` - setup/ts/src/app/app.component.ts, - setup/ts/src/app/app.module.ts, - setup/ts/src/main.ts - `, '', ` - src/app/app.component.ts, - src/app/app.module.ts, - src/main.ts - `)(format='.') + .file lib + .children + .file component + .children + .file lib.component.ts + .file service + .children + .file lib.service.ts + .file index.ts + .file module.ts + ++makeTabs(` + quickstart-lib/ts/src/demo/app/app.component.ts, + quickstart-lib/ts/src/demo/app/app.module.ts, + quickstart-lib/ts/src/lib/component/lib.component.ts, + quickstart-lib/ts/src/lib/service/lib.service.ts, + quickstart-lib/ts/src/lib/index.ts, + quickstart-lib/ts/src/lib/module.ts + `, '', ` + src/demo/app/app.component.ts, + src/demo/app/app.module.ts, + src/lib/component/lib.component.ts, + src/lib/service/lib.service.ts, + src/lib/index.ts, + src/lib/module.ts + `)(format='.') :marked Each file has a distinct purpose and evolves independently as the application grows. @@ -131,10 +144,12 @@ block core-files Files outside `src/` concern building, deploying, and testing your app. They include configuration files and external dependencies. - Files inside `src/` "belong" to your app. - Add new Typescript, HTML and CSS files inside the `src/` directory, most of them inside `src/app`, - unless told to do otherwise. + Files inside `src/lib` "belong" to your library, while `src/demo` contains a demo application + that loads your library. + Libraries do not run by themselves, so it's very useful to have this "demo" app while developing + to see how your library would look like to consumers. + The following are all in `src/` style td, th {vertical-align: top} @@ -145,29 +160,36 @@ table(width="100%") th File th Purpose tr - td app/app.component.ts + td demo/app/app.component.ts td :marked - Defines the same `AppComponent` as the one in the QuickStart. - It is the **root** component of what will become a tree of nested components - as the application evolves. - tr(if-docs="ts") - td app/app.module.ts + A demo component that renders the library component and a value from the library service. + tr + td demo/app/app.module.ts + td + :marked + A demo `NgModule` that imports the Library `LibModule`. + tr + td lib/component/app.component.ts + td + :marked + A sample library component that renders an `h2` tag. + tr + td lib/service/lib.service.ts td :marked - Defines `AppModule`, the [root module](appmodule.html "AppModule: the root module") that tells Angular how to assemble the application. - Right now it declares only the `AppComponent`. - Soon there will be more components to declare. + A sample library service that exports a value. tr - td main.ts + td lib/index.ts td :marked - Compiles the application with the [JIT compiler](../glossary.html#jit) and - [bootstraps](appmodule.html#main "bootstrap the application") - the application's main module (`AppModule`) to run in the browser. - The JIT compiler is a reasonable choice during the development of most projects and - it's the only viable choice for a sample running in a _live-coding_ environment like Plunker. - You'll learn about alternative compiling and [deployment](deployment.html) options later in the documentation. + The public API of your library, where you choose what to export to consumers. + tr + td lib/module.ts + td + :marked + The library's main `NgModule`, `LibModule`. + .l-main-section @@ -184,6 +206,19 @@ table(width="100%") If you're new to Angular, we recommend staying on the [learning path](learning-angular.html "Angular learning path"). + +.l-main-section +:marked + ## Appendix: library-setup-anatomy + + content + +.l-main-section +:marked + ## Appendix: testing libraries + + content + ============= .l-main-section From ed14ce07e00f19d929b51d389f5cb7577712ca3e Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 14:55:44 +0000 Subject: [PATCH 07/31] add entry points and build step --- .../ts/latest/cookbook/third-party-lib.jade | 81 +++++++++++++++++-- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 0b582c365a..82631d94d3 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -149,6 +149,8 @@ a#seed Libraries do not run by themselves, so it's very useful to have this "demo" app while developing to see how your library would look like to consumers. + + When you run `npm start`, the demo application is served. The following are all in `src/` @@ -173,7 +175,7 @@ table(width="100%") td lib/component/app.component.ts td :marked - A sample library component that renders an `h2` tag. + A sample library component that renders an `

` tag. tr td lib/service/lib.service.ts td @@ -191,31 +193,94 @@ table(width="100%") The library's main `NgModule`, `LibModule`. +.l-main-section +:marked + ## Entry points + + In order to understand how to build and publish a library, you have to consider _how_ the library is going to be consumed. + + Some users need to add it as a ` - - - - - - - - Loading... - - - diff --git a/public/docs/_examples/cb-third-party-lib/ts/aot/styles.css b/public/docs/_examples/cb-third-party-lib/ts/aot/styles.css deleted file mode 100644 index d81835d0cd..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/aot/styles.css +++ /dev/null @@ -1,116 +0,0 @@ -/* #docregion , quickstart, toh */ -/* Master Styles */ -h1 { - color: #369; - font-family: Arial, Helvetica, sans-serif; - font-size: 250%; -} -h2, h3 { - color: #444; - font-family: Arial, Helvetica, sans-serif; - font-weight: lighter; -} -body { - margin: 2em; -} -/* #enddocregion quickstart */ -body, input[text], button { - color: #888; - font-family: Cambria, Georgia; -} -/* #enddocregion toh */ -a { - cursor: pointer; - cursor: hand; -} -button { - font-family: Arial; - background-color: #eee; - border: none; - padding: 5px 10px; - border-radius: 4px; - cursor: pointer; - cursor: hand; -} -button:hover { - background-color: #cfd8dc; -} -button:disabled { - background-color: #eee; - color: #aaa; - cursor: auto; -} - -/* Navigation link styles */ -nav a { - padding: 5px 10px; - text-decoration: none; - margin-right: 10px; - margin-top: 10px; - display: inline-block; - background-color: #eee; - border-radius: 4px; -} -nav a:visited, a:link { - color: #607D8B; -} -nav a:hover { - color: #039be5; - background-color: #CFD8DC; -} -nav a.active { - color: #039be5; -} - -/* items class */ -.items { - margin: 0 0 2em 0; - list-style-type: none; - padding: 0; - width: 24em; -} -.items li { - cursor: pointer; - position: relative; - left: 0; - background-color: #EEE; - margin: .5em; - padding: .3em 0; - height: 1.6em; - border-radius: 4px; -} -.items li:hover { - color: #607D8B; - background-color: #DDD; - left: .1em; -} -.items li.selected { - background-color: #CFD8DC; - color: white; -} -.items li.selected:hover { - background-color: #BBD8DC; -} -.items .text { - position: relative; - top: -3px; -} -.items .badge { - display: inline-block; - font-size: small; - color: white; - padding: 0.8em 0.7em 0 0.7em; - background-color: #607D8B; - line-height: 1em; - position: relative; - left: -1px; - top: -4px; - height: 1.8em; - margin-right: .8em; - border-radius: 4px 0 0 4px; -} -/* #docregion toh */ -/* everywhere else */ -* { - font-family: Arial, Helvetica, sans-serif; -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json b/public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json deleted file mode 100644 index e59a7403a0..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/bs-config.aot.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "open": false, - "logLevel": "silent", - "port": 8080, - "server": { - "baseDir": "aot", - "routes": { - "/node_modules": "node_modules" - }, - "middleware": { - "0": null - } - } -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/example-config.json b/public/docs/_examples/cb-third-party-lib/ts/example-config.json deleted file mode 100644 index 85a9a43ad0..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/example-config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "build": "build:aot:jit" -} \ No newline at end of file diff --git a/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js b/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js deleted file mode 100644 index 8d40a6c910..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/rollup-config.js +++ /dev/null @@ -1,34 +0,0 @@ -// #docregion -import rollup from 'rollup' -import nodeResolve from 'rollup-plugin-node-resolve' -import commonjs from 'rollup-plugin-commonjs'; -import uglify from 'rollup-plugin-uglify' - -//paths are relative to the execution path -export default { - entry: 'src/main-aot.js', - dest: 'aot/dist/build.js', // output a single application bundle - sourceMap: true, - sourceMapFile: 'aot/dist/build.js.map', - format: 'iife', - onwarn: function(warning) { - // Skip certain warnings - - // should intercept ... but doesn't in some rollup versions - if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; } - // intercepts in some rollup versions - if ( warning.indexOf("The 'this' keyword is equivalent to 'undefined'") > -1 ) { return; } - - // console.warn everything else - console.warn( warning.message ); - }, - plugins: [ - // #docregion nodeResolve - nodeResolve({jsnext: true, module: true}), - // #enddocregion nodeResolve - commonjs({ - include: ['node_modules/rxjs/**'] - }), - uglify() - ] -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts b/public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts deleted file mode 100644 index b4b4d02be6..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/src/app/app.component.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Component } from '@angular/core'; - -import { Hero } from 'hero-profile'; - -@Component({ - selector: 'my-app', - template: ` -
-

Library Consumer

- -
- ` -}) -export class AppComponent { - hero = new Hero('Magneta', 'Brave as they come'); -} diff --git a/public/docs/_examples/cb-third-party-lib/ts/src/app/app.module.ts b/public/docs/_examples/cb-third-party-lib/ts/src/app/app.module.ts deleted file mode 100644 index dadd2faf1c..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/src/app/app.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { AppComponent } from './app.component'; -import { HeroProfileModule } from 'hero-profile'; - -@NgModule({ - imports: [HeroProfileModule, BrowserModule], - declarations: [AppComponent], - bootstrap: [AppComponent] -}) -export class AppModule { } diff --git a/public/docs/_examples/cb-third-party-lib/ts/src/index.html b/public/docs/_examples/cb-third-party-lib/ts/src/index.html deleted file mode 100644 index 447671e9a3..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/src/index.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - Third Party Lib - - - - - - - - - - - - - - - - Loading... - - diff --git a/public/docs/_examples/cb-third-party-lib/ts/src/main-aot.ts b/public/docs/_examples/cb-third-party-lib/ts/src/main-aot.ts deleted file mode 100644 index bd2ca604a3..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/src/main-aot.ts +++ /dev/null @@ -1,6 +0,0 @@ -// #docregion -import { platformBrowser } from '@angular/platform-browser'; - -import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory'; - -platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/public/docs/_examples/cb-third-party-lib/ts/src/main.ts b/public/docs/_examples/cb-third-party-lib/ts/src/main.ts deleted file mode 100644 index 6b6532d428..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -// #docregion -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; - -platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json b/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json deleted file mode 100644 index 667ba0df42..0000000000 --- a/public/docs/_examples/cb-third-party-lib/ts/tsconfig-aot.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "module": "es2015", - "moduleResolution": "node", - "sourceMap": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "lib": ["es2015", "dom"], - "noImplicitAny": true, - "suppressImplicitAnyIndexErrors": true, - "typeRoots": [ - "../../node_modules/@types/" - ] - }, - - "files": [ - "src/app/app.module.ts", - "src/main-aot.ts" - ], - - "angularCompilerOptions": { - "genDir": "aot", - "skipMetadataEmit" : true - } -} From 9bbc128fc242ac01d6e62a1a16d0a2dceae76f2d Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 17:14:41 +0000 Subject: [PATCH 12/31] whitespace --- .../ts/latest/cookbook/third-party-lib.jade | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 063b44cf05..09cb0858f8 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -33,7 +33,7 @@ include ../_util-fns TODO finish this -a#develop-locally +.l-main-section :marked ## Setup a local development environment @@ -71,6 +71,7 @@ code-example(language="sh" class="code-shell"). npm install npm start + .l-main-section :marked ## Initialize your repository @@ -230,6 +231,7 @@ code-example(language="json"). There is also a minified UMD bundle (`angular-quickstart-lib.umd.min.js`) for smaller payloads in Plunkers and script tags. + .l-sub-section :marked A flat ECMAScript module (FESM) is a bundled ECMAScript module where all imports were followed @@ -237,6 +239,7 @@ code-example(language="json"). It always contains ES module import/export statements but can have different levels of ES code inside. + .l-main-section :marked ## The build step @@ -251,6 +254,7 @@ code-example(language="json"). - Copy typings, metatada, html and css. - Create each bundle using Rollup. + .l-main-section :marked ## Testing libraries @@ -281,6 +285,7 @@ code-example(language="json"). In addition to integration tests, you can also run unit tests in watch mode via `npm run test`, or single-run via `npm run test:once`. + .l-main-section :marked ## Publishing your library @@ -318,28 +323,11 @@ code-example(language="json"). You'll need to create a NPM account, login on your local machine, and then you can publish updated by running `npm publish`. - Remember to follow [Semantic Versioning](http://semver.org/) and document your library! - -.l-main-section -:marked - ## title - - content + Remember to document your library, follow [Semantic Versioning](http://semver.org/) and + setup a Continuous Integration solution to test your library (included is a `travis.yml` + file for [Travis CI](https://docs.travis-ci.com/user/getting-started/))! -.l-main-section -:marked - ## title - - content - - -.l-main-section -:marked - ## Appendix: Library Setup Anatomy - - content - .l-main-section :marked ## Appendix: Supporting AOT @@ -382,6 +370,7 @@ code-example(language="json"). Publishing plain JavaScript with typings and meta data allows the consuming application to remain agnostic of the library's build environment. + .l-main-section :marked ## Appendix: Supporting JIT From 274a207bc5ae80a9d764840a73f4f4b1ac6a5e33 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 17:25:04 +0000 Subject: [PATCH 13/31] add v4 message --- public/docs/ts/latest/cookbook/third-party-lib.jade | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 09cb0858f8..abe188bb8c 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -13,6 +13,10 @@ include ../_util-fns This cookbook shows how to publish a third party library in a way that makes it possible to take advantage of techniques like Ahead of Time Compilation (AOT) and Tree Shaking. +.alert.is-important + :marked + The setup shown in this cookbook is only for Angular version 4 (and up) libraries. + :marked ## Table of contents From 0f65921ee6efbe5f3c99d95a7aeb8ae31d69d953 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 17:53:26 +0000 Subject: [PATCH 14/31] add dep management --- .../ts/latest/cookbook/third-party-lib.jade | 58 ++++++++++++++++++- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index abe188bb8c..0946183a96 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -289,6 +289,9 @@ code-example(language="json"). In addition to integration tests, you can also run unit tests in watch mode via `npm run test`, or single-run via `npm run test:once`. + You can also test your library by installing it in another local repository you have. + To do so, first build your lib via `npm run build`. + Then install it from your other repo using a relative path: `npm install relative/path/to/lib`. .l-main-section :marked @@ -327,9 +330,15 @@ code-example(language="json"). You'll need to create a NPM account, login on your local machine, and then you can publish updated by running `npm publish`. - Remember to document your library, follow [Semantic Versioning](http://semver.org/) and - setup a Continuous Integration solution to test your library (included is a `travis.yml` - file for [Travis CI](https://docs.travis-ci.com/user/getting-started/))! +.l-sub-section + :marked + ### Be a good library maintainer + + Remember to document your library, + [manage your dependencies properly](appendix-dependency-management), + follow [Semantic Versioning](http://semver.org/) and + setup a Continuous Integration solution to test your library (included is a `travis.yml` + file for [Travis CI](https://docs.travis-ci.com/user/getting-started/))! .l-main-section @@ -384,3 +393,46 @@ code-example(language="json"). To create a more flexible developer experience, a JIT compatible build of the library should be published as well. The format of the JIT bundle is `umd`, which stands for Universal Module Definition. Shipping the bundle as `umd` ensures compatibility with most common module loading formats. The `umd` bundle will ship as a single file containing ES5 JavaScript and inlined versions of any external templates or css. + + +.l-main-section +:marked + ## Appendix: Dependency Management + + As a library maintainer, it's important to properly manage your dependencies in `package.json`. + + There are [three kinds of dependencies](https://docs.npmjs.com/files/package.json#dependencies): + `dependencies`, `devDependencies` and `peerDependencies`. + + - `dependencies`: here go all the other libraries yours depends on when being used. + A good way to figure out these is to go through your library source code (in `src/lib` **only**) + and list all the libraries there. + - `devDependencies`: libraries that you need while developing, testing and building your app + go here. + When a user installs your library, these won't be installed. + Users don't need to develop, build or test your library, they just need to run it. + your app. + - `peerDependencies`: these are similar to `dependencies` since your library expects them to be + there at runtime. + The difference is that you don't want to install a new version of these, but instead use + the one already available. + + A good example of a peer dependency is `@angular/core` and all other main Angular libraries. + If you listed these in `dependencies`, a new one - with a different version! - could be installed + for your library to use. + This isn't what you wanted though. You want your library to use *the exact same* `@angular/core` + that the app is using. + + You'll usually used `@angular/*` libraries listed in both `devDependencies` and + `peerDependencies`. + This is normal and expected, because when you're developing your library also need a copy of + them installed. + + Another thing to remember is to keep your dependencies from changing too much unexpectedly. + Different versions of libraries can have different features, and if you inadvertently are too + lenient with allowed versions your library might stop working because a dependency changed. + + You can choose what versions you allow by using [ranges](https://docs.npmjs.com/misc/semver). + + A good rule of thumb is to have all `dependencies` specified with a tilde `~`(`~1.2.3`), + while your `peerDependencies` have a range (`"@angular/core": ">=4.0.0 <5.0.0 || >=4.0.0-beta <5.0.0"`). From e2e77383b9c510fc1fe487b49fae9f69eb8b434a Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 17:55:02 +0000 Subject: [PATCH 15/31] whitespace --- .../ts/latest/cookbook/third-party-lib.jade | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 0946183a96..011e5c2be0 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -345,12 +345,14 @@ code-example(language="json"). :marked ## Appendix: Supporting AOT - AOT plays an important role in optimizing Angular applications. It's therefore important that third party libraries be published in a format compatible with AOT compilation. Otherwise it will not be possible to include the library in an AOT compiled application. + AOT plays an important role in optimizing Angular applications. + It's therefore important that third party libraries be published in a format compatible with AOT + compilation. + Otherwise it will not be possible to include the library in an AOT compiled application. Only code written in TypeScript can be AOT compiled. Before publishing the library must first be compiled using the `ngc` compiler. - `ngc` extends the `tsc` compiler by adding extensions to support AOT compilation in addition to regular TypeScript compilation. AOT compilation outputs three files that must be included in order to be compatible with AOT. @@ -361,27 +363,38 @@ code-example(language="json"). *Typings files* - JavaScript has no way of representing typings. In order to preserve the original typings, `ngc` will generate `.d.ts` typings files. + JavaScript has no way of representing typings. In order to preserve the original typings, `ngc` + will generate `.d.ts` typings files. *Meta Data JSON files* - `ngc` outputs a metadata.json file for every `Component` and `NgModule`. These meta data files represent the information in the original `NgModule` and `Component` decorators. + `ngc` outputs a metadata.json file for every `Component` and `NgModule`. + These meta data files represent the information in the original `NgModule` and `Component` + decorators. - The meta data may reference external templates or css files. These external files must be included with the library. + The meta data may reference external templates or css files. + These external files must be included with the library. ### NgFactories - `ngc` generates a series of files with an `.ngfactory` suffix as well. These files represent the AOT compiled source, but should not be included with the published library. + `ngc` generates a series of files with an `.ngfactory` suffix as well. + These files represent the AOT compiled source, but should not be included with the published library. - Instead the `ngc` compiler in the consuming application will generate `.ngfactory` files based on the JavaScript, Typings and meta data shipped with the library. + Instead the `ngc` compiler in the consuming application will generate `.ngfactory` files based + on the JavaScript, Typings and meta data shipped with the library. ### Why not publish TypeScript? - Why not ship TypeScript source instead? After all the library will be part of another TypeScript compilation step when the library is imported by the consuming application? + Why not ship TypeScript source instead? + After all the library will be part of another TypeScript compilation step when the library is + imported by the consuming application? - Generally it's discouraged to ship TypeScript with third party libraries. It would require the consumer to replicate the complete build environment of the library. Not only typings, but potentially a specific version of `ngc` as well. + Generally it's discouraged to ship TypeScript with third party libraries. + It would require the consumer to replicate the complete build environment of the library. + Not only typings, but potentially a specific version of `ngc` as well. - Publishing plain JavaScript with typings and meta data allows the consuming application to remain agnostic of the library's build environment. + Publishing plain JavaScript with typings and meta data allows the consuming application to + remain agnostic of the library's build environment. .l-main-section From aef571f2db495ef0089c31e38e36ea1a5b44b6b8 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 18:04:21 +0000 Subject: [PATCH 16/31] add externals/globals note --- public/docs/ts/latest/cookbook/third-party-lib.jade | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 011e5c2be0..850b342742 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -449,3 +449,9 @@ code-example(language="json"). A good rule of thumb is to have all `dependencies` specified with a tilde `~`(`~1.2.3`), while your `peerDependencies` have a range (`"@angular/core": ">=4.0.0 <5.0.0 || >=4.0.0-beta <5.0.0"`). + + Any extra dependency or peer Dependency that you add to `package.json` should also be added + to the `globals` and `external` array in the `rollupBaseConfig` variable in `./build.js`. + + This ensures your library doesn't package extra libraries inside of it and instead uses the ones + available in the consuming app. From 5bf5337a82f187f7a591c6b7150ee0bc6933f603 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 18:10:19 +0000 Subject: [PATCH 17/31] fix headers --- .../ts/latest/cookbook/third-party-lib.jade | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 850b342742..7c38e075ee 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -21,19 +21,23 @@ include ../_util-fns :marked ## Table of contents - [Creating a Third Party Library](#third-party-lib) + [Setup a local development environment](#setup-a-local-development-environment) - [Supporting AOT](#AOT) + [What's in the QuickStart Library seed?](#whats-in-the-quickStart-library-seed) - [Preparing the library for Tree Shaking](#tree-shaking) + [Entry points](#entry-points) - [Supporting JIT](#JIT) + [The build step](#the-build-step) - [Publish](#publish) + [Testing libraries](#testing-libraries) - [Integrate with Application](#integrate-with-app) + [Publishing your library](#publishing-your-library) - [Final Application](#final-app) + [Appendix: Supporting AOT](#appendix-supporting-aot) + + [Appendix: Supporting JIT](#appendix-supporting-jit) + + [Appendix: Dependency Management](#appendix-dependency-management) TODO finish this From 3ef8d45d422d0e5a337b7b5cc7e56e7dc7c4ce80 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 18:18:13 +0000 Subject: [PATCH 18/31] add example --- .../_examples/quickstart-lib/ts/.gitignore | 11 ++++ .../_examples/quickstart-lib/ts/.npmignore | 8 +++ .../docs/_examples/quickstart-lib/ts/LICENSE | 21 +++++++ .../_examples/quickstart-lib/ts/README.md | 25 ++++++++ .../quickstart-lib/ts/integration/.gitignore | 9 +++ .../quickstart-lib/ts/integration/README.md | 26 +++++++++ .../ts/integration/bs-config.aot.json | 5 ++ .../ts/integration/bs-config.e2e-aot.json | 11 ++++ .../ts/integration/bs-config.e2e.json | 14 +++++ .../ts/integration/bs-config.json | 8 +++ .../ts/integration/e2e/app.e2e-spec.ts | 21 +++++++ .../ts/integration/e2e/tsconfig.json | 13 +++++ .../ts/integration/package.json | 55 ++++++++++++++++++ .../ts/integration/src/app/app.component.ts | 16 +++++ .../ts/integration/src/app/app.module.ts | 12 ++++ .../ts/integration/src/favicon.ico | Bin 0 -> 5430 bytes .../ts/integration/src/index-aot.html | 18 ++++++ .../ts/integration/src/index.html | 25 ++++++++ .../ts/integration/src/main-aot.ts | 5 ++ .../quickstart-lib/ts/integration/src/main.ts | 5 ++ .../ts/integration/src/styles.css | 5 ++ .../ts/integration/src/systemjs.config.js | 41 +++++++++++++ .../ts/integration/src/tsconfig.json | 16 +++++ .../ts/integration/tsconfig.aot.json | 24 ++++++++ .../ts/src/demo/app/app.component.ts | 17 ++++++ .../ts/src/demo/app/app.module.ts | 13 +++++ .../quickstart-lib/ts/src/demo/favicon.ico | Bin 0 -> 5430 bytes .../quickstart-lib/ts/src/demo/index.html | 25 ++++++++ .../quickstart-lib/ts/src/demo/main.ts | 5 ++ .../quickstart-lib/ts/src/demo/styles.css | 5 ++ .../ts/src/demo/systemjs.config.js | 43 ++++++++++++++ .../quickstart-lib/ts/src/demo/tsconfig.json | 17 ++++++ .../quickstart-lib/ts/src/demo/typings.d.ts | 5 ++ .../ts/src/lib/angular-quickstart-lib.ts | 7 +++ .../ts/src/lib/component/lib.component.css | 0 .../ts/src/lib/component/lib.component.html | 1 + .../src/lib/component/lib.component.spec.ts | 33 +++++++++++ .../ts/src/lib/component/lib.component.ts | 12 ++++ .../quickstart-lib/ts/src/lib/index.ts | 4 ++ .../quickstart-lib/ts/src/lib/module.ts | 12 ++++ .../ts/src/lib/service/lib.service.spec.ts | 19 ++++++ .../ts/src/lib/service/lib.service.ts | 8 +++ .../ts/src/lib/tsconfig.es2015.json | 18 ++++++ .../quickstart-lib/ts/src/lib/tsconfig.json | 20 +++++++ .../ts/src/lib/tsconfig.spec.json | 9 +++ .../quickstart-lib/ts/src/lib/typings.d.ts | 5 ++ .../ts/latest/cookbook/third-party-lib.jade | 2 +- 47 files changed, 673 insertions(+), 1 deletion(-) create mode 100644 public/docs/_examples/quickstart-lib/ts/.gitignore create mode 100644 public/docs/_examples/quickstart-lib/ts/.npmignore create mode 100644 public/docs/_examples/quickstart-lib/ts/LICENSE create mode 100644 public/docs/_examples/quickstart-lib/ts/README.md create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/.gitignore create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/README.md create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/bs-config.aot.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e-aot.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/bs-config.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/e2e/app.e2e-spec.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/e2e/tsconfig.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/package.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/app/app.component.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/app/app.module.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/favicon.ico create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/index-aot.html create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/index.html create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/main-aot.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/main.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/styles.css create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/systemjs.config.js create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/src/tsconfig.json create mode 100644 public/docs/_examples/quickstart-lib/ts/integration/tsconfig.aot.json create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/app/app.component.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/app/app.module.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/favicon.ico create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/index.html create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/main.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/styles.css create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/systemjs.config.js create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/tsconfig.json create mode 100644 public/docs/_examples/quickstart-lib/ts/src/demo/typings.d.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/angular-quickstart-lib.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.css create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.html create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.spec.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/index.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/module.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.spec.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.ts create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.es2015.json create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.json create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.spec.json create mode 100644 public/docs/_examples/quickstart-lib/ts/src/lib/typings.d.ts diff --git a/public/docs/_examples/quickstart-lib/ts/.gitignore b/public/docs/_examples/quickstart-lib/ts/.gitignore new file mode 100644 index 0000000000..7b260b085c --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/.gitignore @@ -0,0 +1,11 @@ +dist/ +node_modules/ +out-tsc/ +debug.log +npm-debug.log +src/**/*.js +!src/demo/systemjs.config.js +!src/demo/systemjs.config.lib.js +*.js.map +e2e/**/*.js +e2e/**/*.js.map diff --git a/public/docs/_examples/quickstart-lib/ts/.npmignore b/public/docs/_examples/quickstart-lib/ts/.npmignore new file mode 100644 index 0000000000..d1e75d8f72 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/.npmignore @@ -0,0 +1,8 @@ +# Ignore eveything by default. +/* + +# Only publish these files/folders: +!dist/ +!LICENSE +!package.json +!README.md diff --git a/public/docs/_examples/quickstart-lib/ts/LICENSE b/public/docs/_examples/quickstart-lib/ts/LICENSE new file mode 100644 index 0000000000..51b127e827 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2014-2016 Google, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/public/docs/_examples/quickstart-lib/ts/README.md b/public/docs/_examples/quickstart-lib/ts/README.md new file mode 100644 index 0000000000..123937345d --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/README.md @@ -0,0 +1,25 @@ +# Angular QuickStart Lib +[![Build Status][travis-badge]][travis-badge-url] + +This is a simple library quickstart for Angular libraries. + +Features: +- a simple a library +- unit tests for the library +- a demo application that consumes the library in JIT mode and runs in watch mode +- an integration app that consumes the library in JIT and AOT mode and runs e2e tests + +Common tasks are present as npm scripts: + +- `npm start` to run a live-reload server with the demo app +- `npm run test` to test in watch mode, or `npm run test:once` to only run once +- `npm run build` to build the library +- `npm run lint` to lint +- `npm run clean` to clean +- `npm run integration` to run the integration e2e tests +- `npm install ./relative/path/to/lib` after `npm run build` to test locally in another app + +If you need to debug the integration app, please check `./integration/README.md`. + +[travis-badge]: https://travis-ci.org/filipesilva/angular-quickstart-lib.svg?branch=master +[travis-badge-url]: https://travis-ci.org/filipesilva/angular-quickstart-lib diff --git a/public/docs/_examples/quickstart-lib/ts/integration/.gitignore b/public/docs/_examples/quickstart-lib/ts/integration/.gitignore new file mode 100644 index 0000000000..1cce1c63c5 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/.gitignore @@ -0,0 +1,9 @@ +node_modules +npm-debug.log +src/**/*.js +!src/systemjs.config.js +*.js.map +e2e/**/*.js +e2e/**/*.js.map +out-tsc/* +dist/* diff --git a/public/docs/_examples/quickstart-lib/ts/integration/README.md b/public/docs/_examples/quickstart-lib/ts/integration/README.md new file mode 100644 index 0000000000..58c845d87b --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/README.md @@ -0,0 +1,26 @@ +# Integration App + +This is a simplified version of https://github.com/angular/quickstart used to test the built lib. + +## npm scripts + +We've captured many of the most useful commands in npm scripts defined in the `package.json`: + +* `npm start` - runs the compiler and a server at the same time, both in "watch mode". +* `npm run e2e` - compiles the app and run e2e tests. +* `npm run e2e:aot` - compiles and the app with AOT and run e2e tests. + + +If you need to manually test a library build, follow these steps: +``` +# starting at the project root, build the library +npm run build +# clean the integration app +npm run preintegration +cd integration +npm install +``` + +Now the library is installed in your integration app. + +You can use `npm start` to start a live reload server running the app in JIT mode, or `npm run build && npm run serve:aot` to run a static server in AOT mode. diff --git a/public/docs/_examples/quickstart-lib/ts/integration/bs-config.aot.json b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.aot.json new file mode 100644 index 0000000000..01f2e4ac6b --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.aot.json @@ -0,0 +1,5 @@ +{ + "server": { + "baseDir": "dist" + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e-aot.json b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e-aot.json new file mode 100644 index 0000000000..ac61d35f83 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e-aot.json @@ -0,0 +1,11 @@ +{ + "open": false, + "logLevel": "silent", + "port": 8080, + "server": { + "baseDir": "dist", + "middleware": { + "0": null + } + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e.json b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e.json new file mode 100644 index 0000000000..24570dbcc9 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.e2e.json @@ -0,0 +1,14 @@ +{ + "open": false, + "logLevel": "silent", + "port": 8080, + "server": { + "baseDir": "src", + "routes": { + "/node_modules": "node_modules" + }, + "middleware": { + "0": null + } + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/bs-config.json b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.json new file mode 100644 index 0000000000..4e58595267 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/bs-config.json @@ -0,0 +1,8 @@ +{ + "server": { + "baseDir": "src", + "routes": { + "/node_modules": "node_modules" + } + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/e2e/app.e2e-spec.ts b/public/docs/_examples/quickstart-lib/ts/integration/e2e/app.e2e-spec.ts new file mode 100644 index 0000000000..f2340b148b --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/e2e/app.e2e-spec.ts @@ -0,0 +1,21 @@ +import { browser, element, by } from 'protractor'; + +describe('QuickStart Lib E2E Tests', function () { + + beforeEach(() => browser.get('')); + + afterEach(() => { + browser.manage().logs().get('browser').then((browserLog: any[]) => { + expect(browserLog).toEqual([]); + }); + }); + + it('should display lib', () => { + expect(element(by.css('h2')).getText()).toEqual('Hello Angular Library'); + }); + + it('should display meaning', () => { + expect(element(by.css('h3')).getText()).toEqual('Meaning is: 42'); + }); + +}); diff --git a/public/docs/_examples/quickstart-lib/ts/integration/e2e/tsconfig.json b/public/docs/_examples/quickstart-lib/ts/integration/e2e/tsconfig.json new file mode 100644 index 0000000000..2c7260d1bc --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/e2e/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ "es2015", "dom" ], + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/package.json b/public/docs/_examples/quickstart-lib/ts/integration/package.json new file mode 100644 index 0000000000..012f5c37cc --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/package.json @@ -0,0 +1,55 @@ +{ + "name": "integration-test", + "version": "1.0.0", + "description": "App for integration tests", + "scripts": { + "clean": "rimraf aot/ dist/ node_modules/angular-quickstart-lib/", + "build": "tsc -p src/", + "build:watch": "tsc -p src/ -w", + "build:e2e": "tsc -p e2e/", + "build:aot": "node build.js", + "serve": "lite-server -c=bs-config.json", + "serve:aot": "lite-server -c bs-config.aot.json", + "serve:e2e": "lite-server -c=bs-config.e2e.json", + "serve:e2e-aot": "lite-server -c bs-config.e2e-aot.json", + "prestart": "npm run build", + "start": "concurrently \"npm run build:watch\" \"npm run serve\"", + "pree2e": "npm run build:e2e && npm run build", + "e2e": "concurrently \"npm run serve:e2e\" \"npm run protractor\" --kill-others --success first", + "pree2e:aot": "npm run build:e2e && npm run build:aot", + "e2e:aot": "concurrently \"npm run serve:e2e-aot\" \"npm run protractor\" --kill-others --success first", + "preprotractor": "webdriver-manager update", + "protractor": "protractor protractor.config.js" + }, + "keywords": [], + "author": "", + "license": "MIT", + "dependencies": { + "@angular/common": "^4.0.0-rc.3", + "@angular/compiler": "^4.0.0-rc.3", + "@angular/compiler-cli": "^4.0.0-rc.3", + "@angular/core": "^4.0.0-rc.3", + "@angular/platform-browser": "^4.0.0-rc.3", + "@angular/platform-browser-dynamic": "^4.0.0-rc.3", + "angular-quickstart-lib": "../", + "core-js": "^2.4.1", + "rxjs": "5.0.1", + "systemjs": "0.19.40", + "zone.js": "^0.8.4" + }, + "devDependencies": { + "@types/jasmine": "2.5.36", + "concurrently": "^3.2.0", + "jasmine-core": "~2.4.1", + "glob": "^7.1.1", + "lite-server": "^2.2.2", + "protractor": "~5.1.0", + "rimraf": "^2.5.4", + "rollup": "^0.41.4", + "rollup-plugin-commonjs": "^7.0.0", + "rollup-plugin-node-resolve": "^2.0.0", + "rollup-plugin-uglify": "^1.0.1", + "typescript": "^2.0.10" + }, + "repository": {} +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/app/app.component.ts b/public/docs/_examples/quickstart-lib/ts/integration/src/app/app.component.ts new file mode 100644 index 0000000000..c4d3e11b27 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/app/app.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { LibService } from 'angular-quickstart-lib'; + +@Component({ + selector: 'integration-app', + template: ` + +

Meaning is: {{meaning}}

+ `, +}) +export class AppComponent { + meaning: number; + constructor(libService: LibService) { + this.meaning = libService.getMeaning(); + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/app/app.module.ts b/public/docs/_examples/quickstart-lib/ts/integration/src/app/app.module.ts new file mode 100644 index 0000000000..d3888e3fa1 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/app/app.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { LibModule } from 'angular-quickstart-lib'; + +import { AppComponent } from './app.component'; + +@NgModule({ + imports: [ BrowserModule, LibModule], + declarations: [ AppComponent ], + bootstrap: [ AppComponent ] +}) +export class AppModule { } diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/favicon.ico b/public/docs/_examples/quickstart-lib/ts/integration/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8081c7ceaf2be08bf59010158c586170d9d2d517 GIT binary patch literal 5430 zcmc(je{54#6vvCoAI3i*G5%$U7!sA3wtMZ$fH6V9C`=eXGJb@R1%(I_{vnZtpD{6n z5Pl{DmxzBDbrB>}`90e12m8T*36WoeDLA&SD_hw{H^wM!cl_RWcVA!I+x87ee975; z@4kD^=bYPn&pmG@(+JZ`rqQEKxW<}RzhW}I!|ulN=fmjVi@x{p$cC`)5$a!)X&U+blKNvN5tg=uLvuLnuqRM;Yc*swiexsoh#XPNu{9F#c`G zQLe{yWA(Y6(;>y|-efAy11k<09(@Oo1B2@0`PtZSkqK&${ zgEY}`W@t{%?9u5rF?}Y7OL{338l*JY#P!%MVQY@oqnItpZ}?s z!r?*kwuR{A@jg2Chlf0^{q*>8n5Ir~YWf*wmsh7B5&EpHfd5@xVaj&gqsdui^spyL zB|kUoblGoO7G(MuKTfa9?pGH0@QP^b#!lM1yHWLh*2iq#`C1TdrnO-d#?Oh@XV2HK zKA{`eo{--^K&MW66Lgsktfvn#cCAc*(}qsfhrvOjMGLE?`dHVipu1J3Kgr%g?cNa8 z)pkmC8DGH~fG+dlrp(5^-QBeEvkOvv#q7MBVLtm2oD^$lJZx--_=K&Ttd=-krx(Bb zcEoKJda@S!%%@`P-##$>*u%T*mh+QjV@)Qa=Mk1?#zLk+M4tIt%}wagT{5J%!tXAE;r{@=bb%nNVxvI+C+$t?!VJ@0d@HIyMJTI{vEw0Ul ze(ha!e&qANbTL1ZneNl45t=#Ot??C0MHjjgY8%*mGisN|S6%g3;Hlx#fMNcL<87MW zZ>6moo1YD?P!fJ#Jb(4)_cc50X5n0KoDYfdPoL^iV`k&o{LPyaoqMqk92wVM#_O0l z09$(A-D+gVIlq4TA&{1T@BsUH`Bm=r#l$Z51J-U&F32+hfUP-iLo=jg7Xmy+WLq6_tWv&`wDlz#`&)Jp~iQf zZP)tu>}pIIJKuw+$&t}GQuqMd%Z>0?t%&BM&Wo^4P^Y z)c6h^f2R>X8*}q|bblAF?@;%?2>$y+cMQbN{X$)^R>vtNq_5AB|0N5U*d^T?X9{xQnJYeU{ zoZL#obI;~Pp95f1`%X3D$Mh*4^?O?IT~7HqlWguezmg?Ybq|7>qQ(@pPHbE9V?f|( z+0xo!#m@Np9PljsyxBY-UA*{U*la#8Wz2sO|48_-5t8%_!n?S$zlGe+NA%?vmxjS- zHE5O3ZarU=X}$7>;Okp(UWXJxI%G_J-@IH;%5#Rt$(WUX?6*Ux!IRd$dLP6+SmPn= z8zjm4jGjN772R{FGkXwcNv8GBcZI#@Y2m{RNF_w8(Z%^A*!bS*!}s6sh*NnURytky humW;*g7R+&|Ledvc- + + + Angular QuickStart + + + + + + + + + + + Loading... + + + diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/index.html b/public/docs/_examples/quickstart-lib/ts/integration/src/index.html new file mode 100644 index 0000000000..65e0079f5e --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/index.html @@ -0,0 +1,25 @@ + + + + Angular QuickStart + + + + + + + + + + + + + + + + + Loading AppComponent content here ... + + diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/main-aot.ts b/public/docs/_examples/quickstart-lib/ts/integration/src/main-aot.ts new file mode 100644 index 0000000000..09b22100b4 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/main-aot.ts @@ -0,0 +1,5 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModuleNgFactory } from '../out-tsc/src/app/app.module.ngfactory'; + +platformBrowserDynamic().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/main.ts b/public/docs/_examples/quickstart-lib/ts/integration/src/main.ts new file mode 100644 index 0000000000..311c44b76d --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/main.ts @@ -0,0 +1,5 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/styles.css b/public/docs/_examples/quickstart-lib/ts/integration/src/styles.css new file mode 100644 index 0000000000..58e1a7d9a4 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/styles.css @@ -0,0 +1,5 @@ +h1 { + color: #369; + font-family: Arial, Helvetica, sans-serif; + font-size: 250%; +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/systemjs.config.js b/public/docs/_examples/quickstart-lib/ts/integration/src/systemjs.config.js new file mode 100644 index 0000000000..95a3533dbe --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/systemjs.config.js @@ -0,0 +1,41 @@ +/** + * System configuration for Angular samples + * Adjust as necessary for your application needs. + */ +(function (global) { + System.config({ + paths: { + // paths serve as alias + 'npm:': 'node_modules/' + }, + // map tells the System loader where to look for things + map: { + // our app is within the app folder + app: 'app', + + // angular bundles + '@angular/core': 'npm:@angular/core/bundles/core.umd.js', + '@angular/common': 'npm:@angular/common/bundles/common.umd.js', + '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', + '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', + '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', + '@angular/http': 'npm:@angular/http/bundles/http.umd.js', + '@angular/router': 'npm:@angular/router/bundles/router.umd.js', + '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', + + // other libraries + 'rxjs': 'npm:rxjs', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js', + 'angular-quickstart-lib': 'npm:angular-quickstart-lib/dist/angular-quickstart-lib.umd.js' + }, + // packages tells the System loader how to load when no filename and/or no extension + packages: { + app: { + defaultExtension: 'js' + }, + rxjs: { + defaultExtension: 'js' + } + } + }); +})(this); diff --git a/public/docs/_examples/quickstart-lib/ts/integration/src/tsconfig.json b/public/docs/_examples/quickstart-lib/ts/integration/src/tsconfig.json new file mode 100644 index 0000000000..ca12633368 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/src/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ "es2015", "dom" ], + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + }, + "exclude": [ + "main-aot.ts" + ] +} diff --git a/public/docs/_examples/quickstart-lib/ts/integration/tsconfig.aot.json b/public/docs/_examples/quickstart-lib/ts/integration/tsconfig.aot.json new file mode 100644 index 0000000000..6f608e9870 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/integration/tsconfig.aot.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ + "es2015", + "dom" + ], + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + }, + "files": [ + "src/app/app.module.ts", + "src/main-aot.ts" + ], + "angularCompilerOptions": { + "genDir": "out-tsc", + "skipMetadataEmit": true + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/app/app.component.ts b/public/docs/_examples/quickstart-lib/ts/src/demo/app/app.component.ts new file mode 100644 index 0000000000..89e1ab8db0 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/app/app.component.ts @@ -0,0 +1,17 @@ +// #docregion +import { Component } from '@angular/core'; +import { LibService } from 'angular-quickstart-lib'; + +@Component({ + selector: 'demo-app', + template: ` + +

Meaning is: {{meaning}}

+ `, +}) +export class AppComponent { + meaning: number; + constructor(libService: LibService) { + this.meaning = libService.getMeaning(); + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/app/app.module.ts b/public/docs/_examples/quickstart-lib/ts/src/demo/app/app.module.ts new file mode 100644 index 0000000000..9e35226eaf --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/app/app.module.ts @@ -0,0 +1,13 @@ +// #docregion +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { LibModule } from 'angular-quickstart-lib'; + +import { AppComponent } from './app.component'; + +@NgModule({ + imports: [ BrowserModule, LibModule], + declarations: [ AppComponent ], + bootstrap: [ AppComponent ] +}) +export class AppModule { } diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/favicon.ico b/public/docs/_examples/quickstart-lib/ts/src/demo/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8081c7ceaf2be08bf59010158c586170d9d2d517 GIT binary patch literal 5430 zcmc(je{54#6vvCoAI3i*G5%$U7!sA3wtMZ$fH6V9C`=eXGJb@R1%(I_{vnZtpD{6n z5Pl{DmxzBDbrB>}`90e12m8T*36WoeDLA&SD_hw{H^wM!cl_RWcVA!I+x87ee975; z@4kD^=bYPn&pmG@(+JZ`rqQEKxW<}RzhW}I!|ulN=fmjVi@x{p$cC`)5$a!)X&U+blKNvN5tg=uLvuLnuqRM;Yc*swiexsoh#XPNu{9F#c`G zQLe{yWA(Y6(;>y|-efAy11k<09(@Oo1B2@0`PtZSkqK&${ zgEY}`W@t{%?9u5rF?}Y7OL{338l*JY#P!%MVQY@oqnItpZ}?s z!r?*kwuR{A@jg2Chlf0^{q*>8n5Ir~YWf*wmsh7B5&EpHfd5@xVaj&gqsdui^spyL zB|kUoblGoO7G(MuKTfa9?pGH0@QP^b#!lM1yHWLh*2iq#`C1TdrnO-d#?Oh@XV2HK zKA{`eo{--^K&MW66Lgsktfvn#cCAc*(}qsfhrvOjMGLE?`dHVipu1J3Kgr%g?cNa8 z)pkmC8DGH~fG+dlrp(5^-QBeEvkOvv#q7MBVLtm2oD^$lJZx--_=K&Ttd=-krx(Bb zcEoKJda@S!%%@`P-##$>*u%T*mh+QjV@)Qa=Mk1?#zLk+M4tIt%}wagT{5J%!tXAE;r{@=bb%nNVxvI+C+$t?!VJ@0d@HIyMJTI{vEw0Ul ze(ha!e&qANbTL1ZneNl45t=#Ot??C0MHjjgY8%*mGisN|S6%g3;Hlx#fMNcL<87MW zZ>6moo1YD?P!fJ#Jb(4)_cc50X5n0KoDYfdPoL^iV`k&o{LPyaoqMqk92wVM#_O0l z09$(A-D+gVIlq4TA&{1T@BsUH`Bm=r#l$Z51J-U&F32+hfUP-iLo=jg7Xmy+WLq6_tWv&`wDlz#`&)Jp~iQf zZP)tu>}pIIJKuw+$&t}GQuqMd%Z>0?t%&BM&Wo^4P^Y z)c6h^f2R>X8*}q|bblAF?@;%?2>$y+cMQbN{X$)^R>vtNq_5AB|0N5U*d^T?X9{xQnJYeU{ zoZL#obI;~Pp95f1`%X3D$Mh*4^?O?IT~7HqlWguezmg?Ybq|7>qQ(@pPHbE9V?f|( z+0xo!#m@Np9PljsyxBY-UA*{U*la#8Wz2sO|48_-5t8%_!n?S$zlGe+NA%?vmxjS- zHE5O3ZarU=X}$7>;Okp(UWXJxI%G_J-@IH;%5#Rt$(WUX?6*Ux!IRd$dLP6+SmPn= z8zjm4jGjN772R{FGkXwcNv8GBcZI#@Y2m{RNF_w8(Z%^A*!bS*!}s6sh*NnURytky humW;*g7R+&|Ledvc- + + + Angular QuickStart + + + + + + + + + + + + + + + + + Loading AppComponent content here ... + + diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/main.ts b/public/docs/_examples/quickstart-lib/ts/src/demo/main.ts new file mode 100644 index 0000000000..311c44b76d --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/main.ts @@ -0,0 +1,5 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/styles.css b/public/docs/_examples/quickstart-lib/ts/src/demo/styles.css new file mode 100644 index 0000000000..58e1a7d9a4 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/styles.css @@ -0,0 +1,5 @@ +h1 { + color: #369; + font-family: Arial, Helvetica, sans-serif; + font-size: 250%; +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/systemjs.config.js b/public/docs/_examples/quickstart-lib/ts/src/demo/systemjs.config.js new file mode 100644 index 0000000000..5ef7111444 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/systemjs.config.js @@ -0,0 +1,43 @@ +/** + * System configuration for Angular samples + * Adjust as necessary for your application needs. + */ +(function (global) { + System.config({ + paths: { + // paths serve as alias + 'npm:': 'node_modules/' + }, + // map tells the System loader where to look for things + map: { + // our app is within the app folder + app: 'app', + + // angular bundles + '@angular/core': 'npm:@angular/core/bundles/core.umd.js', + '@angular/common': 'npm:@angular/common/bundles/common.umd.js', + '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', + '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', + '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', + '@angular/http': 'npm:@angular/http/bundles/http.umd.js', + '@angular/router': 'npm:@angular/router/bundles/router.umd.js', + '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', + + // other libraries + 'rxjs': 'npm:rxjs', + }, + // packages tells the System loader how to load when no filename and/or no extension + packages: { + app: { + defaultExtension: 'js' + }, + rxjs: { + defaultExtension: 'js' + }, + 'angular-quickstart-lib': { + main: 'index.js', + defaultExtension: 'js' + } + } + }); +})(this); diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/tsconfig.json b/public/docs/_examples/quickstart-lib/ts/src/demo/tsconfig.json new file mode 100644 index 0000000000..02677b7a4a --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "", + "module": "commonjs", + "declaration": false, + "emitDecoratorMetadata": true, + "paths": { + "angular-quickstart-lib": [ + "../lib" + ] + } + }, + "exclude": [ + "main-aot.ts" + ] +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/demo/typings.d.ts b/public/docs/_examples/quickstart-lib/ts/src/demo/typings.d.ts new file mode 100644 index 0000000000..ef5c7bd620 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/demo/typings.d.ts @@ -0,0 +1,5 @@ +/* SystemJS module definition */ +declare var module: NodeModule; +interface NodeModule { + id: string; +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/angular-quickstart-lib.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/angular-quickstart-lib.ts new file mode 100644 index 0000000000..97332ad928 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/angular-quickstart-lib.ts @@ -0,0 +1,7 @@ +// This file should have the same name as the project in package.json. +// This file is not used to build this module. It is only used during editing +// by the TypeScript language service and during build for verification. `ngc` +// replaces this file with production index.ts when it rewrites private symbol +// names. + +export * from './index'; diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.css b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.html b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.html new file mode 100644 index 0000000000..20fc08a99d --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.html @@ -0,0 +1 @@ +

Hello {{name}}

diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.spec.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.spec.ts new file mode 100644 index 0000000000..9858d043e7 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.spec.ts @@ -0,0 +1,33 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { LibComponent } from './lib.component'; + +describe('LibComponent', function () { + let de: DebugElement; + let comp: LibComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [LibComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LibComponent); + comp = fixture.componentInstance; + de = fixture.debugElement.query(By.css('h2')); + }); + + it('should create component', () => expect(comp).toBeDefined()); + + it('should have expected

text', () => { + fixture.detectChanges(); + const h2 = de.nativeElement; + expect(h2.innerText).toMatch(/angular/i, + '

should say something about "Angular"'); + }); +}); diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.ts new file mode 100644 index 0000000000..3a3a6ff2f4 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/component/lib.component.ts @@ -0,0 +1,12 @@ +// #docregion +import { Component } from '@angular/core'; + +@Component({ + moduleId: module.id, + selector: 'my-lib', + templateUrl: './lib.component.html', + styleUrls: ['./lib.component.css'] +}) +export class LibComponent { + name = 'Angular Library'; +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/index.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/index.ts new file mode 100644 index 0000000000..78b98c7519 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/index.ts @@ -0,0 +1,4 @@ +// #docregion +export { LibComponent } from './component/lib.component'; +export { LibService } from './service/lib.service'; +export { LibModule } from './module'; diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/module.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/module.ts new file mode 100644 index 0000000000..384e04b4eb --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/module.ts @@ -0,0 +1,12 @@ +// #docregion +import { NgModule } from '@angular/core'; + +import { LibComponent } from './component/lib.component'; +import { LibService } from './service/lib.service'; + +@NgModule({ + declarations: [LibComponent], + providers: [LibService], + exports: [LibComponent] +}) +export class LibModule { } diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.spec.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.spec.ts new file mode 100644 index 0000000000..b7e4fdab70 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.spec.ts @@ -0,0 +1,19 @@ +import { TestBed, inject } from '@angular/core/testing'; + +import { LibService } from './lib.service'; + +describe('LibService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [LibService] + }); + }); + + it('should create service', inject([LibService], (service: LibService) => { + expect(service).toBeTruthy(); + })); + + it('should return 42 from getMeaning', inject([LibService], (service: LibService) => { + expect(service.getMeaning()).toBe(42); + })); +}); diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.ts new file mode 100644 index 0000000000..7c5807a827 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/service/lib.service.ts @@ -0,0 +1,8 @@ +// #docregion +import { Injectable } from '@angular/core'; + +@Injectable() +export class LibService { + constructor() { } + getMeaning() { return 42; } +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.es2015.json b/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.es2015.json new file mode 100644 index 0000000000..ab65f9a18e --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.es2015.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib-es2015/", + "target": "es2015" + }, + "files": [ + "./index.ts", + "./typings.d.ts" + ], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "flatModuleOutFile": "angular-quickstart-lib.js", + "flatModuleId": "angular-quickstart-lib", + "genDir": "../../out-tsc/lib-gen-dir/" + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.json b/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.json new file mode 100644 index 0000000000..dbce619c43 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./", + "outDir": "../../out-tsc/lib/", + "baseUrl": "", + "types": [] + }, + "files": [ + "./index.ts", + "./typings.d.ts" + ], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "flatModuleOutFile": "angular-quickstart-lib.js", + "flatModuleId": "angular-quickstart-lib", + "genDir": "../../out-tsc/lib-gen-dir/" + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.spec.json b/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.spec.json new file mode 100644 index 0000000000..f1bcaf32a1 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "", + "module": "commonjs", + "declaration": false, + "emitDecoratorMetadata": true + } +} diff --git a/public/docs/_examples/quickstart-lib/ts/src/lib/typings.d.ts b/public/docs/_examples/quickstart-lib/ts/src/lib/typings.d.ts new file mode 100644 index 0000000000..ef5c7bd620 --- /dev/null +++ b/public/docs/_examples/quickstart-lib/ts/src/lib/typings.d.ts @@ -0,0 +1,5 @@ +/* SystemJS module definition */ +declare var module: NodeModule; +interface NodeModule { + id: string; +} diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 7c38e075ee..019a008383 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -23,7 +23,7 @@ include ../_util-fns [Setup a local development environment](#setup-a-local-development-environment) - [What's in the QuickStart Library seed?](#whats-in-the-quickStart-library-seed) + [What's in the QuickStart Library seed?](#what-s-in-the-quickstart-library-seed-) [Entry points](#entry-points) From d38aedc186f04552ff34e9ca5b4d48faebd4fd1c Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Wed, 22 Mar 2017 18:22:03 +0000 Subject: [PATCH 19/31] remove unused changes --- public/docs/_examples/_boilerplate/package.json | 1 - .../_boilerplate/src/systemjs.config.js | 3 +-- .../upgrade-phonecat-2-hybrid/ts/tsconfig.json | 3 +-- .../third-party-lib/third-party-lib.png | Bin 58016 -> 0 bytes 4 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 public/resources/images/cookbooks/third-party-lib/third-party-lib.png diff --git a/public/docs/_examples/_boilerplate/package.json b/public/docs/_examples/_boilerplate/package.json index d7866e6665..2e4bc19f91 100644 --- a/public/docs/_examples/_boilerplate/package.json +++ b/public/docs/_examples/_boilerplate/package.json @@ -25,7 +25,6 @@ "build:cli": "ng build --no-progress", "serve:cli": "http-server dist/", "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js", - "build:aot:jit": "npm run build:aot && npm run tsc", "serve:aot": "lite-server -c bs-config.aot.json", "start:webpack": "webpack-dev-server --inline --progress --port 8080", "test:webpack": "karma start karma.webpack.conf.js", diff --git a/public/docs/_examples/_boilerplate/src/systemjs.config.js b/public/docs/_examples/_boilerplate/src/systemjs.config.js index 6d062ef918..ea7a3879ac 100644 --- a/public/docs/_examples/_boilerplate/src/systemjs.config.js +++ b/public/docs/_examples/_boilerplate/src/systemjs.config.js @@ -31,8 +31,7 @@ // other libraries 'rxjs': 'npm:rxjs', - 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js', - 'hero-profile': 'npm:hero-profile/bundles/hero-profile.umd.js' + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json index 2dfccc22d1..f267800f14 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/tsconfig.json @@ -16,7 +16,6 @@ "compileOnSave": true, "exclude": [ "node_modules/*", - "**/*-aot.ts", - "app-aot" + "**/*-aot.ts" ] } diff --git a/public/resources/images/cookbooks/third-party-lib/third-party-lib.png b/public/resources/images/cookbooks/third-party-lib/third-party-lib.png deleted file mode 100644 index 525a27b88d696a4f8b096dae454c2e03a2c1f8a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58016 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 From 2e9bfbdaf81016bb8f024d7d6356b3f189317988 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Thu, 23 Mar 2017 10:20:34 +0000 Subject: [PATCH 20/31] spelling --- public/docs/ts/latest/cookbook/third-party-lib.jade | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index 019a008383..b436482a42 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -3,7 +3,7 @@ include ../_util-fns :marked Libraries are the backbone of the Angular ecosystem. They add functionality that would otherwise take a long time to implement from scratch and keep it up to date. - Everyone benifits from a healthy library ecosystem. + Everyone benefits from a healthy library ecosystem. Traditionally, third party JavaScript libraries have been published in the form of a single JavaScript file. Consumers of the library have then included the library, "as is", somewhere on the page using a `script` tag. @@ -216,7 +216,7 @@ table(width="100%") Both [Ahead-of-time](#appendix-supporting-aot) and [Just-in-time](#appendix-supporting-it) compilation should be supported. - It's daunting to think of all the ways your library might be used and how to accomodate it, + It's daunting to think of all the ways your library might be used and how to accommodate it, but you don't need to have a "one-size-fits-all" library. You can configure `package.json` with more entry points besides [main](https://docs.npmjs.com/files/package.json#main). @@ -405,7 +405,7 @@ code-example(language="json"). :marked ## Appendix: Supporting JIT - AOT compiled code is the prefered format for production builds, but due to the long compilation time, it may not be practical to use AOT during development. + AOT compiled code is the preferred format for production builds, but due to the long compilation time, it may not be practical to use AOT during development. To create a more flexible developer experience, a JIT compatible build of the library should be published as well. The format of the JIT bundle is `umd`, which stands for Universal Module Definition. Shipping the bundle as `umd` ensures compatibility with most common module loading formats. From 97a7df0e78bdb3596416ea7d3bbf7be4064f8f73 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Thu, 23 Mar 2017 10:25:05 +0000 Subject: [PATCH 21/31] line breaks --- .../ts/latest/cookbook/third-party-lib.jade | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index b436482a42..b385e1b871 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -2,16 +2,21 @@ include ../_util-fns :marked Libraries are the backbone of the Angular ecosystem. - They add functionality that would otherwise take a long time to implement from scratch and keep it up to date. + They add functionality that would otherwise take a long time to implement from scratch and keep + up to date. Everyone benefits from a healthy library ecosystem. - Traditionally, third party JavaScript libraries have been published in the form of a single JavaScript file. - Consumers of the library have then included the library, "as is", somewhere on the page using a `script` tag. + Traditionally, third party JavaScript libraries have been published in the form of a single + JavaScript file. + Consumers of the library have then included the library, "as is", somewhere on the page using a + `script` tag. Modern web development has changed this process. - Instead of publishing a "one size fits all" bundle, developers want to only include the parts of the library they actually need and in the format they need it in. + Instead of publishing a "one size fits all" bundle, developers want to only include the parts of + the library they actually need and in the format they need it in. - This cookbook shows how to publish a third party library in a way that makes it possible to take advantage of techniques like Ahead of Time Compilation (AOT) and Tree Shaking. + This cookbook shows how to publish a third party library in a way that makes it possible to + fully benefit from techniques like Ahead of Time Compilation (AOT) and Tree Shaking. .alert.is-important :marked @@ -357,7 +362,8 @@ code-example(language="json"). Only code written in TypeScript can be AOT compiled. Before publishing the library must first be compiled using the `ngc` compiler. - `ngc` extends the `tsc` compiler by adding extensions to support AOT compilation in addition to regular TypeScript compilation. + `ngc` extends the `tsc` compiler by adding extensions to support AOT compilation in addition to + regular TypeScript compilation. AOT compilation outputs three files that must be included in order to be compatible with AOT. @@ -367,8 +373,8 @@ code-example(language="json"). *Typings files* - JavaScript has no way of representing typings. In order to preserve the original typings, `ngc` - will generate `.d.ts` typings files. + JavaScript has no way of representing typings. + In order to preserve the original typings, `ngc` will generate `.d.ts` typings files. *Meta Data JSON files* @@ -405,11 +411,16 @@ code-example(language="json"). :marked ## Appendix: Supporting JIT - AOT compiled code is the preferred format for production builds, but due to the long compilation time, it may not be practical to use AOT during development. + AOT compiled code is the preferred format for production builds, but due to the long compilation + time, it may not be practical to use AOT during development. - To create a more flexible developer experience, a JIT compatible build of the library should be published as well. The format of the JIT bundle is `umd`, which stands for Universal Module Definition. Shipping the bundle as `umd` ensures compatibility with most common module loading formats. + To create a more flexible developer experience, a JIT compatible build of the library should be + published as well. The format of the JIT bundle is `umd`, which stands for Universal Module + Definition. + Shipping the bundle as `umd` ensures compatibility with most common module loading formats. - The `umd` bundle will ship as a single file containing ES5 JavaScript and inlined versions of any external templates or css. + The `umd` bundle will ship as a single file containing ES5 JavaScript and inlined versions of + any external templates or css. .l-main-section From 24455bc8e755f3a3949c8dd9f6e8d079739f135e Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Thu, 23 Mar 2017 13:42:57 +0000 Subject: [PATCH 22/31] emphasize package format over starter --- .../ts/latest/cookbook/third-party-lib.jade | 110 +++++++++--------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/public/docs/ts/latest/cookbook/third-party-lib.jade b/public/docs/ts/latest/cookbook/third-party-lib.jade index b385e1b871..be1f80e375 100644 --- a/public/docs/ts/latest/cookbook/third-party-lib.jade +++ b/public/docs/ts/latest/cookbook/third-party-lib.jade @@ -26,12 +26,12 @@ include ../_util-fns :marked ## Table of contents + [Library package format](#library-package-format) + [Setup a local development environment](#setup-a-local-development-environment) [What's in the QuickStart Library seed?](#what-s-in-the-quickstart-library-seed-) - [Entry points](#entry-points) - [The build step](#the-build-step) [Testing libraries](#testing-libraries) @@ -44,14 +44,64 @@ include ../_util-fns [Appendix: Dependency Management](#appendix-dependency-management) - TODO finish this .l-main-section :marked - ## Setup a local development environment + ## Library package format + + In order to understand how to build and publish a library, you have to consider _how_ the library is going to be consumed. + + Some users need to add it as a `