├── .editorconfig ├── .gitignore ├── 1-events-demo ├── .editorconfig ├── .gitignore ├── README.md ├── nodemon.json ├── package.json ├── src │ ├── app │ │ └── app.component.ts │ ├── client.ts │ ├── index.html │ ├── server.ts │ └── typings.d.ts ├── tsconfig.json ├── typings.json └── webpack.config.js ├── 2-async-demo ├── .editorconfig ├── .gitignore ├── README.md ├── nodemon.json ├── package.json ├── src │ ├── app │ │ └── app.component.ts │ ├── client.ts │ ├── index.html │ ├── server.ts │ └── typings.d.ts ├── tsconfig.json ├── typings.json └── webpack.config.js ├── 3-di-demo ├── .editorconfig ├── .gitignore ├── README.md ├── nodemon.json ├── package.json ├── src │ ├── app │ │ └── app.component.ts │ ├── client.ts │ ├── index.html │ ├── server.ts │ ├── typings.d.ts │ └── universal-store │ │ ├── package.json │ │ └── src │ │ ├── backend │ │ ├── browser-backend.ts │ │ └── node-backend.ts │ │ ├── browser.ts │ │ ├── node.ts │ │ └── store.ts ├── tsconfig.json ├── typings.json └── webpack.config.js └── async-timeout.ts.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /__build__ 2 | /__server_build__ 3 | /node_modules 4 | /typings 5 | /tsd_typings/ 6 | npm-debug.log 7 | 8 | /dist/ 9 | 10 | .idea 11 | -------------------------------------------------------------------------------- /1-events-demo/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /1-events-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /__build__ 2 | /__server_build__ 3 | /node_modules 4 | /typings 5 | /tsd_typings/ 6 | npm-debug.log 7 | 8 | /dist/ 9 | 10 | .idea 11 | -------------------------------------------------------------------------------- /1-events-demo/README.md: -------------------------------------------------------------------------------- 1 | # ng-conf 2016 Angular 2 Universal Patterns 2 | > universal patterns for Angular 2 3 | -------------------------------------------------------------------------------- /1-events-demo/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": [ 3 | "dist", 4 | "package.json", 5 | "src/index.html" 6 | ], 7 | "ext" : "js ts json html" 8 | } 9 | -------------------------------------------------------------------------------- /1-events-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-conf-2016-universal-patterns", 3 | "version": "2.0.0", 4 | "description": "ng-conf 2016 universal patterns", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/angular/ng-conf-2016-universal-patterns.git" 8 | }, 9 | "scripts": { 10 | "postinstall": "typings install", 11 | "watch": "webpack --watch", 12 | "prebuild": "rimraf dist", 13 | "build": "webpack", 14 | "prestart": "npm run build", 15 | "server": "nodemon dist/server/bundle.js", 16 | "start": "npm run server", 17 | "predebug": "npm run build", 18 | "debug": "node --debug-brk dist/server/bundle.js" 19 | }, 20 | "license": "MIT", 21 | "contributors": [ 22 | "PatrickJS ", 23 | "Jeff Whelpley " 24 | ], 25 | "dependencies": { 26 | "angular2": "2.0.0-beta.17", 27 | "angular2-universal": "~0.99.0", 28 | "angular2-universal-polyfills": "~0.4.1", 29 | "angular2-express-engine": "0.11.1", 30 | "angular2-hapi-engine": "0.11.1", 31 | "body-parser": "^1.15.0", 32 | "express": "^4.13.4", 33 | "preboot": "~2.0.10", 34 | "rxjs": "5.0.0-beta.6" 35 | }, 36 | "devDependencies": { 37 | "json-loader": "^0.5.4", 38 | "nodemon": "^1.8.1", 39 | "rimraf": "^2.5.0", 40 | "ts-loader": "^0.8.1", 41 | "typescript": "^1.8.7", 42 | "typings": "~0.8.1", 43 | "webpack": "^1.12.10", 44 | "webpack-dev-server": "^1.14.0", 45 | "webpack-merge": "^0.8.4" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /1-events-demo/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from 'angular2/core'; 2 | 3 | const IGNORE_KEY_CODE = [8, 13, 16, 17, 91]; 4 | 5 | @Component({ 6 | selector: 'app', 7 | template: ` 8 | 9 | 10 |
11 |
Key pressed: {{key}}
12 |
13 | ` 14 | }) 15 | export class App { 16 | keys: string[] = []; 17 | 18 | showKey(event) { 19 | let keyCode = event.keyCode; 20 | 21 | if (IGNORE_KEY_CODE.indexOf(keyCode) < 0) { 22 | this.keys.push(String.fromCharCode(keyCode).toLowerCase()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /1-events-demo/src/client.ts: -------------------------------------------------------------------------------- 1 | import 'angular2-universal/polyfills'; 2 | 3 | import { 4 | bootstrap, 5 | enableProdMode 6 | } from 'angular2-universal'; 7 | 8 | import {App} from './app/app.component'; 9 | 10 | enableProdMode(); 11 | 12 | function main() { 13 | // preboot: true in server.ts 14 | bootstrap(App) 15 | .then(setClientRenderedEl); 16 | 17 | } 18 | 19 | // setTimeout(main, 4000); 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | (window).runBootstrap = function () { 42 | bootstrap(App) 43 | .then(setClientRenderedEl) 44 | .then(compRef => { 45 | (window).runBootstrap = () => {}; 46 | return compRef; 47 | }); 48 | }; 49 | 50 | function setClientRenderedEl(componentRef) { 51 | document.querySelector('.server').innerHTML = ''; 52 | document.querySelector('.client').innerHTML = 'Client Rendered'; 53 | document.querySelector('.replayBtn').setAttribute('style', 'background-color:#36434b;'); 54 | 55 | var bootstrapBtn = document.querySelector('.bootstrapBtn'); 56 | bootstrapBtn.innerHTML = 'Bootstrapped'; 57 | bootstrapBtn.setAttribute('style', 'color:rgba(26,138,182,1);background-color:#fff'); 58 | return componentRef; 59 | } 60 | 61 | var origReplayEvents = (window).replayEvents; 62 | 63 | (window).replayEvents = function () { 64 | origReplayEvents(); 65 | var replayBtn = document.querySelector('.replayBtn'); 66 | replayBtn.innerHTML = 'Replayed'; 67 | replayBtn.setAttribute('style', 'color:rgba(26,138,182,1);background-color:#fff'); 68 | }; 69 | -------------------------------------------------------------------------------- /1-events-demo/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular 2 Universal Starter 5 | 6 | 7 | 8 | 9 | 10 | 11 | 24 | 54 | 55 | 56 | 57 |

Current View: Server Rendered

58 |
59 | 60 | 61 |
62 | 63 | 64 | Loading... 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /1-events-demo/src/server.ts: -------------------------------------------------------------------------------- 1 | import 'angular2-universal/polyfills'; 2 | 3 | import * as path from 'path'; 4 | import * as express from 'express'; 5 | import * as bodyParser from 'body-parser'; 6 | 7 | // Angular 2 Universal 8 | import { 9 | provide, 10 | expressEngine, 11 | ORIGIN_URL, 12 | enableProdMode 13 | } from 'angular2-universal'; 14 | 15 | // Application 16 | import {App} from './app/app.component'; 17 | 18 | enableProdMode(); 19 | const app = express(); 20 | const ROOT = path.join(path.resolve(__dirname, '..')); 21 | 22 | // Express View 23 | app.engine('.html', expressEngine); 24 | app.set('views', __dirname); 25 | app.set('view engine', 'html'); 26 | 27 | function ngApp(req, res) { 28 | res.render('index', { 29 | directives: [ App ], 30 | platformProviders: [ 31 | provide(ORIGIN_URL, {useValue: 'http://localhost:3000'}) 32 | ], 33 | 34 | preboot: false 35 | 36 | 37 | }); 38 | } 39 | 40 | // Serve static files 41 | app.use(express.static(ROOT, {index: false})); 42 | 43 | 44 | // Routes with html5pushstate 45 | app.use('/', ngApp); 46 | 47 | // Server 48 | app.listen(3000, () => { 49 | console.log('Listen on http://localhost:3000'); 50 | }); 51 | -------------------------------------------------------------------------------- /1-events-demo/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Custom Type Definitions 3 | * When including 3rd party modules you also need to include the type definition for the module 4 | * if they don't provide one within the module. You can try to install it with typings 5 | typings install node --save 6 | * If you can't find the type definition in the registry we can make an ambient definition in 7 | * this file for now. For example 8 | declare module "my-module" { 9 | export function doesSomething(value: string): string; 10 | } 11 | * 12 | * If you're prototying and you will fix the types later you can also declare it as type any 13 | * 14 | declare var assert: any; 15 | * 16 | * If you're importing a module that uses Node.js modules which are CommonJS you need to import as 17 | * 18 | import * as _ from 'lodash' 19 | * You can include your type definitions in this file until you create one for the typings registry 20 | * see https://github.com/typings/registry 21 | * 22 | */ 23 | 24 | 25 | // Extra variables that live on Global that will be replaced by webpack DefinePlugin 26 | declare var ENV: string; 27 | declare var HMR: boolean; 28 | interface GlobalEnvironment { 29 | ENV; 30 | HMR; 31 | } 32 | 33 | interface WebpackModule { 34 | hot: { 35 | data?: any, 36 | idle: any, 37 | accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; 38 | decline(dependencies?: string | string[]): void; 39 | dispose(callback?: (data?: any) => void): void; 40 | addDisposeHandler(callback?: (data?: any) => void): void; 41 | removeDisposeHandler(callback?: (data?: any) => void): void; 42 | check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; 43 | apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; 44 | status(callback?: (status?: string) => void): void | string; 45 | removeStatusHandler(callback?: (status?: string) => void): void; 46 | }; 47 | } 48 | 49 | interface WebpackRequire { 50 | context(file: string, flag?: boolean, exp?: RegExp): any; 51 | } 52 | 53 | 54 | interface ErrorStackTraceLimit { 55 | stackTraceLimit: number; 56 | } 57 | 58 | 59 | // Extend typings 60 | interface NodeRequire extends WebpackRequire {} 61 | interface ErrorConstructor extends ErrorStackTraceLimit {} 62 | interface NodeModule extends WebpackModule {} 63 | interface Global extends GlobalEnvironment {} 64 | 65 | 66 | interface Thenable { 67 | then( 68 | onFulfilled?: (value: T) => U | Thenable, 69 | onRejected?: (error: any) => U | Thenable): Thenable; 70 | then( 71 | onFulfilled?: (value: T) => U | Thenable, 72 | onRejected?: (error: any) => void): Thenable; 73 | catch(onRejected?: (error: any) => U | Thenable): Thenable; 74 | } 75 | -------------------------------------------------------------------------------- /1-events-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "target": "es5", 6 | "module": "commonjs", 7 | "removeComments": true, 8 | "sourceMap": true 9 | }, 10 | "exclude": [ 11 | "typings/main.d.ts", 12 | "typings/main", 13 | "node_modules" 14 | ], 15 | "compileOnSave": false, 16 | "buildOnSave": false, 17 | "atom": { "rewriteTsconfig": false } 18 | } 19 | -------------------------------------------------------------------------------- /1-events-demo/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientDependencies": { 3 | "body-parser": "registry:dt/body-parser#0.0.0+20160317120654", 4 | "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", 5 | "express": "registry:dt/express#4.0.0+20160317120654", 6 | "express-serve-static-core": "registry:dt/express-serve-static-core#0.0.0+20160322035842", 7 | "mime": "registry:dt/mime#0.0.0+20160316155526", 8 | "node": "registry:dt/node#4.0.0+20160412142033", 9 | "serve-static": "registry:dt/serve-static#0.0.0+20160317120654" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /1-events-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | var commonConfig = { 5 | resolve: { 6 | extensions: ['', '.ts', '.js', '.json'] 7 | }, 8 | module: { 9 | loaders: [ 10 | // TypeScript 11 | { test: /\.ts$/, loader: 'ts-loader' }, 12 | { test: /\.json$/, loader: 'json-loader' } 13 | ] 14 | }, 15 | plugins: [ 16 | new webpack.optimize.OccurenceOrderPlugin(true) 17 | ] 18 | }; 19 | 20 | 21 | var clientConfig = { 22 | target: 'web', 23 | entry: './src/client', 24 | output: { 25 | path: path.join(__dirname, 'dist', 'client') 26 | }, 27 | node: { 28 | global: true, 29 | __dirname: true, 30 | __filename: true, 31 | process: true, 32 | Buffer: false 33 | } 34 | }; 35 | 36 | 37 | var serverConfig = { 38 | target: 'node', 39 | entry: './src/server', 40 | output: { 41 | path: path.join(__dirname, 'dist', 'server') 42 | }, 43 | externals: checkNodeImport, 44 | node: { 45 | global: true, 46 | __dirname: true, 47 | __filename: true, 48 | process: true, 49 | Buffer: true 50 | } 51 | }; 52 | 53 | 54 | 55 | 56 | 57 | // Default config 58 | var defaultConfig = { 59 | output: { 60 | publicPath: path.resolve(__dirname), 61 | filename: 'bundle.js' 62 | }, 63 | module: { 64 | noParse: [ 65 | path.join(__dirname, 'zone.js', 'dist'), 66 | path.join(__dirname, 'angular2', 'bundles') 67 | ] 68 | }, 69 | context: __dirname, 70 | resolve: { 71 | root: path.join(__dirname, '/src') 72 | } 73 | }; 74 | 75 | 76 | var webpackMerge = require('webpack-merge'); 77 | module.exports = [ 78 | // Client 79 | webpackMerge({}, defaultConfig, commonConfig, clientConfig), 80 | 81 | // Server 82 | webpackMerge({}, defaultConfig, commonConfig, serverConfig) 83 | ]; 84 | 85 | 86 | 87 | 88 | // Helpers 89 | function checkNodeImport(context, request, cb) { 90 | if (!path.isAbsolute(request) && request.charAt(0) !== '.') { 91 | cb(null, 'commonjs ' + request); return; 92 | } 93 | cb(); 94 | } 95 | -------------------------------------------------------------------------------- /2-async-demo/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /2-async-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /__build__ 2 | /__server_build__ 3 | /node_modules 4 | /typings 5 | /tsd_typings/ 6 | npm-debug.log 7 | 8 | /dist/ 9 | 10 | .idea 11 | -------------------------------------------------------------------------------- /2-async-demo/README.md: -------------------------------------------------------------------------------- 1 | # ng-conf 2016 Angular 2 Universal Patterns 2 | > universal patterns for Angular 2 3 | -------------------------------------------------------------------------------- /2-async-demo/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": [ 3 | "dist", 4 | "src/index.html" 5 | ], 6 | "ext" : "js ts json html" 7 | } 8 | -------------------------------------------------------------------------------- /2-async-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-conf-2016-universal-patterns", 3 | "version": "2.0.0", 4 | "description": "ng-conf 2016 universal patterns", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/angular/ng-conf-2016-universal-patterns.git" 8 | }, 9 | "scripts": { 10 | "postinstall": "typings install", 11 | "watch": "webpack --watch", 12 | "prebuild": "rimraf dist", 13 | "build": "webpack", 14 | "prestart": "npm run build", 15 | "server": "nodemon dist/server/bundle.js", 16 | "start": "npm run server", 17 | "predebug": "npm run build", 18 | "debug": "node --debug-brk dist/server/bundle.js" 19 | }, 20 | "license": "MIT", 21 | "contributors": [ 22 | "PatrickJS ", 23 | "Jeff Whelpley " 24 | ], 25 | "dependencies": { 26 | "angular2": "2.0.0-beta.17", 27 | "angular2-universal": "~0.99.0", 28 | "angular2-universal-polyfills": "~0.4.1", 29 | "angular2-express-engine": "0.11.1", 30 | "angular2-hapi-engine": "0.11.1", 31 | "body-parser": "^1.15.0", 32 | "express": "^4.13.3", 33 | "preboot": "~2.0.10", 34 | "rxjs": "5.0.0-beta.6" 35 | }, 36 | "devDependencies": { 37 | "json-loader": "^0.5.4", 38 | "nodemon": "^1.8.1", 39 | "rimraf": "^2.5.0", 40 | "ts-loader": "^0.8.1", 41 | "typescript": "^1.8.7", 42 | "typings": "~0.8.1", 43 | "webpack": "^1.12.10", 44 | "webpack-dev-server": "^1.14.0", 45 | "webpack-merge": "^0.8.4" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /2-async-demo/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, Directive, ElementRef, Renderer} from 'angular2/core'; 2 | import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; 3 | import {Http} from 'angular2/http'; 4 | 5 | 6 | @Directive({ 7 | selector: '[x-large]' 8 | }) 9 | export class XLarge { 10 | constructor(element: ElementRef, renderer: Renderer) { 11 | // we must interact with the dom through Renderer for webworker/server to see the changes 12 | renderer.setElementStyle(element.nativeElement, 'fontSize', 'x-large'); 13 | } 14 | } 15 | 16 | 17 | @Component({ 18 | selector: 'home', 19 | template: ` 20 | Home 21 | ` 22 | }) 23 | export class Home { 24 | } 25 | 26 | @Component({ 27 | selector: 'about', 28 | template: ` 29 | About 30 | ` 31 | }) 32 | export class About { 33 | } 34 | 35 | 36 | @Component({ 37 | selector: 'app', 38 | directives: [ 39 | ...ROUTER_DIRECTIVES, 40 | XLarge 41 | ], 42 | styles: [` 43 | .router-link-active { 44 | background-color: lightgray; 45 | } 46 | `], 47 | template: ` 48 |
49 | 53 |
54 | Hello, {{ name }}! 55 |
56 | 57 | name: 58 |
{{ data | json }}
59 | 60 |
61 | 62 |
63 | 64 |

