From d586c7cd6a0ff4e20ece61d738a8482959aaf783 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 1 Mar 2017 20:26:56 +0000 Subject: [PATCH] fix(toh-6): add missing tsconfig file (#3289) --- .../_examples/toh-6/ts/src/tsconfig.1.json | 13 ++ .../docs/ts/latest/cookbook/aot-compiler.jade | 158 +++++++++--------- 2 files changed, 92 insertions(+), 79 deletions(-) create mode 100644 public/docs/_examples/toh-6/ts/src/tsconfig.1.json diff --git a/public/docs/_examples/toh-6/ts/src/tsconfig.1.json b/public/docs/_examples/toh-6/ts/src/tsconfig.1.json new file mode 100644 index 0000000000..fb3d43db90 --- /dev/null +++ b/public/docs/_examples/toh-6/ts/src/tsconfig.1.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ "es2015", "dom" ], + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + } +} \ No newline at end of file diff --git a/public/docs/ts/latest/cookbook/aot-compiler.jade b/public/docs/ts/latest/cookbook/aot-compiler.jade index 9a72c991f4..fe8401f538 100644 --- a/public/docs/ts/latest/cookbook/aot-compiler.jade +++ b/public/docs/ts/latest/cookbook/aot-compiler.jade @@ -1,7 +1,7 @@ include ../_util-fns - + :marked - This cookbook describes how to radically improve performance by compiling _Ahead of Time_ (AOT) + This cookbook describes how to radically improve performance by compiling _Ahead of Time_ (AOT) during a build process. a#toc @@ -24,26 +24,26 @@ a#overview ## Overview An Angular application consist largely of components and their HTML templates. - Before the browser can render the application, + Before the browser can render the application, the components and templates must be converted to executable JavaScript by the _Angular compiler_. .l-sub-section :marked Watch compiler author Tobias Bosch explain the Angular Compiler at AngularConnect 2016. :marked - You can compile the app in the browser, at runtime, as the application loads, using the **_Just-in-Time_ (JIT) compiler**. + You can compile the app in the browser, at runtime, as the application loads, using the **_Just-in-Time_ (JIT) compiler**. This is the standard development approach shown throughout the documentation. It's great .. but it has shortcomings. - JIT compilation incurs a runtime performance penalty. - Views take longer to render because of the in-browser compilation step. - The application is bigger because it includes the Angular compiler + JIT compilation incurs a runtime performance penalty. + Views take longer to render because of the in-browser compilation step. + The application is bigger because it includes the Angular compiler and a lot of library code that the application won't actually need. Bigger apps take longer to transmit and are slower to load. - + Compilation can uncover many component-template binding errors. JIT compilation discovers them at runtime which is later than we'd like. - - The **_Ahead-of-Time_ (AOT) compiler** can catch template errors early and improve performance + + The **_Ahead-of-Time_ (AOT) compiler** can catch template errors early and improve performance by compiling at build time as you'll learn in this chapter. @@ -52,15 +52,15 @@ a#aot-jit :marked ## _Ahead-of-time_ (AOT) vs _Just-in-time_ (JIT) - There is actually only one Angular compiler. The difference between AOT and JIT is a matter of timing and tooling. - With AOT, the compiler runs once at build time using one set of libraries; - With JIT it runs every time for every user at runtime using a different set of libraries. + There is actually only one Angular compiler. The difference between AOT and JIT is a matter of timing and tooling. + With AOT, the compiler runs once at build time using one set of libraries; + With JIT it runs every time for every user at runtime using a different set of libraries. ### Why do AOT compilation? *Faster rendering* - With AOT, the browser downloads a pre-compiled version of the application. + With AOT, the browser downloads a pre-compiled version of the application. The browser loads executable code so it can render the application immediately, without waiting to compile the app first. *Fewer asynchronous requests* @@ -70,7 +70,7 @@ a#aot-jit *Smaller Angular framework download size* - There's no need to download the Angular compiler if the app is already compiled. + There's no need to download the Angular compiler if the app is already compiled. The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload. @@ -104,31 +104,31 @@ a#compile )(format='.') :marked - Install a few new npm dependencies with the following command: + Install a few new npm dependencies with the following command: code-example(language="none" class="code-shell"). npm install @angular/compiler-cli @angular/platform-server --save :marked You will run the `ngc` compiler provided in the `@angular/compiler-cli` npm package - instead of the TypeScript compiler (`tsc`). + instead of the TypeScript compiler (`tsc`). - `ngc` is a drop-in replacement for `tsc` and is configured much the same way. + `ngc` is a drop-in replacement for `tsc` and is configured much the same way. `ngc` requires its own `tsconfig.json` with AOT-oriented settings. - Copy the original `src/tsconfig.json` to a file called `tsconfig-aot.json` (on the project root), + Copy the original `src/tsconfig.json` to a file called `tsconfig-aot.json` (on the project root), then modify it to look as follows. +makeExample('cb-aot-compiler/ts/tsconfig-aot.json', null, 'tsconfig-aot.json')(format='.') :marked - The `compilerOptions` section is unchanged except for one property. - **Set the `module` to `es2015`**. + The `compilerOptions` section is unchanged except for one property. + **Set the `module` to `es2015`**. This is important as explained later in the [Tree Shaking](#tree-shaking) section. - What's really new is the `ngc` section at the bottom called `angularCompilerOptions`. - Its `"genDir"` property tells the compiler + What's really new is the `ngc` section at the bottom called `angularCompilerOptions`. + Its `"genDir"` property tells the compiler to store the compiled output files in a new `aot` folder. - The `"skipMetadataEmit" : true` property prevents the compiler from generating metadata files with the compiled application. + The `"skipMetadataEmit" : true` property prevents the compiler from generating metadata files with the compiled application. Metadata files are not necessary when targeting TypeScript files, so there is no reason to include them. :marked @@ -139,14 +139,14 @@ code-example(language="none" class="code-shell"). For example, an `'app.component.html'` URL means that the template file is a sibling of its companion `app.component.ts` file. While JIT app URLs are more flexible, stick with _component-relative_ URLs for compatibility with AOT compilation. - + JIT-compiled applications that use the SystemJS loader and _component-relative_ URLs *must set the* `@Component.moduleId` *property to* `module.id`. - The `module` object is undefined when an AOT-compiled app runs. + The `module` object is undefined when an AOT-compiled app runs. The app fails with a null reference error unless you assign a global `module` value in the `index.html` like this: -+makeExample('cb-aot-compiler/ts/src/index.html','moduleId')(format='.') ++makeExample('cb-aot-compiler/ts/src/index.html','moduleId')(format='.') .l-sub-section :marked - Setting a global `module` is a temporary expedient. + Setting a global `module` is a temporary expedient. :marked ### Compiling the application @@ -162,9 +162,9 @@ code-example(language="none" class="code-shell"). :marked `ngc` expects the `-p` switch to point to a `tsconfig.json` file or a folder containing a `tsconfig.json` file. - After `ngc` completes, look for a collection of _NgFactory_ files in the `aot` folder (the folder specified as `genDir` in `tsconfig-aot.json`). + After `ngc` completes, look for a collection of _NgFactory_ files in the `aot` folder (the folder specified as `genDir` in `tsconfig-aot.json`). - These factory files are essential to the compiled application. + These factory files are essential to the compiled application. Each component factory creates an instance of the component at runtime by combining the original class file and a JavaScript representation of the component's template. Note that the original component class is still referenced internally by the generated factory. @@ -179,7 +179,7 @@ code-example(language="none" class="code-shell"). :marked .alert.is-important :marked - Do not edit the _NgFactories_! Re-compilation replaces these files and all edits will be lost. + Do not edit the _NgFactories_! Re-compilation replaces these files and all edits will be lost. a#bootstrap .l-main-section @@ -190,7 +190,7 @@ a#bootstrap Instead of bootstrapping `AppModule`, you bootstrap the application with the generated module factory, `AppModuleNgFactory`. - Make a copy of `main.ts` and name it `main-jit.ts`. + Make a copy of `main.ts` and name it `main-jit.ts`. This is the JIT version; set it aside as you may need it [later](#run-jit "Running with JIT"). Open `main.ts` and convert it to AOT compilation. @@ -218,16 +218,16 @@ a#tree-shaking A Tree Shaker walks the dependency graph, top to bottom, and _shakes out_ unused code like dead needles in a Christmas tree. - Tree Shaking can greatly reduce the downloaded size of the application - by removing unused portions of both source and library code. - In fact, most of the reduction in small apps comes from removing unreferenced Angular features. - + Tree Shaking can greatly reduce the downloaded size of the application + by removing unused portions of both source and library code. + In fact, most of the reduction in small apps comes from removing unreferenced Angular features. + For example, this demo application doesn't use anything from the `@angular/forms` library. There is no reason to download Forms-related Angular code and tree shaking ensures that you don't. - Tree Shaking and AOT compilation are separate steps. - Tree Shaking can only target JavaScript code. - AOT compilation converts more of the application to JavaScript, + Tree Shaking and AOT compilation are separate steps. + Tree Shaking can only target JavaScript code. + AOT compilation converts more of the application to JavaScript, which in turn makes more of the application "Tree Shakable". ### Rollup @@ -240,8 +240,8 @@ a#tree-shaking Rollup can only Tree Shake `ES2015` modules which have `import` and `export` statements. .l-sub-section :marked - Recall that `tsconfig-aot.json` is configured to produce `ES2015` modules. - It's not important that the code itself be written with `ES2015` syntax such as `class` and `const`. + Recall that `tsconfig-aot.json` is configured to produce `ES2015` modules. + It's not important that the code itself be written with `ES2015` syntax such as `class` and `const`. What matters is that the code uses ES `import` and `export` statements rather than `require` statements. :marked Install the Rollup dependencies with this command: @@ -249,7 +249,7 @@ code-example(format='.'). npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev :marked Next, create a configuration file (`rollup-config.js`) - in the project root directory to tell Rollup how to process the application. + in the project root directory to tell Rollup how to process the application. The cookbook configuration file looks like this. +makeExample('cb-aot-compiler/ts/rollup-config.js', null, 'rollup-config.js')(format='.') @@ -266,25 +266,25 @@ code-example(format='.'). Optional plugins filter and transform the Rollup inputs and output. *RxJS* - Rollup expects application source code to use `ES2015` modules. + Rollup expects application source code to use `ES2015` modules. Not all external dependencies are published as `ES2015` modules. In fact, most are not. Many of them are published as _CommonJS_ modules. - + The _RxJs_ observable library is an essential Angular dependency published as an ES5 JavaScript _CommonJS_ module. - Luckily there is a Rollup plugin that modifies _RxJs_ + Luckily there is a Rollup plugin that modifies _RxJs_ to use the ES `import` and `export` statements that Rollup requires. Rollup then preserves in the final bundle the parts of `RxJS` referenced by the application. -+makeExample('cb-aot-compiler/ts/rollup-config.js','commonjs','rollup-config.js (CommonJs to ES2015 Plugin)')(format='.') ++makeExample('cb-aot-compiler/ts/rollup-config.js','commonjs','rollup-config.js (CommonJs to ES2015 Plugin)')(format='.') :marked - *Minification* + *Minification* Rollup Tree Shaking reduces code size considerably. Minification makes it smaller still. This cookbook relies on the _uglify_ Rollup plugin to minify and mangle the code. -+makeExample('cb-aot-compiler/ts/rollup-config.js','uglify','rollup-config.js (CommonJs to ES2015 Plugin)')(format='.') ++makeExample('cb-aot-compiler/ts/rollup-config.js','uglify','rollup-config.js (CommonJs to ES2015 Plugin)')(format='.') .l-sub-section :marked @@ -307,11 +307,11 @@ a#load :marked ## Load the Bundle - Loading the generated application bundle does not require a module loader like SystemJS. + Loading the generated application bundle does not require a module loader like SystemJS. Remove the scripts that concern SystemJS. Instead, load the bundle file using a single `script` tag **_after_** the `` tag: -+makeExample('cb-aot-compiler/ts/src/index.html','bundle','index.html (load bundle)')(format='.') ++makeExample('cb-aot-compiler/ts/src/index.html','bundle','index.html (load bundle)')(format='.') a#serve .l-main-section @@ -324,7 +324,7 @@ code-example(language="none" class="code-shell"). npm run lite :marked The server starts, launches a browser, and the app should appear. - + a#source-code .l-main-section :marked @@ -352,7 +352,7 @@ a#workflow :marked ## Workflow and convenience script - You'll rebuild the AOT version of the application every time you make a change. + You'll rebuild the AOT version of the application every time you make a change. Those _npm_ commands are long and difficult to remember. Add the following _npm_ convenience script to the `package.json` so you can compile and rollup in one command. @@ -360,20 +360,20 @@ a#workflow :marked Open a terminal window and try it. code-example(language="none" class="code-shell"). - npm run build:aot + npm run build:aot a#run-jit :marked ### And JIT too! - AOT compilation and rollup together take several seconds. + AOT compilation and rollup together take several seconds. You may be able to develop iteratively a little faster with SystemJS and JIT. The same source code can be built both ways. Here's one way to do that. * Make a copy of `index.html` and call it `index-jit.html`. * Delete the script at the bottom of `index-jit.html` that loads `bundle.js` * Restore the SystemJS scripts like this: -+makeExample('cb-aot-compiler/ts/src/index-jit.html','jit','src/index-jit.html (SystemJS scripts)')(format='.') ++makeExample('cb-aot-compiler/ts/src/index-jit.html','jit','src/index-jit.html (SystemJS scripts)')(format='.') :marked Notice the slight change to the `system.import` which now specifies `src/app/main-jit`. @@ -391,7 +391,7 @@ code-example(language="none" class="code-shell"). Develop as usual. The server and TypeScript compiler are in "watch mode" so your changes are reflected immediately in the browser. - To see those changes in AOT, switch to the original terminal and re-run `npm run build:aot`. + To see those changes in AOT, switch to the original terminal and re-run `npm run build:aot`. When it finishes, go back to the browser and back-button to the AOT version in the (default) `index.html`. Now you can develop JIT and AOT, side-by-side. @@ -402,8 +402,8 @@ a#toh :marked ## Tour of Heroes - The sample above is a trivial variation of the QuickStart app. - In this section you apply what you've learned about AOT compilation and Tree Shaking + The sample above is a trivial variation of the QuickStart app. + In this section you apply what you've learned about AOT compilation and Tree Shaking to an app with more substance, the tutorial [_Tour of Heroes_](../tutorial/toh-pt6.html). ### JIT in development, AOT in production @@ -415,8 +415,8 @@ a#toh ***index.html*** - The JIT and AOT apps require their own `index.html` files because they setup and launch so differently. - + The JIT and AOT apps require their own `index.html` files because they setup and launch so differently. + Here they are for comparison: +makeTabs( @@ -428,17 +428,17 @@ a#toh ) :marked - The JIT version relies on `SystemJS` to load individual modules. + The JIT version relies on `SystemJS` to load individual modules. Its scripts appear in its `index.html`. The AOT version loads the entire application in a single script, `aot/dist/build.js`. It does not need `SystemJS`, so that script is absent from its `index.html` - + ***main.ts*** - + JIT and AOT applications boot in much the same way but require different Angular libraries to do so. The key differences, covered in the [Bootstrap](#bootstrap) section above, - are evident in these `main` files which can and should reside in the same folder: + are evident in these `main` files which can and should reside in the same folder: +makeTabs( `toh-6/ts/src/main-aot.ts, @@ -452,14 +452,14 @@ a#toh ***TypeScript configuration*** JIT-compiled applications transpile to `commonjs` modules. - AOT-compiled applications transpile to _ES2015_/_ES6_ modules to facilitate Tree Shaking. + AOT-compiled applications transpile to _ES2015_/_ES6_ modules to facilitate Tree Shaking. AOT requires its own TypeScript configuration settings as well. You'll need separate TypeScript configuration files such as these: +makeTabs( `toh-6/ts/tsconfig-aot.json, - toh-6/ts/src/tsconfig.json`, + toh-6/ts/src/tsconfig.1.json`, null, `tsconfig-aot.json (AOT), src/tsconfig.json (JIT)` @@ -469,9 +469,9 @@ a#toh header @Types and node modules :marked In the file structure of _this particular sample project_, - the `node_modules` folder happens to be two levels up from the project root. - Therefore, `"typeRoots"` must be set to `"../../node_modules/@types/"`. - + the `node_modules` folder happens to be two levels up from the project root. + Therefore, `"typeRoots"` must be set to `"../../node_modules/@types/"`. + In a more typical project, `node_modules` would be a sibling of `tsconfig-aot.json` and `"typeRoots"` would be set to `"node_modules/@types/"`. Edit your `tsconfig-aot.json` to fit your project's file structure. @@ -480,8 +480,8 @@ a#toh ### Tree Shaking Rollup does the Tree Shaking as before. - -+makeExample('toh-6/ts/rollup-config.js',null,'rollup-config.js')(format='.') + ++makeExample('toh-6/ts/rollup-config.js',null,'rollup-config.js')(format='.') :marked ### Running the application @@ -490,8 +490,8 @@ a#toh :marked The general audience instructions for running the AOT build of the Tour of Heroes app are not ready. - The following instructions presuppose that you have cloned the - angular.io + The following instructions presuppose that you have cloned the + angular.io github repository and prepared it for development as explained in the repo's README.md. The _Tour of Heroes_ source code is in the `public/docs/_examples/toh-6/ts` folder. @@ -512,7 +512,7 @@ a#toh :marked Extend the `scripts` section of the `package.json` with these npm scripts: +makeJson('cb-aot-compiler/ts/package.json', { paths: 'scripts.build:aot, scripts.serve:aot'}, "package.json (convenience scripts)") - + :marked Copy the AOT distribution files into the `/aot` folder with the node script: code-example(language="none" class="code-shell"). @@ -528,10 +528,10 @@ code-example(language="none" class="code-shell"). :marked ### Inspect the Bundle - It's fascinating to see what the generated JavaScript bundle looks like after Rollup. + It's fascinating to see what the generated JavaScript bundle looks like after Rollup. The code is minified, so you won't learn much from inspecting the bundle directly. - But the source-map-explorer - tool can be quite revealing. + But the source-map-explorer + tool can be quite revealing. Install it: code-example(language="none" class="code-shell"). @@ -546,8 +546,8 @@ code-example(language="none" class="code-shell"). The `source-map-explorer` analyzes the source map generated with the bundle and draws a map of all dependencies, showing exactly which application and Angular modules and classes are included in the bundle. - Here's the map for _Tour of Heroes_. + Here's the map for _Tour of Heroes_. a(href="/resources/images/cookbooks/aot-compiler/toh6-bundle.png", target="_blank", title="View larger image") figure.image-display - img(src="/resources/images/cookbooks/aot-compiler/toh6-bundle.png" alt="TOH-6-bundle") + img(src="/resources/images/cookbooks/aot-compiler/toh6-bundle.png" alt="TOH-6-bundle")