382 lines
15 KiB
Markdown
382 lines
15 KiB
Markdown
# Deployment
|
|
|
|
This page describes techniques for deploying your Angular application to a remote server.
|
|
|
|
{@a dev-deploy}
|
|
{@a copy-files}
|
|
|
|
## Simplest deployment possible
|
|
|
|
For the simplest deployment, build for development and copy the output directory to a web server.
|
|
|
|
1. Start with the development build
|
|
|
|
<code-example language="none" class="code-shell">
|
|
ng build
|
|
</code-example>
|
|
|
|
|
|
2. Copy _everything_ within the output folder (`dist/` by default) to a folder on the server.
|
|
|
|
|
|
3. If you copy the files into a server _sub-folder_, append the build flag, `--base-href` and set the `<base href>` appropriately.<br><br>
|
|
|
|
For example, if the `index.html` is on the server at `/my/app/index.html`, set the _base href_ to
|
|
`<base href="/my/app/">` like this.
|
|
|
|
<code-example language="none" class="code-shell">
|
|
ng build --base-href=/my/app/
|
|
</code-example>
|
|
|
|
You'll see that the `<base href>` is set properly in the generated `dist/index.html`.<br><br>
|
|
If you copy to the server's root directory, omit this step and leave the `<base href>` alone.<br><br>
|
|
Learn more about the role of `<base href>` [below](guide/deployment#base-tag).
|
|
|
|
|
|
4. Configure the server to redirect requests for missing files to `index.html`.
|
|
Learn more about server-side redirects [below](guide/deployment#fallback).
|
|
|
|
|
|
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.
|
|
|
|
{@a optimize}
|
|
|
|
## Optimize for production
|
|
|
|
Although deploying directly from the development environment works,
|
|
you can generate an optimized build with additional CLI command line flags,
|
|
starting with `--prod`.
|
|
|
|
### Build with _--prod_
|
|
|
|
<code-example language="none" class="code-shell">
|
|
ng build --prod
|
|
</code-example>
|
|
|
|
The `--prod` _meta-flag_ engages the following optimization features.
|
|
|
|
* [Ahead-of-Time (AOT) Compilation](guide/aot-compiler): pre-compiles Angular component templates.
|
|
* [Production mode](#enable-prod-mode): deploys the production environment which enables _production mode_.
|
|
* Bundling: concatenates your many application and library files into a few bundles.
|
|
* 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 much unused code.
|
|
|
|
The remaining [copy deployment steps](#copy-files) are the same as before.
|
|
|
|
You may further reduce bundle sizes by adding the `build-optimizer` flag.
|
|
|
|
<code-example language="none" class="code-shell">
|
|
ng build --prod --build-optimizer
|
|
</code-example>
|
|
|
|
See the [CLI Documentation](https://github.com/angular/angular-cli/wiki/build)
|
|
for details about available build options and what they do.
|
|
|
|
{@a enable-prod-mode}
|
|
|
|
### 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 is running in the development mode. Call enableProdMode() to enable the production mode.
|
|
</code-example>
|
|
|
|
Switching to _production mode_ can make it run faster by disabling development specific checks such as the dual change detection cycles.
|
|
|
|
Building for production (or appending the `--environment=prod` flag) enables _production mode_
|
|
Look at the CLI-generated `main.ts` to see how this works.
|
|
|
|
{@a lazy-loading}
|
|
|
|
### 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](guide/router#preloading "Preloading")
|
|
or by [_lazy loading_](guide/router#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 CLI runs the
|
|
[Angular Ahead-of-Time Webpack Plugin](https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack)
|
|
which automatically recognizes lazy loaded `NgModules` and creates separate bundles for them.
|
|
|
|
{@a measure}
|
|
|
|
### Measure performance
|
|
|
|
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" 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 inspect-bundle}
|
|
|
|
### Inspect the bundles
|
|
|
|
The <a href="https://github.com/danvk/source-map-explorer/blob/master/README.md">source-map-explorer</a>
|
|
tool is a great way to inspect the generated JavaScript bundles after a production build.
|
|
|
|
Install `source-map-explorer`:
|
|
|
|
<code-example language="none" class="code-shell">
|
|
npm install source-map-explorer --save-dev
|
|
</code-example>
|
|
|
|
Build your app for production _including the source maps_
|
|
|
|
<code-example language="none" class="code-shell">
|
|
ng build --prod --sourcemaps
|
|
</code-example>
|
|
|
|
List the generated bundles in the `dist/` folder.
|
|
|
|
<code-example language="none" class="code-shell">
|
|
ls dist/*.bundle.js
|
|
</code-example>
|
|
|
|
Run the explorer to generate a graphical representation of one of the bundles.
|
|
The following example displays the graph for the _main_ bundle.
|
|
|
|
<code-example language="none" class="code-shell">
|
|
node_modules/.bin/source-map-explorer dist/main.*.bundle.js
|
|
</code-example>
|
|
|
|
The `source-map-explorer` analyzes the source map generated with the bundle and draws a map of all dependencies,
|
|
showing exactly which classes are included in the bundle.
|
|
|
|
Here's the output for the _main_ bundle of the QuickStart.
|
|
|
|
<figure>
|
|
<img src="generated/images/guide/cli-quickstart/quickstart-sourcemap-explorer.png" alt="quickstart sourcemap explorer">
|
|
</figure>
|
|
|
|
{@a base-tag}
|
|
|
|
## The `base` tag
|
|
|
|
The HTML [_<base href="..."/>_](/guide/router)
|
|
specifies a base path for resolving relative URLs to assets such as images, scripts, and style sheets.
|
|
For example, given the `<base href="/my/app/">`, the browser resolves a URL such as `some/place/foo.jpg`
|
|
into a server request for `my/app/some/place/foo.jpg`.
|
|
During navigation, the Angular router uses the _base href_ as the base path to component, template, and module files.
|
|
|
|
<div class="l-sub-section">
|
|
|
|
See also the [*APP_BASE_HREF*](api/common/APP_BASE_HREF "API: APP_BASE_HREF") alternative.
|
|
|
|
</div>
|
|
|
|
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/my/app/`,
|
|
the subfolder is `my/app/` and you should add `<base href="/my/app/">` to the server version of the `index.html`.
|
|
|
|
When the `base` tag is mis-configured, 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.
|
|
|
|
## _build_ vs. _serve_
|
|
|
|
You'll probably prefer `ng build` for deployments.
|
|
|
|
The **ng build** command is intended for building the app and deploying the build artifacts elsewhere.
|
|
The **ng serve** command is intended for fast, local, iterative development.
|
|
|
|
Both `ng build` and `ng serve` **clear the output folder** before they build the project.
|
|
The `ng build` command writes generated build artifacts to the output folder.
|
|
The `ng serve` command does not.
|
|
It serves build artifacts from memory instead for a faster development experience.
|
|
|
|
<div class="l-sub-section">
|
|
|
|
The output folder is `dist/` by default.
|
|
To output to a different folder, change the `outputPath` in `angular.json`.
|
|
|
|
</div>
|
|
|
|
The `ng serve` command builds, watches, and serves the application from a local CLI development server.
|
|
|
|
The `ng build` command generates output files just once and does not serve them.
|
|
The `ng build --watch` command will regenerate output files when source files change.
|
|
This `--watch` flag is useful if you're building during development and
|
|
are automatically re-deploying changes to another server.
|
|
|
|
|
|
See the [CLI `build` topic](https://github.com/angular/angular-cli/wiki/build) for more details and options.
|
|
|
|
<hr>
|
|
|
|
{@a server-configuration}
|
|
|
|
## Server configuration
|
|
|
|
This section covers changes you may have make to the server or to files deployed to the server.
|
|
|
|
{@a fallback}
|
|
|
|
### 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}
|
|
|
|
|
|
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']
|
|
}
|
|
</code-example>
|
|
|
|
|
|
#### 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 shown
|
|
(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
|
|
</code-example>
|
|
|
|
|
|
* [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;
|
|
</code-example>
|
|
|
|
|
|
* [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='.'>
|
|
<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="/index.html" />
|
|
</rule>
|
|
</rules>
|
|
</rewrite>
|
|
</system.webServer>
|
|
|
|
</code-example>
|
|
|
|
|
|
* [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"
|
|
} ]
|
|
|
|
</code-example>
|
|
|
|
{@a cors}
|
|
|
|
### Requesting services from a different server (CORS)
|
|
|
|
Angular developers may encounter a
|
|
<a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing" 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" title="Enabling CORS server">enable-cors.org</a>.
|