{{ serverMessage }}

65 | 66 |
67 | ` 68 | }) 69 | @RouteConfig([ 70 | { path: '/', component: Home, name: 'Home', useAsDefault: true }, 71 | { path: '/home', component: Home, name: 'Home' }, 72 | { path: '/about', component: About, name: 'About' }, 73 | { path: '/**', redirectTo: ['Home'] } 74 | ]) 75 | export class App { 76 | name: string = 'Angular 2'; 77 | data = {}; 78 | serverMessage = 'setTimeout not Rendered'; 79 | constructor(public http: Http) { 80 | 81 | } 82 | ngOnInit() { 83 | 84 | setTimeout(() => { 85 | this.serverMessage = 86 | 'setTimeout Rendered'; 87 | }, 10); 88 | 89 | this.http.get('/data.json') 90 | .subscribe(res => { 91 | this.data = res.json(); 92 | }); 93 | 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /2-async-demo/src/client.ts: -------------------------------------------------------------------------------- 1 | import 'angular2-universal/polyfills'; 2 | 3 | import { 4 | bootstrap, 5 | enableProdMode, 6 | BROWSER_ROUTER_PROVIDERS, 7 | BROWSER_HTTP_PROVIDERS 8 | } from 'angular2-universal'; 9 | 10 | import {App} from './app/app.component'; 11 | 12 | enableProdMode(); 13 | 14 | function main() { 15 | return bootstrap(App, [ 16 | ...BROWSER_ROUTER_PROVIDERS, 17 | ...BROWSER_HTTP_PROVIDERS 18 | ]) 19 | .then(setClientRenderedEl); 20 | } 21 | 22 | setTimeout(() => main(), 2000); 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | function setClientRenderedEl(componentRef) { 35 | document.querySelector('.server').innerHTML = ''; 36 | document.querySelector('.client').innerHTML = 'Client Rendered'; 37 | document.querySelector('.replayBtn').setAttribute('style', 'background-color:#36434b;'); 38 | 39 | return componentRef; 40 | } 41 | -------------------------------------------------------------------------------- /2-async-demo/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular 2 Universal Starter 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 26 | 27 | 28 | 29 |

Current View: Server Rendered

30 | 31 | 32 | Loading... 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /2-async-demo/src/server.ts: -------------------------------------------------------------------------------- 1 | import 'angular2-universal/polyfills'; 2 | 3 | import * as path from 'path'; 4 | import * as express from 'express'; 5 | import * as bodyParser from 'body-parser'; 6 | 7 | // Angular 2 Universal 8 | import { 9 | provide, 10 | enableProdMode, 11 | expressEngine, 12 | REQUEST_URL, 13 | ORIGIN_URL, 14 | BASE_URL, 15 | NODE_ROUTER_PROVIDERS, 16 | NODE_HTTP_PROVIDERS, 17 | ExpressEngineConfig 18 | } from 'angular2-universal'; 19 | 20 | // Application 21 | import {App} from './app/app.component'; 22 | 23 | const app = express(); 24 | const ROOT = path.join(path.resolve(__dirname, '..')); 25 | 26 | enableProdMode(); 27 | 28 | // Express View 29 | app.engine('.html', expressEngine); 30 | app.set('views', __dirname); 31 | app.set('view engine', 'html'); 32 | 33 | app.use(bodyParser.json()); 34 | 35 | 36 | function ngApp(req, res) { 37 | let baseUrl = '/'; 38 | let url = req.originalUrl || '/'; 39 | 40 | let config: ExpressEngineConfig = { 41 | directives: [ App ], 42 | platformProviders: [ 43 | provide(ORIGIN_URL, {useValue: 'http://localhost:3000'}), 44 | provide(BASE_URL, {useValue: baseUrl}), 45 | ], 46 | providers: [ 47 | provide(REQUEST_URL, {useValue: url}), 48 | NODE_ROUTER_PROVIDERS, 49 | NODE_HTTP_PROVIDERS, 50 | ], 51 | 52 | async: false, 53 | 54 | preboot: false 55 | }; 56 | 57 | res.render('index', config); 58 | } 59 | 60 | // Serve static files 61 | app.use(express.static(ROOT, {index: false})); 62 | 63 | // Our API for demos only 64 | app.get('/data.json', (req, res) => { 65 | res.json({ 66 | data: 'fake data' 67 | }); 68 | }); 69 | 70 | // Routes with html5pushstate 71 | app.use('/', ngApp); 72 | app.use('/about', ngApp); 73 | app.use('/home', ngApp); 74 | 75 | // Server 76 | app.listen(3000, () => { 77 | console.log('Listen on http://localhost:3000'); 78 | }); 79 | -------------------------------------------------------------------------------- /2-async-demo/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Custom Type Definitions 3 | * When including 3rd party modules you also need to include the type definition for the module 4 | * if they don't provide one within the module. You can try to install it with typings 5 | typings install node --save 6 | * If you can't find the type definition in the registry we can make an ambient definition in 7 | * this file for now. For example 8 | declare module "my-module" { 9 | export function doesSomething(value: string): string; 10 | } 11 | * 12 | * If you're prototying and you will fix the types later you can also declare it as type any 13 | * 14 | declare var assert: any; 15 | * 16 | * If you're importing a module that uses Node.js modules which are CommonJS you need to import as 17 | * 18 | import * as _ from 'lodash' 19 | * You can include your type definitions in this file until you create one for the typings registry 20 | * see https://github.com/typings/registry 21 | * 22 | */ 23 | 24 | 25 | // Extra variables that live on Global that will be replaced by webpack DefinePlugin 26 | declare var ENV: string; 27 | declare var HMR: boolean; 28 | interface GlobalEnvironment { 29 | ENV; 30 | HMR; 31 | } 32 | 33 | interface WebpackModule { 34 | hot: { 35 | data?: any, 36 | idle: any, 37 | accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; 38 | decline(dependencies?: string | string[]): void; 39 | dispose(callback?: (data?: any) => void): void; 40 | addDisposeHandler(callback?: (data?: any) => void): void; 41 | removeDisposeHandler(callback?: (data?: any) => void): void; 42 | check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; 43 | apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; 44 | status(callback?: (status?: string) => void): void | string; 45 | removeStatusHandler(callback?: (status?: string) => void): void; 46 | }; 47 | } 48 | 49 | interface WebpackRequire { 50 | context(file: string, flag?: boolean, exp?: RegExp): any; 51 | } 52 | 53 | 54 | interface ErrorStackTraceLimit { 55 | stackTraceLimit: number; 56 | } 57 | 58 | 59 | // Extend typings 60 | interface NodeRequire extends WebpackRequire {} 61 | interface ErrorConstructor extends ErrorStackTraceLimit {} 62 | interface NodeModule extends WebpackModule {} 63 | interface Global extends GlobalEnvironment {} 64 | 65 | 66 | interface Thenable { 67 | then( 68 | onFulfilled?: (value: T) => U | Thenable, 69 | onRejected?: (error: any) => U | Thenable): Thenable; 70 | then( 71 | onFulfilled?: (value: T) => U | Thenable, 72 | onRejected?: (error: any) => void): Thenable; 73 | catch(onRejected?: (error: any) => U | Thenable): Thenable; 74 | } 75 | -------------------------------------------------------------------------------- /2-async-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "target": "es5", 6 | "module": "commonjs", 7 | "removeComments": true, 8 | "sourceMap": true 9 | }, 10 | "exclude": [ 11 | "typings/main.d.ts", 12 | "typings/main", 13 | "node_modules" 14 | ], 15 | "compileOnSave": false, 16 | "buildOnSave": false, 17 | "atom": { "rewriteTsconfig": false } 18 | } 19 | -------------------------------------------------------------------------------- /2-async-demo/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientDependencies": { 3 | "body-parser": "registry:dt/body-parser#0.0.0+20160317120654", 4 | "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", 5 | "express": "registry:dt/express#4.0.0+20160317120654", 6 | "express-serve-static-core": "registry:dt/express-serve-static-core#0.0.0+20160322035842", 7 | "mime": "registry:dt/mime#0.0.0+20160316155526", 8 | "node": "registry:dt/node#4.0.0+20160412142033", 9 | "serve-static": "registry:dt/serve-static#0.0.0+20160317120654" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /2-async-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | var commonConfig = { 5 | resolve: { 6 | extensions: ['', '.ts', '.js', '.json'] 7 | }, 8 | module: { 9 | loaders: [ 10 | // TypeScript 11 | { test: /\.ts$/, loader: 'ts-loader' }, 12 | { test: /\.json$/, loader: 'json-loader' } 13 | ] 14 | }, 15 | plugins: [ 16 | new webpack.optimize.OccurenceOrderPlugin(true) 17 | ] 18 | }; 19 | 20 | 21 | var clientConfig = { 22 | target: 'web', 23 | entry: './src/client', 24 | output: { 25 | path: path.join(__dirname, 'dist', 'client') 26 | }, 27 | node: { 28 | global: true, 29 | __dirname: true, 30 | __filename: true, 31 | process: true, 32 | Buffer: false 33 | } 34 | }; 35 | 36 | 37 | var serverConfig = { 38 | target: 'node', 39 | entry: './src/server', 40 | output: { 41 | path: path.join(__dirname, 'dist', 'server') 42 | }, 43 | externals: checkNodeImport, 44 | node: { 45 | global: true, 46 | __dirname: true, 47 | __filename: true, 48 | process: true, 49 | Buffer: true 50 | } 51 | }; 52 | 53 | 54 | 55 | 56 | 57 | // Default config 58 | var defaultConfig = { 59 | output: { 60 | publicPath: path.resolve(__dirname), 61 | filename: 'bundle.js' 62 | }, 63 | module: { 64 | noParse: [ 65 | path.join(__dirname, 'zone.js', 'dist'), 66 | path.join(__dirname, 'angular2', 'bundles') 67 | ] 68 | }, 69 | context: __dirname, 70 | resolve: { 71 | root: path.join(__dirname, '/src') 72 | } 73 | } 74 | 75 | 76 | var webpackMerge = require('webpack-merge'); 77 | module.exports = [ 78 | // Client 79 | webpackMerge({}, defaultConfig, commonConfig, clientConfig), 80 | 81 | // Server 82 | webpackMerge({}, defaultConfig, commonConfig, serverConfig) 83 | ] 84 | 85 | 86 | 87 | 88 | // Helpers 89 | function checkNodeImport(context, request, cb) { 90 | if (!path.isAbsolute(request) && request.charAt(0) !== '.') { 91 | cb(null, 'commonjs ' + request); return; 92 | } 93 | cb(); 94 | } 95 | -------------------------------------------------------------------------------- /3-di-demo/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /3-di-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /__build__ 2 | /__server_build__ 3 | /node_modules 4 | /typings 5 | /tsd_typings/ 6 | npm-debug.log 7 | 8 | /dist/ 9 | 10 | .idea 11 | -------------------------------------------------------------------------------- /3-di-demo/README.md: -------------------------------------------------------------------------------- 1 | # ng-conf 2016 Angular 2 Universal Patterns 2 | > universal patterns for Angular 2 3 | -------------------------------------------------------------------------------- /3-di-demo/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": [ 3 | "dist", 4 | "src/index.html" 5 | ], 6 | "ext" : "js ts json html" 7 | } 8 | -------------------------------------------------------------------------------- /3-di-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-conf-2016-universal-patterns", 3 | "version": "2.0.0", 4 | "description": "ng-conf 2016 universal patterns", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/angular/ng-conf-2016-universal-patterns.git" 8 | }, 9 | "scripts": { 10 | "postinstall": "typings install", 11 | "watch": "webpack --watch", 12 | "prebuild": "rimraf dist", 13 | "build": "webpack", 14 | "prestart": "npm run build", 15 | "server": "nodemon dist/server/bundle.js", 16 | "start": "npm run server", 17 | "predebug": "npm run build", 18 | "debug": "node --debug-brk dist/server/bundle.js" 19 | }, 20 | "license": "MIT", 21 | "contributors": [ 22 | "PatrickJS ", 23 | "Jeff Whelpley " 24 | ], 25 | "dependencies": { 26 | "angular2": "2.0.0-beta.17", 27 | "angular2-universal": "~0.99.0", 28 | "angular2-universal-polyfills": "~0.4.1", 29 | "angular2-express-engine": "0.11.1", 30 | "angular2-hapi-engine": "0.11.1", 31 | "body-parser": "^1.15.0", 32 | "express": "^4.13.3", 33 | "preboot": "~2.0.10", 34 | "rxjs": "5.0.0-beta.6" 35 | }, 36 | "devDependencies": { 37 | "json-loader": "^0.5.4", 38 | "nodemon": "^1.8.1", 39 | "rimraf": "^2.5.0", 40 | "ts-loader": "^0.8.1", 41 | "typescript": "^1.8.7", 42 | "typings": "~0.8.1", 43 | "webpack": "^1.12.10", 44 | "webpack-dev-server": "^1.14.0", 45 | "webpack-merge": "^0.8.4" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /3-di-demo/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from 'angular2/core'; 2 | import {FORM_DIRECTIVES} from 'angular2/common'; 3 | import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; 4 | import {Http} from 'angular2/http'; 5 | 6 | 7 | import {Store} from '../universal-store/src/store'; 8 | 9 | 10 | @Component({ 11 | selector: 'home', 12 | template: ` 13 | Home 14 | ` 15 | }) 16 | export class Home { 17 | } 18 | 19 | @Component({ 20 | selector: 'about', 21 | template: ` 22 | About 23 | ` 24 | }) 25 | export class About { 26 | } 27 | 28 | 29 | @Component({ 30 | selector: 'app', 31 | directives: [ 32 | ...ROUTER_DIRECTIVES, 33 | ...FORM_DIRECTIVES 34 | ], 35 | styles: [` 36 | .router-link-active { 37 | background-color: lightgray; 38 | } 39 | `], 40 | template: ` 41 |
42 | 46 | 47 |
48 | 52 |
53 | 54 | 55 |
56 | 57 |
58 | 59 |
this.data = {{ data | json }}
60 |
this.store.get('data') = {{ store.get('data') | json }}
61 | 62 |
63 | ` 64 | }) 65 | @RouteConfig([ 66 | { path: '/', component: Home, name: 'Home', useAsDefault: true }, 67 | { path: '/home', component: Home, name: 'Home' }, 68 | { path: '/about', component: About, name: 'About' }, 69 | { path: '/**', redirectTo: ['Home'] } 70 | ]) 71 | export class App { 72 | data = 'ng-conf'; 73 | // doesn't work on server 74 | store = { 75 | get(prop) { 76 | return localStorage.getItem(prop); 77 | }, 78 | set(prop, value) { 79 | return localStorage.setItem(prop, value); 80 | } 81 | }; 82 | constructor( 83 | // public store: Store 84 | ) { 85 | 86 | } 87 | 88 | onSubmit() { 89 | this.store.set('data', this.data); 90 | this.data = ''; 91 | } 92 | 93 | 94 | } 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | @Component({ 108 | selector: 'app', 109 | template: 'Loading...' 110 | }) 111 | export class Noop {} 112 | -------------------------------------------------------------------------------- /3-di-demo/src/client.ts: -------------------------------------------------------------------------------- 1 | import 'angular2-universal/polyfills'; 2 | 3 | import { 4 | bootstrap, 5 | enableProdMode, 6 | BROWSER_ROUTER_PROVIDERS, 7 | BROWSER_HTTP_PROVIDERS 8 | } from 'angular2-universal'; 9 | 10 | import { 11 | BROWSER_STORE_PROVIDERS 12 | } from './universal-store/src/browser'; 13 | 14 | import {App} from './app/app.component'; 15 | 16 | enableProdMode(); 17 | 18 | 19 | bootstrap(App, [ 20 | ...BROWSER_ROUTER_PROVIDERS, 21 | ...BROWSER_HTTP_PROVIDERS, 22 | 23 | ...BROWSER_STORE_PROVIDERS 24 | 25 | ]) 26 | .then(setClientRenderedEl); 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | function setClientRenderedEl(compRef) { 38 | document.querySelector('.server').innerHTML = ''; 39 | document.querySelector('.client').innerHTML = 'Client Rendered'; 40 | document.querySelector('.replayBtn').setAttribute('style', 'background-color:#36434b;'); 41 | 42 | return compRef; 43 | } 44 | -------------------------------------------------------------------------------- /3-di-demo/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular 2 Universal Starter 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 26 | 27 | 28 | 29 |

Current View: Server Rendered

30 | 31 | 32 | Loading... 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /3-di-demo/src/server.ts: -------------------------------------------------------------------------------- 1 | import 'angular2-universal/polyfills'; 2 | 3 | import * as path from 'path'; 4 | import * as express from 'express'; 5 | import * as bodyParser from 'body-parser'; 6 | 7 | // Angular 2 Universal 8 | import { 9 | provide, 10 | enableProdMode, 11 | expressEngine, 12 | REQUEST_URL, 13 | ORIGIN_URL, 14 | BASE_URL, 15 | NODE_ROUTER_PROVIDERS, 16 | NODE_HTTP_PROVIDERS, 17 | ExpressEngineConfig 18 | } from 'angular2-universal'; 19 | 20 | import {NODE_STORE_PROVIDERS} from './universal-store/src/node'; 21 | 22 | // Application 23 | import {App, Noop} from './app/app.component'; 24 | 25 | const app = express(); 26 | const ROOT = path.join(path.resolve(__dirname, '..')); 27 | 28 | enableProdMode(); 29 | 30 | // Express View 31 | app.engine('.html', expressEngine); 32 | app.set('views', __dirname); 33 | app.set('view engine', 'html'); 34 | 35 | app.use(bodyParser.json()); 36 | 37 | 38 | function ngApp(req, res) { 39 | let baseUrl = '/'; 40 | let url = req.originalUrl || '/'; 41 | 42 | let config: ExpressEngineConfig = { 43 | // directives: [ Noop ], 44 | directives: [ App ], 45 | platformProviders: [ 46 | provide(ORIGIN_URL, {useValue: 'http://localhost:3000'}), 47 | provide(BASE_URL, {useValue: baseUrl}), 48 | ], 49 | providers: [ 50 | provide(REQUEST_URL, {useValue: url}), 51 | ...NODE_ROUTER_PROVIDERS, 52 | ...NODE_HTTP_PROVIDERS, 53 | ...NODE_STORE_PROVIDERS 54 | ], 55 | async: true, 56 | preboot: true 57 | }; 58 | 59 | res.render('index', config); 60 | } 61 | 62 | // Serve static files 63 | app.use(express.static(ROOT, {index: false})); 64 | 65 | // Our API for demos only 66 | app.get('/data.json', (req, res) => { 67 | res.json({ 68 | data: 'fake data' 69 | }); 70 | }); 71 | 72 | // Routes with html5pushstate 73 | app.use('/', ngApp); 74 | app.use('/about', ngApp); 75 | app.use('/home', ngApp); 76 | 77 | // Server 78 | app.listen(3000, () => { 79 | console.log('Listen on http://localhost:3000'); 80 | }); 81 | -------------------------------------------------------------------------------- /3-di-demo/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Custom Type Definitions 3 | * When including 3rd party modules you also need to include the type definition for the module 4 | * if they don't provide one within the module. You can try to install it with typings 5 | typings install node --save 6 | * If you can't find the type definition in the registry we can make an ambient definition in 7 | * this file for now. For example 8 | declare module "my-module" { 9 | export function doesSomething(value: string): string; 10 | } 11 | * 12 | * If you're prototying and you will fix the types later you can also declare it as type any 13 | * 14 | declare var assert: any; 15 | * 16 | * If you're importing a module that uses Node.js modules which are CommonJS you need to import as 17 | * 18 | import * as _ from 'lodash' 19 | * You can include your type definitions in this file until you create one for the typings registry 20 | * see https://github.com/typings/registry 21 | * 22 | */ 23 | 24 | 25 | // Extra variables that live on Global that will be replaced by webpack DefinePlugin 26 | declare var ENV: string; 27 | declare var HMR: boolean; 28 | interface GlobalEnvironment { 29 | ENV; 30 | HMR; 31 | } 32 | 33 | interface WebpackModule { 34 | hot: { 35 | data?: any, 36 | idle: any, 37 | accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; 38 | decline(dependencies?: string | string[]): void; 39 | dispose(callback?: (data?: any) => void): void; 40 | addDisposeHandler(callback?: (data?: any) => void): void; 41 | removeDisposeHandler(callback?: (data?: any) => void): void; 42 | check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; 43 | apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; 44 | status(callback?: (status?: string) => void): void | string; 45 | removeStatusHandler(callback?: (status?: string) => void): void; 46 | }; 47 | } 48 | 49 | interface WebpackRequire { 50 | context(file: string, flag?: boolean, exp?: RegExp): any; 51 | } 52 | 53 | 54 | interface ErrorStackTraceLimit { 55 | stackTraceLimit: number; 56 | } 57 | 58 | 59 | // Extend typings 60 | interface NodeRequire extends WebpackRequire {} 61 | interface ErrorConstructor extends ErrorStackTraceLimit {} 62 | interface NodeModule extends WebpackModule {} 63 | interface Global extends GlobalEnvironment {} 64 | 65 | 66 | interface Thenable { 67 | then( 68 | onFulfilled?: (value: T) => U | Thenable, 69 | onRejected?: (error: any) => U | Thenable): Thenable; 70 | then( 71 | onFulfilled?: (value: T) => U | Thenable, 72 | onRejected?: (error: any) => void): Thenable; 73 | catch(onRejected?: (error: any) => U | Thenable): Thenable; 74 | } 75 | -------------------------------------------------------------------------------- /3-di-demo/src/universal-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "./node.js", 3 | "browser": "./browser.js", 4 | "scripts": { 5 | "build": "tsc || true" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /3-di-demo/src/universal-store/src/backend/browser-backend.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | export class BrowserBackend { 6 | getValue(prop) { 7 | return window.localStorage.getItem(prop); 8 | } 9 | setValue(prop, value) { 10 | return window.localStorage.setItem(prop, value); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /3-di-demo/src/universal-store/src/backend/node-backend.ts: -------------------------------------------------------------------------------- 1 | // or redis 2 | export var inMemoryStore = { 3 | data: 'ng-conf 2016' 4 | }; 5 | 6 | 7 | export class NodeBackend { 8 | getValue(prop) { 9 | return inMemoryStore[prop] || null; 10 | } 11 | setValue(prop, value) { 12 | return inMemoryStore[prop] = value; 13 | } 14 | } 15 | 16 | 17 | // App, 18 | -------------------------------------------------------------------------------- /3-di-demo/src/universal-store/src/browser.ts: -------------------------------------------------------------------------------- 1 | import {BrowserBackend} from './backend/browser-backend'; 2 | import {Store, StoreBackend} from './store'; 3 | 4 | import {provide} from 'angular2/core'; 5 | // Store -> StoreBackend == BrowserBackend 6 | export const BROWSER_STORE_PROVIDERS = [ 7 | BrowserBackend, 8 | provide(StoreBackend, {useClass: BrowserBackend}), 9 | Store 10 | ]; 11 | -------------------------------------------------------------------------------- /3-di-demo/src/universal-store/src/node.ts: -------------------------------------------------------------------------------- 1 | import {NodeBackend} from './backend/node-backend'; 2 | import {Store, StoreBackend} from './store'; 3 | 4 | import {provide} from 'angular2/core'; 5 | 6 | export const NODE_STORE_PROVIDERS = [ 7 | NodeBackend, 8 | provide(StoreBackend, {useClass: NodeBackend}), 9 | Store 10 | ]; 11 | -------------------------------------------------------------------------------- /3-di-demo/src/universal-store/src/store.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from 'angular2/core'; 2 | 3 | export class StoreBackend { 4 | getValue(key: string): any { 5 | throw new Error('Error getValue on Backend'); 6 | } 7 | setValue(key: string, value: any): any { 8 | throw new Error('Error setValue on Backend'); 9 | } 10 | } 11 | // Store -> StoreBackend 12 | @Injectable() 13 | export class Store { 14 | constructor(public backend: StoreBackend) {} 15 | 16 | get(key) { 17 | return this.backend.getValue(key); 18 | } 19 | 20 | set(key, value) { 21 | return this.backend.setValue(key, value); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /3-di-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "target": "es5", 6 | "module": "commonjs", 7 | "removeComments": true, 8 | "sourceMap": true 9 | }, 10 | "exclude": [ 11 | "typings/main.d.ts", 12 | "typings/main", 13 | "node_modules" 14 | ], 15 | "compileOnSave": false, 16 | "buildOnSave": false, 17 | "atom": { "rewriteTsconfig": false } 18 | } 19 | -------------------------------------------------------------------------------- /3-di-demo/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientDependencies": { 3 | "body-parser": "registry:dt/body-parser#0.0.0+20160317120654", 4 | "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", 5 | "express": "registry:dt/express#4.0.0+20160317120654", 6 | "express-serve-static-core": "registry:dt/express-serve-static-core#0.0.0+20160322035842", 7 | "mime": "registry:dt/mime#0.0.0+20160316155526", 8 | "node": "registry:dt/node#4.0.0+20160412142033", 9 | "serve-static": "registry:dt/serve-static#0.0.0+20160317120654" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /3-di-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | var commonConfig = { 5 | resolve: { 6 | extensions: ['', '.ts', '.js', '.json'] 7 | }, 8 | module: { 9 | loaders: [ 10 | // TypeScript 11 | { test: /\.ts$/, loader: 'ts-loader' }, 12 | { test: /\.json$/, loader: 'json-loader' } 13 | ] 14 | }, 15 | plugins: [ 16 | new webpack.optimize.OccurenceOrderPlugin(true) 17 | ] 18 | }; 19 | 20 | 21 | var clientConfig = { 22 | target: 'web', 23 | entry: './src/client', 24 | output: { 25 | path: path.join(__dirname, 'dist', 'client') 26 | }, 27 | node: { 28 | global: true, 29 | __dirname: true, 30 | __filename: true, 31 | process: true, 32 | Buffer: false 33 | } 34 | }; 35 | 36 | 37 | var serverConfig = { 38 | target: 'node', 39 | entry: './src/server', 40 | output: { 41 | path: path.join(__dirname, 'dist', 'server') 42 | }, 43 | externals: checkNodeImport, 44 | node: { 45 | global: true, 46 | __dirname: true, 47 | __filename: true, 48 | process: true, 49 | Buffer: true 50 | } 51 | }; 52 | 53 | 54 | 55 | 56 | 57 | // Default config 58 | var defaultConfig = { 59 | output: { 60 | publicPath: path.resolve(__dirname), 61 | filename: 'bundle.js' 62 | }, 63 | module: { 64 | noParse: [ 65 | path.join(__dirname, 'zone.js', 'dist'), 66 | path.join(__dirname, 'angular2', 'bundles') 67 | ] 68 | }, 69 | context: __dirname, 70 | resolve: { 71 | root: path.join(__dirname, '/src') 72 | } 73 | } 74 | 75 | 76 | var webpackMerge = require('webpack-merge'); 77 | module.exports = [ 78 | // Client 79 | webpackMerge({}, defaultConfig, commonConfig, clientConfig), 80 | 81 | // Server 82 | webpackMerge({}, defaultConfig, commonConfig, serverConfig) 83 | ] 84 | 85 | 86 | 87 | 88 | // Helpers 89 | function checkNodeImport(context, request, cb) { 90 | if (!path.isAbsolute(request) && request.charAt(0) !== '.') { 91 | cb(null, 'commonjs ' + request); return; 92 | } 93 | cb(); 94 | } 95 | -------------------------------------------------------------------------------- /async-timeout.ts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var count = 0; 4 | var nativeSetTimeout = setTimeout; 5 | 6 | function wrapSetTimeout(fn, delay) { 7 | count++; 8 | setTimeout(() => { 9 | count--; 10 | fn(); 11 | }, delay); 12 | } 13 | 14 | global.setTimeout = wrapSetTimeout; 15 | 16 | 17 | function checkCount() { 18 | return count <= 0; 19 | } 20 | 21 | 22 | // [checkStable, task, task, checkStable] 23 | function waitForAsync(value) { 24 | 25 | var awaitForMe = new Promise(resolve => { 26 | 27 | function checkStable() { 28 | nativeSetTimeout(() => { 29 | var isStable = checkCount(); 30 | 31 | if (isStable) { 32 | return resolve(value); 33 | } else { 34 | checkStable(); 35 | } 36 | 37 | }); 38 | } 39 | checkStable(); 40 | 41 | }); 42 | 43 | return awaitForMe; 44 | } 45 | 46 | 47 | 48 | .platform() 49 | .application() 50 | .then(() => waitForAsync) 51 | .bootstrap() 52 | .then(); 53 | 54 | 55 | 56 | 57 | 58 | // nope 59 | --------------------------------------------------------------------------------