diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json index c77600eed5..bd2d26bb50 100644 --- a/public/docs/_examples/package.json +++ b/public/docs/_examples/package.json @@ -13,48 +13,64 @@ "tsc": "tsc", "tsc:w": "tsc -w", "typings": "typings", - "webdriver:update": "webdriver-manager update" + "webdriver:update": "webdriver-manager update", + "start:webpack": "webpack-dev-server --inline --progress --port 8080", + "test:webpack": "karma start karma.webpack.conf.js", + "build:webpack": "rm -rf dist && webpack --config config/webpack.prod.js --progress --profile --bail" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { - "@angular/common": "2.0.0-rc.1", - "@angular/compiler": "2.0.0-rc.1", - "@angular/core": "2.0.0-rc.1", - "@angular/http": "2.0.0-rc.1", - "@angular/platform-browser": "2.0.0-rc.1", - "@angular/platform-browser-dynamic": "2.0.0-rc.1", - "@angular/router": "2.0.0-rc.1", - "@angular/router-deprecated": "2.0.0-rc.1", - "@angular/upgrade": "2.0.0-rc.1", - + "@angular/common": "2.0.0-rc.1", + "@angular/compiler": "2.0.0-rc.1", + "@angular/core": "2.0.0-rc.1", + "@angular/http": "2.0.0-rc.1", + "@angular/platform-browser": "2.0.0-rc.1", + "@angular/platform-browser-dynamic": "2.0.0-rc.1", + "@angular/router": "2.0.0-rc.1", + "@angular/router-deprecated": "2.0.0-rc.1", + "@angular/upgrade": "2.0.0-rc.1", "systemjs": "0.19.27", "es6-shim": "^0.35.0", "reflect-metadata": "^0.1.3", "rxjs": "5.0.0-beta.6", "zone.js": "^0.6.12", - "angular2-in-memory-web-api": "0.0.7", "bootstrap": "^3.3.6" }, "devDependencies": { - "concurrently": "^2.0.0", - "lite-server": "^2.2.0", - "typescript": "^1.8.10", - "typings": "^0.8.1", - "canonical-path": "0.0.2", + "concurrently": "^2.0.0", + "css-loader": "^0.23.1", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.8.5", + "html-loader": "^0.4.3", + "html-webpack-plugin": "^2.16.1", "http-server": "^0.9.0", - "lodash": "^4.11.1", - "jasmine-core": "~2.4.1", + "jasmine-core": "^2.4.1", "karma": "^0.13.22", "karma-chrome-launcher": "^0.2.3", "karma-cli": "^0.1.2", "karma-htmlfile-reporter": "^0.2.2", "karma-jasmine": "^0.3.8", + "karma-phantomjs-launcher": "^1.0.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^1.7.0", + "lite-server": "^2.2.0", + "lodash": "^4.11.1", + "null-loader": "^0.1.1", + "phantomjs-prebuilt": "^2.1.7", "protractor": "^3.3.0", - "rimraf": "^2.5.2" + "raw-loader": "^0.5.1", + "rimraf": "^2.5.2", + "style-loader": "^0.13.1", + "ts-loader": "^0.8.2", + "typescript": "^1.8.10", + "typings": "^0.8.1", + "webpack": "^1.13.0", + "webpack-dev-server": "^1.14.1", + "webpack-merge": "^0.12.0" }, "repository": {} } diff --git a/public/docs/_examples/quickstart/ts/typings.1.json b/public/docs/_examples/quickstart/ts/typings.1.json index 9d5c20bc92..b5324f4199 100644 --- a/public/docs/_examples/quickstart/ts/typings.1.json +++ b/public/docs/_examples/quickstart/ts/typings.1.json @@ -1,6 +1,7 @@ { "ambientDependencies": { "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", - "jasmine": "registry:dt/jasmine#2.2.0+20160412134438" + "jasmine": "registry:dt/jasmine#2.2.0+20160412134438", + "node": "registry:dt/node#4.0.0+20160509154515" } } diff --git a/public/docs/_examples/quickstart/ts/typings.d.1.ts b/public/docs/_examples/quickstart/ts/typings.d.1.ts deleted file mode 100644 index c048cc5ec2..0000000000 --- a/public/docs/_examples/quickstart/ts/typings.d.1.ts +++ /dev/null @@ -1,14 +0,0 @@ -// #docregion -/** - * Declares the 'commonjs' format module object that identifies the "module id" for the current module. - * Set a component's `moduleId` metadata property to `module.id` for module-relative urls - * when the generated module format is 'commonjs'. - */ -declare var module: {id: string}; - -/** - * Declares the 'system' format string that identifies the "module id" for the current module. - * Set a component's `moduleId` metadata property to `__moduleName` for module-relative urls - * when the generated module format is 'system'. - */ -declare var __moduleName: string; diff --git a/public/docs/_examples/typings.json b/public/docs/_examples/typings.json index 9d5c20bc92..b5324f4199 100644 --- a/public/docs/_examples/typings.json +++ b/public/docs/_examples/typings.json @@ -1,6 +1,7 @@ { "ambientDependencies": { "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", - "jasmine": "registry:dt/jasmine#2.2.0+20160412134438" + "jasmine": "registry:dt/jasmine#2.2.0+20160412134438", + "node": "registry:dt/node#4.0.0+20160509154515" } } diff --git a/public/docs/_examples/typings/typings.d.ts b/public/docs/_examples/typings/typings.d.ts deleted file mode 100644 index 579c9a586c..0000000000 --- a/public/docs/_examples/typings/typings.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Declares the 'commonjs' format module object that identifies the "module id" for the current module. - * Set a component's `moduleId` metadata property to `module.id` for module-relative urls - * when the generated module format is 'commonjs'. - */ -declare var module: {id: string}; - -/** - * Declares the 'system' format string that identifies the "module id" for the current module. - * Set a component's `moduleId` metadata property to `__moduleName` for module-relative urls - * when the generated module format is 'system'. - */ -declare var __moduleName: string; diff --git a/public/docs/_examples/webpack/ts/.gitignore b/public/docs/_examples/webpack/ts/.gitignore new file mode 100644 index 0000000000..8628a5eef6 --- /dev/null +++ b/public/docs/_examples/webpack/ts/.gitignore @@ -0,0 +1,5 @@ +dist +!karma.webpack.conf.js +!webpack.config.js +!config/* +!public/css/styles.css diff --git a/public/docs/_examples/webpack/ts/config/helpers.js b/public/docs/_examples/webpack/ts/config/helpers.js new file mode 100644 index 0000000000..b760520f1c --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/helpers.js @@ -0,0 +1,12 @@ +// #docregion +var path = require('path'); + +var _root = path.resolve(__dirname, '..'); + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [_root].concat(args)); +} + +exports.root = root; +// #enddocregion \ No newline at end of file diff --git a/public/docs/_examples/webpack/ts/config/karma-test-shim.js b/public/docs/_examples/webpack/ts/config/karma-test-shim.js new file mode 100644 index 0000000000..7691460bcd --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/karma-test-shim.js @@ -0,0 +1,22 @@ +// #docregion +Error.stackTraceLimit = Infinity; + +require('es6-shim'); +require('reflect-metadata'); + +require('zone.js/dist/zone'); +require('zone.js/dist/long-stack-trace-zone'); +require('zone.js/dist/jasmine-patch'); +require('zone.js/dist/async-test'); + +var appContext = require.context('../src', true, /\.spec\.ts/); + +appContext.keys().forEach(appContext); + +var testing = require('@angular/core/testing'); +var browser = require('@angular/platform-browser-dynamic/testing'); + +testing.setBaseTestProviders( + browser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, + browser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS +); diff --git a/public/docs/_examples/webpack/ts/config/karma.conf.js b/public/docs/_examples/webpack/ts/config/karma.conf.js new file mode 100644 index 0000000000..3e2e34072f --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/karma.conf.js @@ -0,0 +1,39 @@ +// #docregion +var webpackConfig = require('./webpack.test'); + +module.exports = function (config) { + var _config = { + basePath: '', + + frameworks: ['jasmine'], + + files: [ + {pattern: './config/karma-test-shim.js', watched: false} + ], + + preprocessors: { + './config/karma-test-shim.js': ['webpack', 'sourcemap'] + }, + + webpack: webpackConfig, + + webpackMiddleware: { + stats: 'errors-only' + }, + + webpackServer: { + noInfo: true + }, + + reporters: ['progress'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: false, + browsers: ['PhantomJS'], + singleRun: true + }; + + config.set(_config); +}; +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/config/webpack.common.js b/public/docs/_examples/webpack/ts/config/webpack.common.js new file mode 100644 index 0000000000..07e74adc65 --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/webpack.common.js @@ -0,0 +1,64 @@ +// #docregion +var webpack = require('webpack'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var helpers = require('./helpers'); + +module.exports = { + // #docregion entries + entry: { + 'polyfills': './src/polyfills.ts', + 'vendor': './src/vendor.ts', + 'app': './src/main.ts' + }, + // #enddocregion + + // #docregion resolve + resolve: { + extensions: ['', '.js', '.ts'] + }, + // #enddocregion resolve + + // #docregion loaders + module: { + loaders: [ + { + test: /\.ts$/, + loader: 'ts' + }, + { + test: /\.html$/, + loader: 'html' + }, + { + test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, + loader: 'file?name=assets/[name].[hash].[ext]' + }, + { + test: /\.css$/, + exclude: helpers.root('src', 'app'), + loader: ExtractTextPlugin.extract('style', 'css?sourceMap') + }, + { + test: /\.css$/, + include: helpers.root('src', 'app'), + loader: 'raw' + } + ] + }, + // #enddocregion loaders + + // #docregion plugins + plugins: [ + new webpack.optimize.CommonsChunkPlugin({ + name: ['app', 'vendor', 'polyfills'] + }), + + new HtmlWebpackPlugin({ + template: 'src/index.html' + }) + ] + // #enddocregion plugins +}; +// #enddocregion + diff --git a/public/docs/_examples/webpack/ts/config/webpack.dev.js b/public/docs/_examples/webpack/ts/config/webpack.dev.js new file mode 100644 index 0000000000..c1484a0caa --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/webpack.dev.js @@ -0,0 +1,26 @@ +// #docregion +var webpackMerge = require('webpack-merge'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var commonConfig = require('./webpack.common.js'); +var helpers = require('./helpers'); + +module.exports = webpackMerge(commonConfig, { + devtool: 'cheap-module-eval-source-map', + + output: { + path: helpers.root('dist'), + publicPath: 'http://localhost:8080/', + filename: '[name].js', + chunkFilename: '[id].chunk.js' + }, + + plugins: [ + new ExtractTextPlugin('[name].css') + ], + + devServer: { + historyApiFallback: true, + stats: 'minimal' + } +}); +// #enddocregion \ No newline at end of file diff --git a/public/docs/_examples/webpack/ts/config/webpack.prod.js b/public/docs/_examples/webpack/ts/config/webpack.prod.js new file mode 100644 index 0000000000..0e897cb35a --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/webpack.prod.js @@ -0,0 +1,36 @@ +// #docregion +var webpack = require('webpack'); +var webpackMerge = require('webpack-merge'); +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var commonConfig = require('./webpack.common.js'); +var helpers = require('./helpers'); + +const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; + +module.exports = webpackMerge(commonConfig, { + devtool: 'source-map', + + output: { + path: helpers.root('dist'), + publicPath: '/', + filename: '[name].[hash].js', + chunkFilename: '[id].[hash].chunk.js' + }, + + htmlLoader: { + minimize: false // workaround for ng2 + }, + + plugins: [ + new webpack.NoErrorsPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin(), + new ExtractTextPlugin('[name].[hash].css'), + new webpack.DefinePlugin({ + 'process.env': { + 'ENV': JSON.stringify(ENV) + } + }) + ] +}); +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/config/webpack.test.js b/public/docs/_examples/webpack/ts/config/webpack.test.js new file mode 100644 index 0000000000..b38ad459bd --- /dev/null +++ b/public/docs/_examples/webpack/ts/config/webpack.test.js @@ -0,0 +1,31 @@ +// #docregion +module.exports = { + devtools: 'source-map', + + resolve: { + extensions: ['', '.ts', '.js'] + }, + + module: { + loaders: [ + { + test: /\.ts$/, + loader: 'ts' + }, + { + test: /\.html$/, + loader: 'html' + + }, + { + test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, + loader: 'null' + }, + { + test: /\.css$/, + loader: 'null' + } + ] + } +} +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/example-config.json b/public/docs/_examples/webpack/ts/example-config.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/docs/_examples/webpack/ts/karma.webpack.conf.js b/public/docs/_examples/webpack/ts/karma.webpack.conf.js new file mode 100644 index 0000000000..e2a663e8de --- /dev/null +++ b/public/docs/_examples/webpack/ts/karma.webpack.conf.js @@ -0,0 +1,2 @@ +// #docregion +module.exports = require('./config/karma.conf.js'); diff --git a/public/docs/_examples/webpack/ts/package.webpack.json b/public/docs/_examples/webpack/ts/package.webpack.json new file mode 100644 index 0000000000..51ff625d86 --- /dev/null +++ b/public/docs/_examples/webpack/ts/package.webpack.json @@ -0,0 +1,48 @@ +{ + "name": "angular2-webpack", + "version": "1.0.0", + "description": "A webpack starter for angular 2", + "scripts": { + "start": "webpack-dev-server --inline --progress --port 8080", + "test": "karma start", + "build": "rm -rf dist && webpack --config config/webpack.prod.js --progress --profile --bail", + "postinstall": "typings install" + }, + "license": "MIT", + "dependencies": { + "@angular/common": "2.0.0-rc.1", + "@angular/compiler": "2.0.0-rc.1", + "@angular/core": "2.0.0-rc.1", + "@angular/http": "2.0.0-rc.1", + "@angular/platform-browser": "2.0.0-rc.1", + "@angular/platform-browser-dynamic": "2.0.0-rc.1", + "@angular/router-deprecated": "2.0.0-rc.1", + "es6-shim": "^0.35.0", + "reflect-metadata": "0.1.2", + "rxjs": "5.0.0-beta.6", + "zone.js": "0.6.12" + }, + "devDependencies": { + "css-loader": "^0.23.1", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.8.5", + "html-loader": "^0.4.3", + "html-webpack-plugin": "^2.15.0", + "jasmine-core": "^2.4.1", + "karma": "^0.13.22", + "karma-jasmine": "^0.3.8", + "karma-phantomjs-launcher": "^1.0.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^1.7.0", + "null-loader": "^0.1.1", + "phantomjs-prebuilt": "^2.1.7", + "raw-loader": "^0.5.1", + "style-loader": "^0.13.1", + "ts-loader": "^0.8.1", + "typescript": "^1.8.9", + "typings": "^0.7.12", + "webpack": "^1.12.14", + "webpack-dev-server": "^1.14.1", + "webpack-merge": "^0.9.0" + } +} diff --git a/public/docs/_examples/webpack/ts/public/css/styles.css b/public/docs/_examples/webpack/ts/public/css/styles.css new file mode 100644 index 0000000000..2d404ff5b9 --- /dev/null +++ b/public/docs/_examples/webpack/ts/public/css/styles.css @@ -0,0 +1,6 @@ +/* #docregion */ +body { + background: #0147A7; + color: #fff; +} +/* #enddocregion */ diff --git a/public/docs/_examples/webpack/ts/public/images/angular.png b/public/docs/_examples/webpack/ts/public/images/angular.png new file mode 100644 index 0000000000..a1d9790bc3 Binary files /dev/null and b/public/docs/_examples/webpack/ts/public/images/angular.png differ diff --git a/public/docs/_examples/webpack/ts/src/app/app.component.css b/public/docs/_examples/webpack/ts/src/app/app.component.css new file mode 100644 index 0000000000..bb624c5aae --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/app/app.component.css @@ -0,0 +1,9 @@ +/* #docregion */ +main { + padding: 1em; + font-family: Arial, Helvetica, sans-serif; + text-align: center; + margin-top: 50px; + display: block; +} +/* #enddocregion */ diff --git a/public/docs/_examples/webpack/ts/src/app/app.component.html b/public/docs/_examples/webpack/ts/src/app/app.component.html new file mode 100644 index 0000000000..a333a7a72f --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/app/app.component.html @@ -0,0 +1,7 @@ + +
+

Hello from Angular 2 App with Webpack

+ + +
+ diff --git a/public/docs/_examples/webpack/ts/src/app/app.component.spec.ts b/public/docs/_examples/webpack/ts/src/app/app.component.spec.ts new file mode 100644 index 0000000000..c2e85fd099 --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/app/app.component.spec.ts @@ -0,0 +1,22 @@ +// #docregion +import { + it, + inject, + describe, + beforeEachProviders, + expect +} from '@angular/core/testing'; + +import { AppComponent } from './app.component'; + +describe('App', () => { + beforeEachProviders(() => [ + AppComponent + ]); + + it ('should work', inject([AppComponent], (app: AppComponent) => { + // Add real test here + expect(2).toBe(2); + })); +}); +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/src/app/app.component.ts b/public/docs/_examples/webpack/ts/src/app/app.component.ts new file mode 100644 index 0000000000..590e5008ec --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/app/app.component.ts @@ -0,0 +1,12 @@ +// #docregion +import { Component } from '@angular/core'; + +import '../../public/css/styles.css'; + +@Component({ + selector: 'my-app', + template: require('./app.component.html'), + styles: [require('./app.component.css')] +}) +export class AppComponent { } +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/src/app/index.ts b/public/docs/_examples/webpack/ts/src/app/index.ts new file mode 100644 index 0000000000..3b68b4c2d7 --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/app/index.ts @@ -0,0 +1,2 @@ +// #docregion +export * from './app.component.ts'; diff --git a/public/docs/_examples/webpack/ts/src/index.html b/public/docs/_examples/webpack/ts/src/index.html new file mode 100644 index 0000000000..503ea4a950 --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/index.html @@ -0,0 +1,14 @@ + + + + + + Angular With Webpack + + + + + Loading... + + + diff --git a/public/docs/_examples/webpack/ts/src/main.ts b/public/docs/_examples/webpack/ts/src/main.ts new file mode 100644 index 0000000000..132a0d17f3 --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/main.ts @@ -0,0 +1,14 @@ +// #docregion +import { bootstrap } from '@angular/platform-browser-dynamic'; +import { enableProdMode } from '@angular/core'; + +import { AppComponent } from './app'; + +// #docregion enable-prod +if (process.env.ENV === 'production') { + enableProdMode(); +} +// #enddocregion enable-prod + +bootstrap(AppComponent, []); +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/src/polyfills.ts b/public/docs/_examples/webpack/ts/src/polyfills.ts new file mode 100644 index 0000000000..617af577cf --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/polyfills.ts @@ -0,0 +1,15 @@ +// #docregion +import 'es6-shim'; +import 'reflect-metadata'; +require('zone.js/dist/zone'); + +if (process.env.ENV === 'production') { + // Production + +} else { + // Development + + Error['stackTraceLimit'] = Infinity; + + require('zone.js/dist/long-stack-trace-zone'); +} diff --git a/public/docs/_examples/webpack/ts/src/vendor.ts b/public/docs/_examples/webpack/ts/src/vendor.ts new file mode 100644 index 0000000000..1a45c91d46 --- /dev/null +++ b/public/docs/_examples/webpack/ts/src/vendor.ts @@ -0,0 +1,15 @@ +// #docregion +// Angular 2 +import '@angular/platform-browser'; +import '@angular/platform-browser-dynamic'; +import '@angular/core'; +import '@angular/common'; +import '@angular/http'; +import '@angular/router-deprecated'; + +// RxJS +import 'rxjs'; + +// Other vendors for example jQuery, Lodash or Bootstrap +// You can import js, ts, css, sass, ... +// #enddocregion diff --git a/public/docs/_examples/webpack/ts/tsconfig.1.json b/public/docs/_examples/webpack/ts/tsconfig.1.json new file mode 100644 index 0000000000..302417ff3d --- /dev/null +++ b/public/docs/_examples/webpack/ts/tsconfig.1.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + }, + "exclude": [ + "node_modules", + "typings/main", + "typings/main.d.ts" + ] +} diff --git a/public/docs/_examples/webpack/ts/typings.1.json b/public/docs/_examples/webpack/ts/typings.1.json new file mode 100644 index 0000000000..b5324f4199 --- /dev/null +++ b/public/docs/_examples/webpack/ts/typings.1.json @@ -0,0 +1,7 @@ +{ + "ambientDependencies": { + "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", + "jasmine": "registry:dt/jasmine#2.2.0+20160412134438", + "node": "registry:dt/node#4.0.0+20160509154515" + } +} diff --git a/public/docs/_examples/webpack/ts/webpack.config.js b/public/docs/_examples/webpack/ts/webpack.config.js new file mode 100644 index 0000000000..66141706fe --- /dev/null +++ b/public/docs/_examples/webpack/ts/webpack.config.js @@ -0,0 +1,3 @@ +// #docregion +module.exports = require('./config/webpack.dev.js'); +// #enddocregion \ No newline at end of file diff --git a/public/docs/dart/latest/guide/_data.json b/public/docs/dart/latest/guide/_data.json index f45e266247..fe30a34965 100644 --- a/public/docs/dart/latest/guide/_data.json +++ b/public/docs/dart/latest/guide/_data.json @@ -134,6 +134,12 @@ "hide": true }, + "webpack": { + "title": "Introduction to Webpack", + "intro": "Create your Angular 2 applications with a Webpack based tooling", + "hide": true + }, + "glossary": { "title": "Glossary", "intro": "Brief definitions of the most important words in the Angular 2 vocabulary", diff --git a/public/docs/dart/latest/guide/webpack.jade b/public/docs/dart/latest/guide/webpack.jade new file mode 100644 index 0000000000..6778b6af28 --- /dev/null +++ b/public/docs/dart/latest/guide/webpack.jade @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") diff --git a/public/docs/js/latest/guide/_data.json b/public/docs/js/latest/guide/_data.json index 4dc3cde642..62a168eae5 100644 --- a/public/docs/js/latest/guide/_data.json +++ b/public/docs/js/latest/guide/_data.json @@ -132,6 +132,12 @@ "intro": "Angular 1 applications can be incrementally upgraded to Angular 2." }, + "webpack": { + "title": "Introduction to Webpack", + "intro": "Create your Angular 2 applications with a Webpack based tooling", + "hide": true + }, + "glossary": { "title": "Glossary", "intro": "Brief definitions of the most important words in the Angular 2 vocabulary", diff --git a/public/docs/js/latest/guide/webpack.jade b/public/docs/js/latest/guide/webpack.jade new file mode 100644 index 0000000000..6778b6af28 --- /dev/null +++ b/public/docs/js/latest/guide/webpack.jade @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") diff --git a/public/docs/ts/latest/guide/_data.json b/public/docs/ts/latest/guide/_data.json index 2dc2fc92c8..f1f32bbbc6 100644 --- a/public/docs/ts/latest/guide/_data.json +++ b/public/docs/ts/latest/guide/_data.json @@ -131,6 +131,11 @@ "intro": "Angular 1 applications can be incrementally upgraded to Angular 2." }, + "webpack": { + "title": "Introduction to Webpack", + "intro": "Create your Angular 2 applications with a Webpack based tooling" + }, + "glossary": { "title": "Glossary", "intro": "Brief definitions of the most important words in the Angular 2 vocabulary", diff --git a/public/docs/ts/latest/guide/component-styles.jade b/public/docs/ts/latest/guide/component-styles.jade index 2fca0dfcce..3b58a1ec86 100644 --- a/public/docs/ts/latest/guide/component-styles.jade +++ b/public/docs/ts/latest/guide/component-styles.jade @@ -356,7 +356,7 @@ block module-id [TypeScript compiler documentation](http://www.typescriptlang.org/docs/handbook/compiler-options.html)). The variables are `__moduleName` and `module.id` respectively. - Here's an example in which we set the metadata `moduleId` with one of these variables. + Here's an example in which we set the metadata `moduleId` to `module.id`. +makeExample('component-styles/ts/app/quest-summary.component.ts','', 'app/quest-summary.component.ts') diff --git a/public/docs/ts/latest/guide/typescript-configuration.jade b/public/docs/ts/latest/guide/typescript-configuration.jade index a9c5237ecd..ad83e66967 100644 --- a/public/docs/ts/latest/guide/typescript-configuration.jade +++ b/public/docs/ts/latest/guide/typescript-configuration.jade @@ -95,14 +95,19 @@ a(id="typings") We created a `typings.json` file in the [QuickStart](../quickstart.html): +makeJson('quickstart/ts/typings.1.json', null, 'typings.json')(format=".") :marked - We identified two *typings* file in the QuickStart, the *d.ts* file for - [es6-shim](https://github.com/paulmillr/es6-shim/blob/master/README.md) - that brings ES2015/ES6 capabilities to our ES5 browsers and for the - [jasmine](http://jasmine.github.io/) test framework. + We identified three *typings* file in the QuickStart, the *d.ts* files for - QuickStart itself doesn't require these shims but many of the documentation samples do - and most of us would be disappointed if typical ES2015 features didn't work out-of-the-box - or we didn't support testing. + * [es6-shim](https://github.com/paulmillr/es6-shim/blob/master/README.md) + that brings ES2015/ES6 capabilities to our ES5 browsers + + * [jasmine](http://jasmine.github.io/) typings for the Jasmine test framework + + * [node](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/node/node.d.ts) for code that references objects in the nodejs environment; + see the [webpack](./webpack.html) chapter for an example. + + QuickStart itself doesn't require these typings but many of the documentation samples do. + Most of us would be disappointed if we couldn't code against + typical ES2015 features or support testing right out-of-the-box. We can also run the *typings* tool ourselves. The following command (re)installs the typings files, as is sometimes necessary when the `postInstall` hook fails to do so. @@ -123,18 +128,8 @@ code-example(format=""). it tells npm to pass all arguments to the right of `--` to the *typings* command. Learn about the features of the *typings* tool at its [site on github](https://github.com/typings/typings/blob/master/README.md). + :marked - ### *typings.d.ts* - In the [QuickStart](../quickstart.html) we added a custom `typings.d.ts` file to the *typings* folder. -+makeExample('quickstart/ts/typings.d.1.ts', null, 'typings/typings.d.ts')(format=".") -:marked - The `typings.d.ts` file is the place to declare so-called *ambient* objects that will be globally available at runtime. - We only need it when there is *no typings file* to declare it for us. - - This example declares objects that we need in order to tell Angular how to load templates and styles with [module-relative URLs](component-styles.html#!#relative-urls). - A module loader creates one or the other object dynamically as it loads a module. - These semi-globals are not described in any other `d.ts` file at this time so we have to declare them ourselves. - ### Typing file collisions The TypeScript compiler does not tolerate redefinition of a type. For example, it throws an error if it's given two definitions for @@ -152,7 +147,9 @@ code-example(format=""). .children .file es6-shim .children - .file es6-shim.d.ts + .file index.d.ts + .file ... + .children .file main .children @@ -160,11 +157,11 @@ code-example(format=""). .children .file es6-shim .children - .file es6-shim.d.ts + .file index.d.ts + .file ... .children .file browser.d.ts .file main.d.ts - .file typings.d.ts :marked The `es6-shim` typings are duplicated and the `browser.d.ts` and `main.d.ts` have overlapping content. diff --git a/public/docs/ts/latest/guide/webpack.jade b/public/docs/ts/latest/guide/webpack.jade new file mode 100644 index 0000000000..4cbb9bf1ba --- /dev/null +++ b/public/docs/ts/latest/guide/webpack.jade @@ -0,0 +1,463 @@ +include ../_util-fns + +:marked + [**Webpack**](https://webpack.github.io/) is a popular module bundler, + a tool for bundling application source code in convenient _chunks_ + and for loading that code from a server into a browser. + + It's an excellent alternative to the *SystemJS* approach we use throughout the documentation. + In this guide we get a taste of Webpack and how to use it with Angular 2 applications. + + + ## Table of contents + + [What is Webpack?](#what-is-webpack) + + * [Entries and outputs](#entries-outputs) + * [Loaders](#loaders) + * [Plugins](#plugins) + + [Configuring Webpack](#configure-webpack) + + * [Common configuration](#common-configuration) + * [Development configuration](#development-configuration) + * [Production configuration](#production-configuration) + * [Test configuration](#test-configuration) + + [Trying it out](#try) + + [Conclusions](#conclusions) + +.l-main-section + +:marked + ## What is Webpack? + + Webpack is a powerful module bundler. + A _bundle_ is a JavaScript file that incorporate _assets_ that *belong* together and + should be served to the client in a response to a single file request. + A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file. + + Webpack roams over your application source code, + looking for `import` statements, building a dependency graph, and emitting one (or more) _bundles_. + With plugin "loaders" Webpack can preprocess and minify different non-JavaScript files such as TypeScript, SASS, and LESS files. + + We determine what Webpack does and how it does it with a JavaScript configuration file, `webpack.config.js`. + +a(id="entries-outputs") +.l-main-section +:marked + ### Entries and outputs + + We feed Webpack with one or more *entry* files and let it find and incorporate the dependencies that radiate from those entries. + In this example, we start from the application's root file, `src/app.ts`: + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'one-entry', 'webpack.config.js (single entry)')(format=".") + +:marked + Webpack inspects that file and traverses its `import` dependencies recursively. + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'app-example', 'src/app.ts')(format=".") + +:marked + Here it sees that we're importing *@angular/core* so it adds that to its dependency list for (potential) inclusion in the bundle. + It opens *@angular/core* and follows _its_ network of `import` statements until it has build the complete dependency graph from `app.ts` down. + + Then it **outputs** these files to the `app.js` _bundle file_ designated in configuration: + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'one-output', 'webpack.config.js (single output)')(format=".") + +:marked + This `app.js` output bundle is a single JavaScript file that contains our application source and its dependencies. + We'll load it later with a <script> tag in our index.html. + + #### Multiple bundles + We probably do not want one giant bundle of everything. + We'll likely prefer to separate our volatile application app code from comparatively stable vendor code modules. + + We change the configuration so that we have two entry points, `app.ts` and `vendor.ts`: + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'two-entries','webpack.config.js (two entries)')(format=".") +:marked + Webpack constructs two separate dependency graphs + and emits *two* bundle files, one called `app.js` containing only our application code and + another called `vendor.js` with all the vendor dependencies. + +.l-sub-section + :marked + The `[name]` in the output name is a Webpack *placeholder* that is replaced with the entry names. + `app` and `vendor` respectively. + + We need a plugin to make this work; we'll [cover that later](#commons-chunk-plugin) in the chapter. + +:marked + We met `app.ts` earlier. We wrote `vendor.ts` such that it imports the vendor modules we need: ++makeExample('webpack/ts/src/vendor.ts', null,'src/vendor.ts')(format=".") + + +a(id="loaders") +.l-main-section +:marked + ### Loaders + + Webpack can bundle any kind of file: JavaScript, TypeScript, CSS, SASS, LESS, images, html, fonts, whatever. + Webpack itself doesn't know what to do with a non-JavaScript file. + We teach it to process such files into JavaScript with *loaders*. + Here we configure loaders for TypeScript and CSS: + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'loaders', 'webpack.config.js (two entries)')(format=".") + +:marked + As Webpack encounters `import` statements like these ... + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'imports')(format=".") + +:marked + ... it applies the `test` RegEx patterns. When a pattern matches the filename, Webpack processes the file with the associated loader. + + The first `import` file matches the `.ts` pattern so Webpack processes it with the `ts` (TypeScript) loader. + The imported file doesn't match the second pattern so its loader is ignored. + + The second `import` matches the second `.css` pattern for which we have *two* loaders chained by the (!) character. + Webpack applies chained loaders *right to left* so it applies + the `css` loader first (to flatten CSS `@import` and `url(...)` statements) and + then the `style` loader (to append the css inside *<style>* elements on the page). + +a(id="plugins") +.l-main-section +:marked + ### Plugins + + Webpack has a build pipeline with well-defined phases. + We tap into that pipeline with plugins such as the `uglify` minification plugin: + ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'plugins')(format=".") + +a(id="configure-webpack") +.l-main-section +:marked + ## Configure Webpack + + After that brief orientation, we are ready to build our own Webpack configuration for Angular 2 apps. + + Begin by setting up the development environment. + + Create a **new project folder** +code-example(format=""). + mkdir angular2-webpack + cd angular2-webpack + +:marked + Add these files to the root directory: + ++makeTabs( + `webpack/ts/package.webpack.json, + webpack/ts/typings.1.json, + webpack/ts/tsconfig.1.json, + webpack/ts/webpack.config.js, + webpack/ts/karma.webpack.conf.js, + webpack/ts/config/helpers.js`, + null, + `package.json, + typings.json, + tsconfig.json, + webpack.config.js, + karma.conf.js, + config/helpers.js` +) +.l-sub-section + :marked + Many of these files and much of their content should be familiar from other Angular 2 documentation chapters. + + Learn about the `package.json` in the [npm packages](../guide/npm-packages.html) chapter. + We require packages for Webpack use in addition to the ones listed in that chapter. + + Learn about `tsconfig.json` and `typings.json` in the [Typescript configuration](../guide/typescript-configuration.html) chapter. +:marked + Open a terminal/console window and install the *npm* packages with `npm install`. + + +a(id="common-configuration") +.l-main-section +:marked + ### Common Configuration + + We will define separate configurations for development, production, and test environments. + All three have some configuration in common. + We'll gather that common configuration in a separate file called `webpack.common.js`. + + Let's see the entire file and then walk through it a section at a time: + ++makeExample('webpack/ts/config/webpack.common.js', null, 'config/webpack.common.js')(format=".") + +:marked + Webpack is a NodeJS-based tool so its configuration is a JavaScript _commonjs_ module file + that begins with `require` statements as such files do. + + The configuration exports several objects, beginning with the *entries* described earlier: + ++makeExample('webpack/ts/config/webpack.common.js', 'entries', 'config/webpack.common.js')(format=".") +:marked + We are splitting our application into three bundles: + + * polyfills - the standard polyfills we require to run Angular 2 applications in most modern browsers. + * vendor - the vendor files we need: Angular 2, lodash, bootstrap.css... + * app - our application code. + +.callout.is-critical + header Loading polyfills + :marked + Load Zone.js early, immediately after the other ES6 and metadata shims. + +:marked + Our app will `import` dozens if not hundreds of JavaScript and TypeScript files. + We _might_ write `import` statements with explicit extensions as in this example: ++makeExample('webpack/ts-snippets/webpack.config.snippets.js', 'single-import')(format=".") + +:marked + But most of our `import` statements won't mention the extension at all. + So we tell Webpack to _resolve_ module file requests by looking for matching files with + + * an explicit extention (signified by the empty extension string, `''`) or + * `.js` extension (for regular JavaScript files and pre-compiled TypeScript files) or + * `.ts` extension. + ++makeExample('webpack/ts/config/webpack.common.js', 'resolve', 'config/webpack.common.js')(format=".") +.l-sub-section + :marked + We could add `.css` and `.html` later if we want Webpack to resolve extension-less files with _those_ extension too. +:marked + Next we specify the loaders: + ++makeExample('webpack/ts/config/webpack.common.js', 'loaders', 'config/webpack.common.js')(format=".") + +:marked + * ts - a loader to transpile our Typescript code to ES5, guided by the `tsconfig.json` file + * html - for component templates + * images/fonts - Images and fonts are bundled as well. + * css - The pattern matches application-wide styles; the second handles component-scoped styles (the ones specified in a component's `styleUrls` metadata property). +.l-sub-section + :marked + The first pattern excludes `.css` files within the `/src/app` directories where our component-scoped styles sit. + It includes only `.css` files located at or above `/src`; these are the application-wide styles. + The `ExtractTextPlugin` (described below) applies the `style` and `css` loaders to these files. + + The second pattern filters for component-scoped styles and loads them as strings via the `raw` loader — + which is what Angular expects to do with styles specified in a `styleUrls` metadata property. + +:marked + Finally we add two plugins: + ++makeExample('webpack/ts/config/webpack.common.js', 'plugins', 'config/webpack.common.js')(format=".") + +a(id="commons-chunk-plugin") +:marked + #### *CommonsChunkPlugin* + + We want the `app.js` bundle to contain only app code and the `vendor.js` bundle to contain only the vendor code. + + Our application code `imports` vendor code. Webpack is not smart to keep the vendor code out of the `app.js` bundle. + We rely on the `CommonsChunkPlugin` to do that job. +.l-sub-section + :marked + It identifies the hierarchy among three _chunks_: `app` -> `vendor` -> `polyfills`. + Where Webpack finds that `app` has shared dependencies with `vendor`, it removes them from `app`. + It would do the same if `vendor` and `polyfills` had shared dependencies (which they don't). + +a(id="html-webpack-plugin") +:marked + #### *HtmlWebpackPlugin* + + Webpack generates a number of js and css files. + We _could_ insert them into our `index.html` _manually_. That would be tedious and error-prone. + Webpack can inject those scripts and links for us with the `HtmlWebpackPlugin`. + +a(id="environment-configuration") +.l-main-section +:marked + ### Environment-specific configuration + + The `webpack.common.js` configuration file does most of the heavy lifting. + We create separate, environment-specific configuration files that build on `webpack.common` + by merging into it the peculiarities particular to their target environments. + + These files tend to be short and simple. + +a(id="development-configuration") +.l-main-section +:marked + ### Development Configuration + + Here is the development configuration file, `webpack.dev.js` + ++makeExample('webpack/ts/config/webpack.dev.js', null, 'config/webpack.dev.js')(format=".") + +:marked + The development build relies on the Webpack development server which we configure near the bottom of the file. + + Although we tell Webpack to put output bundles in the `dist` folder, + the dev server keeps all bundles in memory; it doesn't write them to disk. + So we won't find any files in the `dist` folder (at least not any generated from `this development build`). + + + The `HtmlWebpackPlugin` (added in `webpack.common.js`) use the *publicPath* and the *filename* settings to generate + appropriate <script> and <link> tags into the `index.html`. + + Our CSS are buried inside our Javascript bundles by deault. The `ExtractTextPlugin` extracts them into + external `.css` files that the `HtmlWebpackPlugin` inscribes as <link> tags into the `index.html`. + + Refer to the Webpack documentation for details on these and other configuation options in this file + + Grab the app code at the end of this guide and try: + +code-example(format=""). + npm start + +a(id="production-configuration") +.l-main-section +:marked + ### Production Configuration + + Configuration of a *production* build resembles *development* configuration ... with a few key changes. + ++makeExample('webpack/ts/config/webpack.prod.js', null, 'config/webpack.prod.js')(format=".") + +:marked + We don't use a development server. We're expected to deploy the application and its dependencies to a real production server. + + This time the output bundle files are physically placed in the `dist` folder. + + Webpack generates file names with cache-busting hash. + Thanks to the `HtmlWebpackPlugin` we don't have to update the `index.html` file when the hashes changes. + + There are additional plugins: + + * **NoErrorsPlugin** - stops the build if there is any error. + * **DedupePlugin** - detects identical (and nearly identical) files and removes them from the output. + * **UglifyJsPlugin** - minifies the bundles. + * **ExtractTextPlugin** - extracts embedded css as external files, adding cache-busting hash to the filename. + * **DefinePlugin** - use to define environment variables that we can reference within our application. + + Thanks to the *DefinePlugin* and the `ENV` variable defined at top, we can enable Angular 2 production mode like this: + ++makeExample('webpack/ts/src/main.ts', 'enable-prod')(format=".") + +:marked + Grab the app code at the end of this guide and try: + +code-example(format=""). + npm run build + +a(id="test-configuration") +.l-main-section +:marked + ### Test Configuration + + We don't need much configuration to run unit tests. + We don't need the loaders and plugins that we declared for our development and production builds. + We probably don't need to load and process `css` files for unit tests and doing so would slow us down; + we'll use the `null` loader for all CSS. + + We could merge our test configuration into the `webpack.common` configuration and override the parts we don't want or need. + But it might be simpler to start over with a completely fresh configuration. + ++makeExample('webpack/ts/config/webpack.test.js', null, 'config/webpack.test.js')(format=".") + +:marked + Here's our karma configuration: + ++makeExample('webpack/ts/config/karma.conf.js', null, 'config/karma.conf.js')(format=".") + +:marked + We're telling Karma to use webpack to run the tests. + + We don't precompile our TypeScript; Webpack transpiles our Typescript files on the fly, in memory, and feeds the emitted JS directly to Karma. + There are no temporary files on disk. + + The `karma-test-shim` tells Karma what files to pre-load and + primes the Angular test framework with test versions of the providers that every app expects to be pre-loaded. + ++makeExample('webpack/ts/config/karma-test-shim.js', null, 'config/karma-test-shim.js')(format=".") + +:marked + Notice that we do _not_ load our application code explicitly. + We tell Webpack to find and load our test files (the files ending in `.spec.ts`). + Each spec file imports all — and only — the application source code that it tests. + Webpack loads just _those_ specific application files and ignores the other files that we aren't testing. + +:marked + Grab the app code at the end of this guide and try: + +code-example(format=""). + npm test + + +:marked + ## Trying it out + + Here is the source code for a small application that we can bundle with the + Webpack techniques we learned in this chapter. + ++makeTabs( + `webpack/ts/src/index.html, + webpack/ts/src/main.ts, + webpack/ts/public/css/styles.css`, + null, + `src/index.html, + src/main.ts, + public/css/styles.css` +) + ++makeTabs( + `webpack/ts/src/app/app.component.ts, + webpack/ts/src/app/app.component.html, + webpack/ts/src/app/app.component.css, + webpack/ts/src/app/app.component.spec.ts, + webpack/ts/src/app/index.ts`, + null, + `src/app/app.component.ts, + src/app/app.component.html, + src/app/app.component.css, + src/app/app.component.spec.ts, + src/app/index.ts` +) + ++makeTabs( + `webpack/ts/src/vendor.ts, + webpack/ts/src/polyfills.ts`, + null, + `src/vendor.ts, + src/polyfills.ts` +) + +:marked + The `app.component.html` displays the Angular logo image which we can download + from [here](https://raw.githubusercontent.com/angular/angular.io/master/public/resources/images/logos/angular2/angular.png). + + ### Highlights: + + * There are no <script> or <link> tags in the `index.html`. + The `HtmlWebpackPlugin` inserts them dynamically at runtime. + + * The `AppComponent` in `app.component.ts` imports the application-wide css with a simple `import` statement. + + * The `AppComponent` itself has its own html template and css files which we load with the `require()` method + supplied by Webpack. Webpack stashes those component-scoped files in the `app.ts` bundle too. + + * The `vendor.ts` consists of vendor dependency `import` statements that drive the `vendor.js` bundle. + The application imports these modules too; they'd be duplicated in the `app.js` bundle + if the `CommonsChunkPlugin` hadn't detected the overlap and removed them from `app.js`. + +// WHAT GOOD IS THIS? + * We coded our app feature as a [barrel](../glossary.html#barrel). + + +:marked + ## Conclusions + + We've learned just enough Webpack to configurate development, test and production builds + for a small Angular application. + + _We could always do more_. Search the web for expert advice and expand your Webpack knowledge. + + [Back to top](#top) diff --git a/public/docs/ts/latest/quickstart.jade b/public/docs/ts/latest/quickstart.jade index 9193e78081..82a77088ba 100644 --- a/public/docs/ts/latest/quickstart.jade +++ b/public/docs/ts/latest/quickstart.jade @@ -85,9 +85,7 @@ a(id="typings") :marked Add a **typings.json** file to the project folder and copy/paste the following: +makeJson('quickstart/ts/typings.1.json', null, 'typings.json')(format=".") -:marked - Add a **typings** folder to the project folder and then add the following file to that *typings* folder: -+makeExample('quickstart/ts/typings.d.1.ts', null, 'typings/typings.d.ts')(format=".") + .l-verbose-section :marked Many JavaScript libraries extend the JavaScript environment with features and syntax @@ -491,10 +489,7 @@ figure.image-display .file app.component.ts .file main.ts .file node_modules ... - .file typings - .children - .file typings.d.ts - .file ... + .file typings ... .file index.html .file package.json .file styles.css