angular-cn/aio/content/guide/deployment.md

22 KiB
Raw Blame History

Deployment

部署

This page describes techniques for deploying your Angular application to a remote server.

本章会描述在远程服务器上部署Angular应用的工具与技术。

{@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.

最简化的部署方式就是为开发环境构建,并把其输出复制到 Web 服务器上。

  1. Start with the development build

    使用开发环境进行构建

ng build
  1. Copy everything within the output folder (dist/ by default) to a folder on the server.

把输出目录(默认为dist/)下的每个文件都复制到到服务器上的某个目录下。

  1. If you copy the files into a server sub-folder, append the build flag, --base-href and set the <base href> appropriately.

如果要把文件部署到服务器上的某个子路径下,构建时还要添加--base-href(基地址)标识,并设置合适的<base href>

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.

比如,如果 index.html 位于服务器上的 /my/app/index.html 路径下,就要把 base href 设置为 <base href="/my/app/">,就像这样:

ng build --base-href=/my/app/

You'll see that the <base href> is set properly in the generated dist/index.html.

If you copy to the server's root directory, omit this step and leave the <base href> alone.

Learn more about the role of <base href> below.

我们会看到在生成的 dist/index.html<base href> 已经被设置好了。

如果复制到服务器的根目录下,就省略这个步骤,并且让 <base href> 保持原样。

要了解 <base href> 的作用,参见 下面 的内容。

  1. Configure the server to redirect requests for missing files to index.html. Learn more about server-side redirects below.

    配置服务器,使其在找不到文件时把请求重定向到 index.html。要了解服务端重定向的更多知识,参见 下面 的内容。

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

ng build --prod

The --prod meta-flag engages the following optimization features.

  • Ahead-of-Time (AOT) Compilation: pre-compiles Angular component templates.

    预(AOT)编译:预编译 Angular 组件的模板。

  • Production mode: deploys the production environment which enables production mode.

    生产模式:启用生产模式部署到生产环境。

  • Bundling: concatenates your many application and library files into a few bundles.

    打捆Bundle把这些模块串接成一个单独的捆文件bundle

  • Minification: removes excess whitespace, comments, and optional tokens.

    最小化移除不必要的空格、注释和可选令牌Token

  • 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 are the same as before.

剩下的 拷贝部署步骤 和以前的方式是一样的。

You may further reduce bundle sizes by adding the build-optimizer flag.

ng build --prod --build-optimizer

See the CLI Documentation 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:

Angular应用默认运行在开发模式下正如在浏览器控制台中看到的如下信息

Angular is running in the development mode. Call enableProdMode() to enable the production mode. Angular正运行在开发模式下。调用enableProdMode()来启用生产模式)

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 or by lazy loading them on demand.

配置Angular路由器可以延迟加载所有其它模块以及与它们相关的代码无论是等应用启动 还是在需要时才惰性加载

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.

这是一种常犯的错误。 我们本打算惰性加载一个模块,但可能无意中在根模块AppModule文件中使用一个JavaScript的import语句导入了它。 这样一来,该模块就被立即加载了。

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.

关于打包bundle方式的配置必须考虑到惰性加载问题。 因为惰性加载模块不能在JavaScript中导入就像刚才说明的打包器应该默认排除它们。 打包器不知道路由器的配置,并且不会为延迟加载模块创建单独的包。 我们不得不手动创建这些包。

The CLI runs the Angular Ahead-of-Time Webpack Plugin 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 Chrome DevTools Network Performance page is a good place to start learning about measuring performance.

The WebPageTest tool is another good choice that can also help verify that your deployment was successful.

{@a inspect-bundle}

Inspect the bundles

The source-map-explorer tool is a great way to inspect the generated JavaScript bundles after a production build.

Install source-map-explorer:

npm install source-map-explorer --save-dev

Build your app for production including the source maps

ng build --prod --sourcemaps

List the generated bundles in the dist/ folder.

ls dist/*.bundle.js

Run the explorer to generate a graphical representation of one of the bundles. The following example displays the graph for the main bundle.

node_modules/.bin/source-map-explorer dist/main.*.bundle.js

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.

quickstart sourcemap explorer

{@a base-tag}

The base tag

The 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="/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.

See also the APP_BASE_HREF alternative.

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.

The output folder is dist/ by default. To output to a different folder, change the outDir in .angular-cli.json.

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 for more details and options.


{@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

带路由的应用必须以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.

Angular应用很适合用简单的静态HTML服务器提供服务。 我们不需要服务端引擎来动态合成应用页面因为Angular会在客户端完成这件事。

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.

如果该应用使用Angular路由器我们就必须配置服务器让它对不存在的文件返回应用的宿主页(index.html)。

{@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.

带路由的应用应该支持“深链接”。 所谓深链接就是指一个URL它用于指定到应用内某个组件的路径。 比如,http://www.mysite.com/heroes/42就是一个到英雄详情页面的深链接,用于显示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.

当用户从运行中的客户端应用导航到这个URL时这没问题。 Angular路由器会拦截这个URL并且把它路由到正确的页面。

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.

但是,当从邮件中点击链接或在浏览器地址栏中输入它或仅仅在英雄详情页刷新下浏览器时,所有这些操作都是由浏览器本身处理的,在应用的控制范围之外。 浏览器会直接向服务器请求那个URL路由器没机会插手。

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.

静态服务器会在收到对http://www.mysite.com/的请求时返回index.html,但是会拒绝对http://www.mysite.com/heroes/42的请求, 并返回一个404 - Not Found错误,除非,我们把它配置成转而返回index.html

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: the default dev server installed with the Quickstart repo is pre-configured to fallback to index.html.

    Lite-Server"快速上手"仓库中安装的默认开发服务器,它被预先配置为回退到index.html

  • Webpack-Dev-Server: setup the historyApiFallback entry in the dev server options as follows:

    Webpack-Dev-Server在开发服务器的配置中设置了historyApiFallback,代码如下:

    historyApiFallback: { disableDotRule: true, htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'] }

Production servers

生产服务器

NGinx:使用try_files指向index.html,详细描述见Web应用的前端控制器模式。 try_files $uri $uri/ /index.html;

  • IIS: add a rewrite rule to web.config, similar to the one shown here:

IIS:往web.config中添加一条重写规则,类似于这里 <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>

Firebase主机服务:添加一条重写规则。 "rewrites": [ { "source": "**", "destination": "/index.html" } ]

{@a cors}

Requesting services from a different server (CORS)

请求来自另一个服务器的服务CORS

Angular developers may encounter a cross-origin resource sharing 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.

Angular开发者在向与该应用的宿主服务器不同域的服务器发起请求时可能会遇到一种跨域资源共享CORS错误。 浏览器会阻止该请求,除非得到那台服务器的明确许可。

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 enable-cors.org.

客户端应用对这种错误无能为力。 服务器必须配置成可以接受来自该应用的请求。 要了解如何对特定的服务器开启CORS参见enable-cors.org