feat(deployment): add deployment chapter (#3043)
This PR adds the Deployment Chapter.
This commit is contained in:
parent
878dfa6b87
commit
8a537b1225
1
public/docs/_examples/deployment/ts/.gitignore
vendored
Normal file
1
public/docs/_examples/deployment/ts/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
!systemjs.config.server.js
|
15
public/docs/_examples/deployment/ts/app/app.component.ts
Normal file
15
public/docs/_examples/deployment/ts/app/app.component.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
<h1>Simple Deployment</h1>
|
||||
<nav>
|
||||
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
|
||||
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
|
||||
</nav>
|
||||
<router-outlet></router-outlet>
|
||||
`
|
||||
})
|
||||
export class AppComponent { }
|
29
public/docs/_examples/deployment/ts/app/app.module.ts
Normal file
29
public/docs/_examples/deployment/ts/app/app.module.ts
Normal file
@ -0,0 +1,29 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { CrisisListComponent } from './crisis-list.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{ path: 'crisis-center', component: CrisisListComponent },
|
||||
{ path: 'heroes', component: HeroListComponent },
|
||||
|
||||
{ path: '', redirectTo: '/heroes', pathMatch: 'full' }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot(appRoutes)
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
CrisisListComponent,
|
||||
HeroListComponent
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
@ -0,0 +1,9 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<h2>CRISIS CENTER</h2>
|
||||
<p>Get your crisis here</p>`
|
||||
})
|
||||
export class CrisisListComponent { }
|
@ -0,0 +1,10 @@
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<h2>HEROES</h2>
|
||||
<p>Get your heroes here</p>
|
||||
`
|
||||
})
|
||||
export class HeroListComponent { }
|
15
public/docs/_examples/deployment/ts/app/main.ts
Normal file
15
public/docs/_examples/deployment/ts/app/main.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// #docregion
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
// #docregion enableProdMode
|
||||
import { enableProdMode } from '@angular/core';
|
||||
|
||||
// Enable production mode unless running locally
|
||||
if (!/localhost/.test(document.location.host)) {
|
||||
enableProdMode();
|
||||
}
|
||||
// #enddocregion enableProdMode
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
38
public/docs/_examples/deployment/ts/index.html
Normal file
38
public/docs/_examples/deployment/ts/index.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!-- #docregion -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!- Doesn't load from node_modules! -->
|
||||
|
||||
<!-- Set the base href -->
|
||||
<base href="/">
|
||||
<title>Simple Deployment</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
|
||||
<!-- #docregion node-module-scripts -->
|
||||
<!-- Polyfills for older browsers -->
|
||||
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
|
||||
|
||||
<!-- Update these package versions as needed -->
|
||||
<script src="https://unpkg.com/zone.js@0.7.4?main=browser"></script>
|
||||
<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
|
||||
<!-- #enddocregion node-module-scripts -->
|
||||
|
||||
<!-- #docregion systemjs-config -->
|
||||
<!-- This SystemJS configuration loads umd packages from the web -->
|
||||
<script src="systemjs.config.server.js"></script>
|
||||
<!-- #enddocregion systemjs-config -->
|
||||
|
||||
<script>
|
||||
System.import('app')
|
||||
.catch(function(err){ console.error(err); });
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<my-app>loading...</my-app>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,46 @@
|
||||
// #docregion
|
||||
/**
|
||||
* System configuration for deployment without installing node_modules
|
||||
* Loads umd packages from the web instead
|
||||
* Adjust as necessary for your application needs.
|
||||
*/
|
||||
(function (global) {
|
||||
System.config({
|
||||
// #docregion paths
|
||||
paths: {
|
||||
'npm:': 'https://unpkg.com/' // path serves as alias
|
||||
},
|
||||
// #enddocregion paths
|
||||
// map tells the System loader where to look for things
|
||||
map: {
|
||||
app: 'app', // location of transpiled app files
|
||||
|
||||
// angular minimized umd bundles
|
||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.min.js',
|
||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.min.js',
|
||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.min.js',
|
||||
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js',
|
||||
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js',
|
||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.min.js',
|
||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.min.js',
|
||||
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.min.js',
|
||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.min.js',
|
||||
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.min.js',
|
||||
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.min.js',
|
||||
|
||||
// other libraries
|
||||
'rxjs': 'npm:rxjs@5.0.1',
|
||||
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
|
||||
},
|
||||
// packages tells the System loader how to load when no filename and/or no extension
|
||||
packages: {
|
||||
app: {
|
||||
main: './main.js',
|
||||
defaultExtension: 'js'
|
||||
},
|
||||
rxjs: {
|
||||
defaultExtension: 'js'
|
||||
}
|
||||
}
|
||||
});
|
||||
})(this);
|
@ -153,6 +153,11 @@
|
||||
"intro": "Pipes transform displayed values within a template."
|
||||
},
|
||||
|
||||
"production-deploy": {
|
||||
"title": "Deployment",
|
||||
"intro": "Learn how to deploy your Angular app."
|
||||
},
|
||||
|
||||
"router": {
|
||||
"title": "Routing & Navigation",
|
||||
"intro": "Discover the basics of screen navigation with the Angular Router."
|
||||
|
513
public/docs/ts/latest/guide/deployment.jade
Normal file
513
public/docs/ts/latest/guide/deployment.jade
Normal file
@ -0,0 +1,513 @@
|
||||
include ../_util-fns
|
||||
|
||||
:marked
|
||||
This page describes tools and techniques for deploy and optimize your Angular application.
|
||||
|
||||
a#toc
|
||||
:marked
|
||||
## Table of contents
|
||||
* [Overview](#overview)
|
||||
* [Simplest deployment possible](#dev-deploy)
|
||||
* [Optimize for production](#optimize)
|
||||
* [Ahead-of-Time (AOT) compilation](#aot)
|
||||
* [Webpack](#webpack)
|
||||
* [Tree shaking with _rollup_](#rollup)
|
||||
* [Pruned libraries](#prune)
|
||||
* [Measure performance first](#measure)
|
||||
* [Angular configuration](#angular-configuration)
|
||||
* [The `base` tag](#base-tag)
|
||||
* [Enable production mode](#enableprodmode)
|
||||
* [Lazy loading](#lazy-loading)
|
||||
* [Server configuration](#server-configuration)
|
||||
* [Routed apps must fallback to `index.html`](#fallback)
|
||||
* [CORS: requesting services from a different server](#cors)
|
||||
|
||||
a#overview
|
||||
.l-main-section
|
||||
:marked
|
||||
## Overview
|
||||
|
||||
This guide describes techniques for preparing and deploying an Angular application to a server running remotely.
|
||||
The techniques progress from _easy but suboptimal_ to _more optimal and more involved_.
|
||||
|
||||
* The [simple way](#dev-deploy "Simplest deployment possible") is to copy the development environment to the server.
|
||||
|
||||
* [_Ahead of Time_ compilation (AOT)](#aot "AOT Compilation") is the first of
|
||||
[several optimization strategies](#optimize).
|
||||
You'll also want to read the [detailed instructions in the AOT Cookbook](aot-compiler.html "AOT Cookbook").
|
||||
|
||||
* [Webpack](#webpack "Webpack Optimization") is a popular general purpose packaging tool with a rich ecosystem, including plugins for AOT.
|
||||
The Angular [webpack guide](webpack.html "Webpack: an introduction") can get you started and
|
||||
_this_ page provides additional optimization advice, but you'll probably have to learn more about webpack on your own.
|
||||
|
||||
* The [Angular configuration](#angular-configuration "Angular configuration") section calls attention to
|
||||
specific client application changes that could improve performance.
|
||||
|
||||
* The [Server configuration](#server-configuration "Server configuration") section describes
|
||||
server-side changes that may be necessary, _no matter how you deploy the application_.
|
||||
|
||||
.l-main-section
|
||||
a#dev-deploy
|
||||
:marked
|
||||
## Simplest deployment possible
|
||||
|
||||
The simplest way to deploy the app is to publish it to a web server
|
||||
directly out of the development environment.
|
||||
|
||||
It's already running locally. You'll just copy it, almost _as is_,
|
||||
to a non-local server that others can reach.
|
||||
|
||||
1. Copy _everything_ (or [_almost_ everything](#node-modules "Loading npm packages from the web"))
|
||||
from the local project folder to a folder on the server.
|
||||
|
||||
1. If you're serving the app out of a subfolder,
|
||||
edit a version of `index.html` to set the `<base href>` appropriately.
|
||||
For example, if the URL to `index.html` is `www.mysite.com/myapp/`, set the _base href_ to
|
||||
`<base href="/myapp/">`.
|
||||
Otherwise, leave it alone.
|
||||
[More on this below](#base-tag).
|
||||
|
||||
1. Configure the server to redirect requests for missing files to `index.html`.
|
||||
[More on this below](#fallback).
|
||||
|
||||
1. Enable production mode as [described below](#enableprodmode) (optional).
|
||||
|
||||
That's the simplest deployment you can do.
|
||||
|
||||
.alert.is-helpful
|
||||
:marked
|
||||
This is _not_ a production deployment. It's not optimized and it won't be fast for users.
|
||||
It might be good enough for sharing your progress and ideas internally with managers, teammates, and other stakeholders.
|
||||
Be sure to read about [optimizing for production](#optimize "Optimizing for production") below.
|
||||
|
||||
|
||||
a#node-modules
|
||||
:marked
|
||||
### Load npm package files from the web (SystemJS)
|
||||
|
||||
The `node_modules` folder of _npm packages_ contains much more code
|
||||
than is needed to actually run your app in the browser.
|
||||
The `node_modules` for the Quickstart installation is typically 20,500+ files and 180+ MB.
|
||||
The application itself requires a tiny fraction of that to run.
|
||||
|
||||
It takes a long time to upload all of that useless bulk and
|
||||
users will wait unnecessarily while library files download piecemeal.
|
||||
|
||||
Load the few files you need from the web instead.
|
||||
|
||||
(1) Make a copy of `index.html` for deployment and replace all `node_module` scripts
|
||||
with versions that load from the web. It might look like this.
|
||||
|
||||
+makeExample('index.html', 'node-module-scripts', '')(format=".")
|
||||
:marked
|
||||
(2) Replace the `systemjs.config.js` script with a script that
|
||||
loads `systemjs.config.server.js`.
|
||||
+makeExample('index.html', 'systemjs-config', '')(format=".")
|
||||
:marked
|
||||
(3) Add `systemjs.config.server.js` (shown in the code sample below) to the root folder.
|
||||
This alternative version configures _SystemJS_ to load _UMD_ versions of Angular
|
||||
(and other third-party packages) from the web.
|
||||
|
||||
Modify `systemjs.config.server.js` as necessary to stay in sync with changes
|
||||
you make to `systemjs.config.js`.
|
||||
|
||||
Notice the `paths` key:
|
||||
|
||||
+makeExample('systemjs.config.server.js', 'paths', '')(format=".")
|
||||
|
||||
:marked
|
||||
In the standard SystemJS config, the `npm` path points to the `node_modules/`.
|
||||
In this server config, it points to
|
||||
<a href="https://unpkg.com/" target="_blank" title="unpkg.com">https://unpkg.com</a>,
|
||||
a site that hosts _npm packages_,
|
||||
and loads them from the web directly.
|
||||
There are other service providers that do the same thing.
|
||||
|
||||
If you are unwilling or unable to load packages from the open web,
|
||||
the inventory in `systemjs.config.server.js` identifies the files and folders that
|
||||
you would copy to a library folder on the server.
|
||||
Then change the config's `'npm'` path to point to that folder.
|
||||
|
||||
### Practice with an example
|
||||
|
||||
The following trivial router sample app shows these changes.
|
||||
|
||||
+makeTabs(
|
||||
`deployment/ts/index.html,
|
||||
deployment/ts/systemjs.config.server.js,
|
||||
deployment/ts/app/main.ts,
|
||||
deployment/ts/app/app.module.ts,
|
||||
deployment/ts/app/app.component.ts,
|
||||
deployment/ts/app/crisis-list.component.ts,
|
||||
deployment/ts/app/hero-list.component.ts
|
||||
`,
|
||||
null,
|
||||
`index.html,
|
||||
systemjs.config.server.js,
|
||||
app/main.ts,
|
||||
app/app.module.ts,
|
||||
app/app.component.ts,
|
||||
app/crisis-list.component.ts,
|
||||
app/hero-list.component.ts
|
||||
`)
|
||||
|
||||
:marked
|
||||
Practice with this sample before attempting these techniques on your application.
|
||||
|
||||
1. Follow the [setup instructions](../guide/setup.html "Angular QuickStart setup") for creating a new project
|
||||
named <ngio-ex path="simple-deployment"></ngio-ex>.
|
||||
|
||||
1. Add the "Simple deployment" sample files shown above.
|
||||
|
||||
1. Run it with `npm start` as you would any project.
|
||||
|
||||
1. Inspect the network traffic in the browser developer tools.
|
||||
Notice that it loads all packages from the web.
|
||||
You could delete the `node_modules` folder and the app would still run
|
||||
(although you wouldn't be able to recompile or launch `lite-server`
|
||||
until you restored it).
|
||||
|
||||
1. Deploy the sample to the server (minus the `node_modules` folder!).
|
||||
|
||||
When you have that working, try the same process on your application.
|
||||
|
||||
a#optimize
|
||||
.l-main-section
|
||||
:marked
|
||||
## Optimize for production
|
||||
|
||||
Although deploying directly from the development environment works, it's far from optimal.
|
||||
|
||||
The client makes many small requests for individual application code and template files,
|
||||
a fact you can quickly confirm by looking at the network tab in a browser's developer tools.
|
||||
Each small file download can spend more time communicating with the server than tranfering data.
|
||||
|
||||
Development files are full of comments and whitespace for easy reading and debugging.
|
||||
The browser downloads entire libraries, instead of just the parts the app needs.
|
||||
The volume of code passed from server to client (the "payload")
|
||||
can be significantly larger than is strictly necessary to execute the application.
|
||||
|
||||
The many requests and large payloads mean
|
||||
the app takes longer to launch than it would if you optimized it.
|
||||
Several seconds may pass (or worse) before the user can see or do anything userful.
|
||||
|
||||
Does it matter? That depends upon business and technical factors you must evaluate for yourself.
|
||||
|
||||
If it _does_ matter, there are tools and techniques to reduce the number of requests and the size of responses.
|
||||
|
||||
- Ahead-of-Time (AOT) Compilation: pre-compiles Angular component templates.
|
||||
- Bundling: concatenates modules into a single file (bundle).
|
||||
- Inlining: pulls template html and css into the components.
|
||||
- Minification: removes excess whitespace, comments, and optional tokens.
|
||||
- Uglification: rewrites code to use short, cryptic variable and function names.
|
||||
- Dead code elimination: removes unreferenced modules and unused code.
|
||||
- Pruned libraries: drop unused libraries and pare others down to the features you need.
|
||||
- Performance measurement: focus on optimizations that make a measurable difference.
|
||||
|
||||
Each tool does something different.
|
||||
They work best in combination and are mutually reinforcing.
|
||||
|
||||
You can use any build system you like.
|
||||
Whatever system you choose, be sure to automate it so that
|
||||
building for production is a single step.
|
||||
|
||||
a#aot
|
||||
:marked
|
||||
### Ahead-of-Time (AOT) compilation
|
||||
|
||||
The Angular _Ahead-of-Time_ compiler pre-compiles application components and their templates
|
||||
during the build process.
|
||||
|
||||
Apps compiled with AOT launch faster for several reasons.
|
||||
* Application components execute immediately, without client-side compilation.
|
||||
* Templates are embedded as code within their components so there is no client-side request for template files.
|
||||
* You don't download the Angular compiler, which is pretty big on its own.
|
||||
* The compiler discards unused Angular directives that a tree-shaking tool can then exclude.
|
||||
|
||||
Learn more about AOT Compilation in the [AOT Cookbook](aot-compiler.html "AOT Cookbook")
|
||||
which describes running the AOT compiler from the command line
|
||||
and using [_rollup_](#rollup) for bundling, minification, uglification and tree shaking.
|
||||
|
||||
a#webpack
|
||||
:marked
|
||||
### Webpack (and AOT)
|
||||
|
||||
<a href="https://webpack.js.org/" target="_blank" title="Webpack 2">Webpack 2</a> is another
|
||||
great option for inlining templates and style-sheets, for bundling, minifying, and uglifying the application.
|
||||
The "[Webpack: an introduction](webpack.html "Webpack: an introduction")" guide will get you started
|
||||
using webpack with Angular.
|
||||
|
||||
Consider configuring _Webpack_ with the official
|
||||
<a href="https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack" target="_blank" title="Ahead-of-Time Webpack Plugin">
|
||||
Angular Ahead-of-Time Webpack Plugin</a>.
|
||||
This plugin transpiles the TypeScript application code,
|
||||
bundles lazy loaded `NgModules` separately,
|
||||
and performs AOT compilation — without any changes to the source code.
|
||||
|
||||
a#rollup
|
||||
:marked
|
||||
### Dead code elimination with _rollup_
|
||||
|
||||
Any code that you don't call is _dead code_.
|
||||
You can reduce the total size of the application substantially by removing dead code from the application and from third-party libraries.
|
||||
|
||||
_Tree shaking_ is a _dead code elimination_ technique that removes entire exports from JavaScript modules.
|
||||
If a library exports something that the application doesn't import, a tree shaking tool removes it from the code base.
|
||||
|
||||
Tree shaking was popularized by
|
||||
<a href="http://rollupjs.org/" target="_blank" title="Rollup">Rollup</a>, a popular tool with an ecosystem of
|
||||
plugins for bundling, minification, and uglification.
|
||||
Learn more about tree shaking and dead code elmination in
|
||||
<a href="https://medium.com/@Rich_Harris/tree-shaking-versus-dead-code-elimination-d3765df85c80#.15ih9cyvl" target="_blank" title="Tree-shaking and Dead Code Elimination">
|
||||
this post</a> by rollup-creator, Rich Harris.
|
||||
|
||||
a#prune
|
||||
:marked
|
||||
### Pruned libraries
|
||||
|
||||
Don't count on automation to remove all dead code.
|
||||
|
||||
Remove libraries that you don't use, especially unnecessary scripts in `index.html`.
|
||||
Consider smaller alternatives to the libraries that you do use.
|
||||
|
||||
Some libraries offer facilities for building a custom, skinny version with just the features you need.
|
||||
Other libraries let you import features _a la carte_.
|
||||
**RxJS** is a good example; import RxJS `Observable` operators individually instead of the entire library.
|
||||
|
||||
a#measure
|
||||
:marked
|
||||
### Measure performance first
|
||||
|
||||
You can make better decisions about what to optimize and how when you have a clear and accurate understanding of
|
||||
what's making the application slow.
|
||||
The cause may not be what you think it is.
|
||||
You can waste a lot of time and money optimizing something that has no tangible benefit or even makes the app slower.
|
||||
You should measure the app's actual behavior when running in the environments that are important to you.
|
||||
|
||||
The
|
||||
<a href="https://developers.google.com/web/tools/chrome-devtools/network-performance/understanding-resource-timing" target="_blank" title="Chrome DevTools Network Performance">
|
||||
Chrome DevTools Network Performance page</a> is a good place to start learning about measuring performance.
|
||||
|
||||
The [WebPageTest](https://www.webpagetest.org/) tool is another good choice
|
||||
that can also help verify that your deployment was successful.
|
||||
|
||||
a#angular-configuration
|
||||
.l-main-section
|
||||
:marked
|
||||
## Angular configuration
|
||||
|
||||
Angular configuration can make the difference between whether the app launches quickly or doesn't load at all.
|
||||
|
||||
a#base-tag
|
||||
:marked
|
||||
### The `base` tag
|
||||
|
||||
The HTML [_<base href="..."/>_](https://angular.io/docs/ts/latest/guide/router.html#!#base-href)
|
||||
specifies a base path for resolving relative URLs to assets such as images, scripts, and style sheets.
|
||||
For example, given the `<base href="/myapp/">`, the browser resolves a URL such as `some/place/foo.jpg`
|
||||
into a server request for `myapp/some/place/foo.jpg`.
|
||||
During navigation, the Angular router uses the _base href_ as the base path to component, template, and module files.
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
See also the [*APP_BASE_HREF*](../api/common/index/APP_BASE_HREF-let.html "API: APP_BASE_HREF") alternative.
|
||||
:marked
|
||||
In development, you typically start the server in the folder that holds `index.html`.
|
||||
That's the root folder and you'd add `<base href="/">` near the top of `index.html` because `/` is the root of the app.
|
||||
|
||||
But on the shared or production server, you might serve the app from a subfolder.
|
||||
For example, when the URL to load the app is something like `http://www.mysite.com/myapp/`,
|
||||
the subfolder is `myapp/` and you should add `<base href="/myapp/">` to the server version of the `index.html`.
|
||||
|
||||
When the `base` tag is misconfigured, the app fails to load and the browser console displays `404 - Not Found` errors
|
||||
for the missing files. Look at where it _tried_ to find those files and adjust the base tag appropriately.
|
||||
|
||||
a#enableProdMode
|
||||
:marked
|
||||
### Enable production mode
|
||||
|
||||
Angular apps run in development mode by default, as you can see by the following message on the browser
|
||||
console:
|
||||
|
||||
code-example(format="nocode").
|
||||
Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
|
||||
:marked
|
||||
Switching to production mode can make it run faster by disabling development specific checks such as the dual change detection cycles.
|
||||
|
||||
To enable [production mode](../api/core/index/enableProdMode-function.html) when running remotely, add the following code to the `main.ts`.
|
||||
|
||||
+makeExample('app/main.ts', 'enableProdMode','app/main.ts (enableProdMode)')(format=".")
|
||||
|
||||
a#lazy-loading
|
||||
:marked
|
||||
### Lazy loading
|
||||
|
||||
You can dramatically reduce launch time by only loading the application modules that
|
||||
absolutely must be present when the app starts.
|
||||
|
||||
Configure the Angular Router to defer loading of all other modules (and their associated code), either by
|
||||
[waiting until the app has launched](router.html#preloading "Preloading")
|
||||
or by [_lazy loading_](router.html#asynchronous-routing "Lazy loading")
|
||||
them on demand.
|
||||
|
||||
#### Don't eagerly import something from a lazy loaded module
|
||||
|
||||
It's a common mistake.
|
||||
You've arranged to lazy load a module.
|
||||
But you unintentionally import it, with a JavaScript `import` statement,
|
||||
in a file that's eagerly loaded when the app starts, a file such as the root `AppModule`.
|
||||
If you do that, the module will be loaded immediately.
|
||||
|
||||
The bundling configuration must take lazy loading into consideration.
|
||||
Because lazy loaded modules aren't imported in JavaScript (as just noted), bundlers exclude them by default.
|
||||
Bundlers don't know about the router configuration and won't create separate bundles for lazy loaded modules.
|
||||
You have to create these bundles manually.
|
||||
|
||||
The
|
||||
[Angular Ahead-of-Time Webpack Plugin](https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack)
|
||||
automatically recognizes lazy loaded `NgModules` and creates separate bundles for them.
|
||||
|
||||
|
||||
a#server-configuration
|
||||
.l-main-section
|
||||
:marked
|
||||
## Server configuration
|
||||
|
||||
This section covers changes you may have make to the server or to files deployed to the server.
|
||||
|
||||
a#fallback
|
||||
:marked
|
||||
### Routed apps must fallback to `index.html`
|
||||
|
||||
Angular apps are perfect candidates for serving with a simple static HTML server.
|
||||
You don't need a server-side engine to dynamically compose application pages because
|
||||
Angular does that on the client-side.
|
||||
|
||||
If the app uses the Angular router, you must configure the server
|
||||
to return the application's host page (`index.html`) when asked for a file that it does not have.
|
||||
|
||||
a#deep-link
|
||||
:marked
|
||||
A routed application should support "deep links".
|
||||
A _deep link_ is a URL that specifies a path to a component inside the app.
|
||||
For example, `http://www.mysite.com/heroes/42` is a _deep link_ to the hero detail page
|
||||
that displays the hero with `id: 42`.
|
||||
|
||||
There is no issue when the user navigates to that URL from within a running client.
|
||||
The Angular router interprets the URL and routes to that page and hero.
|
||||
|
||||
But clicking a link in an email, entering it in the browser address bar,
|
||||
or merely refreshing the browser while on the hero detail page —
|
||||
all of these actions are handled by the browser itself, _outside_ the running application.
|
||||
The browser makes a direct request to the server for that URL, bypassing the router.
|
||||
|
||||
A static server routinely returns `index.html` when it receives a request for `http://www.mysite.com/`.
|
||||
But it rejects `http://www.mysite.com/heroes/42` and returns a `404 - Not Found` error *unless* it is
|
||||
configured to return `index.html` instead.
|
||||
|
||||
#### Fallback configuration examples
|
||||
|
||||
There is no single configuration that works for every server.
|
||||
The following sections describe configurations for some of the most popular servers.
|
||||
The list is by no means exhaustive, but should provide you with a good starting point.
|
||||
|
||||
#### Development servers
|
||||
|
||||
- [Lite-Server](https://github.com/johnpapa/lite-server): the default dev server installed with the
|
||||
[Quickstart repo](https://github.com/angular/quickstart) is pre-configured to fallback to `index.html`.
|
||||
|
||||
- [Webpack-Dev-Server](https://github.com/webpack/webpack-dev-server): setup the
|
||||
`historyApiFallback` entry in the dev server options as follows:
|
||||
|
||||
code-example().
|
||||
historyApiFallback: {
|
||||
disableDotRule: true,
|
||||
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml']
|
||||
}
|
||||
|
||||
:marked
|
||||
#### Production servers
|
||||
|
||||
- [Apache](https://httpd.apache.org/): add a
|
||||
[rewrite rule](http://httpd.apache.org/docs/current/mod/mod_rewrite.html)
|
||||
to the `.htaccess` file as show
|
||||
[here](https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/):
|
||||
code-example(format=".").
|
||||
RewriteEngine On
|
||||
# If an existing asset or directory is requested go to it as it is
|
||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
|
||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
|
||||
RewriteRule ^ - [L]
|
||||
|
||||
# If the requested resource doesn't exist, use index.html
|
||||
RewriteRule ^ /index.html
|
||||
|
||||
:marked
|
||||
- [NGinx](http://nginx.org/): use `try_files`, as described in
|
||||
[Front Controller Pattern Web Apps](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#front-controller-pattern-web-apps),
|
||||
modified to serve `index.html`:
|
||||
|
||||
code-example(format=".").
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
:marked
|
||||
- [IIS](https://www.iis.net/): add a rewrite rule to `web.config`, similar to the one shown
|
||||
[here](http://stackoverflow.com/a/26152011/2116927):
|
||||
code-example(format="." escape="html").
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Angular Routes" stopProcessing="true">
|
||||
<match url=".*" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="/" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
|
||||
:marked
|
||||
- [GitHub Pages](https://pages.github.com/): you can't
|
||||
[directly configure](https://github.com/isaacs/github/issues/408)
|
||||
the GitHub Pages server, but you can add a 404 page.
|
||||
Copy `index.html` into `404.html`.
|
||||
It will still be served as the 404 response, but the browser will process that page and load the app properly.
|
||||
It's also a good idea to
|
||||
[serve from `docs/` on master](https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/#publishing-your-github-pages-site-from-a-docs-folder-on-your-master-branch)
|
||||
and to
|
||||
[create a `.nojekyll` file](https://www.bennadel.com/blog/3181-including-node-modules-and-vendors-folders-in-your-github-pages-site.htm)
|
||||
|
||||
- [Firebase hosting](https://firebase.google.com/docs/hosting/): add a
|
||||
[rewrite rule](https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-rewrites).
|
||||
|
||||
code-example(format=".").
|
||||
"rewrites": [ {
|
||||
"source": "**",
|
||||
"destination": "/index.html"
|
||||
} ]
|
||||
|
||||
a#cors
|
||||
.l-main-section
|
||||
:marked
|
||||
### Requesting services from a different server (CORS)
|
||||
|
||||
Angular developers may encounter a
|
||||
<a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing" target="_blank" title="Cross-origin resource sharing">
|
||||
<i>cross-origin resource sharing</i></a> error when making a service request (typically a data service request).
|
||||
to a server other than the application's own host server.
|
||||
Browsers forbid such requests unless the server permits them explicitly.
|
||||
|
||||
There isn't anything the client application can do about these errors.
|
||||
The server must be configured to accept the application's requests.
|
||||
Read about how to enable CORS for specific servers at
|
||||
<a href="http://enable-cors.org/server.html" target="_blank" title="Enabling CORS server">enable-cors.org</a>.
|
||||
|
||||
a#next-steps
|
||||
.l-main-section
|
||||
:marked
|
||||
## Next steps
|
||||
If you want to go beyond the [simple _copy-deploy_](#dev-deploy "Simplest deployment possible") approach,
|
||||
read the [AOT Cookbook](aot-compiler.html "AOT Cookbook") next.
|
Loading…
x
Reference in New Issue
Block a user