/` 中查看部署好的页面。
Check out [angular-cli-ghpages](https://github.com/angular-buch/angular-cli-ghpages), a full featured package that does all this for you and has extra functionality.
参见 [angular-cli-ghpages](https://github.com/angular-buch/angular-cli-ghpages),这个包用到了全部这些特性,还提供了一些额外功能。
{@a server-configuration}
## Server configuration
## 服务端配置
This section covers changes you may have to make to the server or to files deployed on 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.
没有一种配置可以适用于所有服务器。
后面这些部分会描述对常见服务器的配置方式。
这个列表虽然不够详尽,但可以为你提供一个良好的起点。
* [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/):
[Apache](https://httpd.apache.org/):在 `.htaccess` 文件中添加一个[重写规则](http://httpd.apache.org/docs/current/mod/mod_rewrite.html),
代码如下([出处](https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/)):
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
* [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`:
[NGinx](http://nginx.org/):使用 `try_files` 指向 `index.html`,详细描述见[Web 应用的前端控制器模式](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#front-controller-pattern-web-apps)。
```
try_files $uri $uri/ /index.html;
* [Ruby](https://www.ruby-lang.org/): create a Ruby server using ([sinatra](http://sinatrarb.com/)) with a basic Ruby file that configures the server `server.rb`:
[Ruby](https://www.ruby-lang.org/):使用 [sinatra](http://sinatrarb.com/) 和用来配置服务器的基础 Ruby 文件 `server.rb` 创建一个 Ruby 服务器:
``` ruby
require 'sinatra'
# Folder structure
# .
# -- server.rb
# -- public
# |-- dist
# |-- index.html
get '/' do
folderDir = settings.public_folder + '/dist' # ng build output folder
send_file File.join(folderDir, 'index.html')
end
```
* [IIS](https://www.iis.net/): add a rewrite rule to `web.config`, similar to the one shown
[here](http://stackoverflow.com/a/26152011/2116927):
[IIS](https://www.iis.net/):往 `web.config` 中添加一条重写规则,类似于[这里](http://stackoverflow.com/a/26152011/2116927):
<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>
* [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)
[GitHub 页面服务](https://pages.github.com/):你没办法[直接配置](https://github.com/isaacs/github/issues/408) Github 的页面服务,但可以添加一个 404 页,只要把 `index.html` 复制到 `404.html` 就可以了。
它仍然会给出一个 404 响应,但是浏览器将会正确处理该页,并正常加载该应用。
使用[在主分支的 `docs/` 下启动服务](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)
并[创建一个 `.nojekyll` 文件](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).
[Firebase 主机服务](https://firebase.google.com/docs/hosting/):添加一条[重写规则](https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-rewrites)。
"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。
{@a optimize}
## Production optimizations
## 为生产环境优化
The `--prod` _meta-flag_ engages the following build optimization features.
`--prod` 标志具有如下优化特性。
* [Ahead-of-Time (AOT) Compilation](guide/aot-compiler): pre-compiles Angular component templates.
[预先(AOT)编译](guide/aot-compiler):预编译 Angular 的组件模板。
* [Production mode](#enable-prod-mode): deploys the production environment which enables _production mode_.
[生产模式](#enable-prod-mode):部署到启用了*生产模式*的生产环境。
* Bundling: concatenates your many application and library files into a few bundles.
打包:把你的多个应用于库文件拼接到少量包(bundle)中。
* 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.
消除死代码:删除未引用过的模块和很多未用到的代码。
See [`ng build`](cli/build) for more about CLI build options and what they do.
要了解关于 CLI 构建选项及其作用的更多知识,参见 [`ng build`](cli/build)。
{@a enable-prod-mode}
### Enable runtime production mode
### 启用生产模式
In addition to build optimizations, Angular also has a runtime production mode. Angular apps run in development mode by default, as you can see by the following message on the browser console:
除了构建期优化之外,Angular 还支持运行期生产模式。Angular 应用默认运行在开发模式下,你可以在浏览器的控制台中看到如下信息:
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
Switching to _production mode_ makes it run faster by disabling development specific checks such as the dual change detection cycles.
切换到*生产模式*可以通过禁用开发阶段特有的检查(比如双重变更检测周期)来让它运行得更快。
When you enable production builds via `--prod` command line flag, the runtime production mode is enabled as well.
如果在构建时添加了 `--prod` 标识,也会同时启用*运行期生产模式*。
{@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.
可以配置 Angular 的路由器,来推迟所有其它模块(及其相关代码)的加载时机,方法有[一直等到应用启动完毕](guide/router#preloading "Preloading"),或者当用到时才按需[*惰性加载*](guide/router#asynchronous-routing "Lazy loading")。
Don't eagerly import something from a lazy-loaded module
不要急性(eagerly)导入来自惰性加载模块中的任何东西
If you mean to lazy-load a module, be careful not import it
in a file that's eagerly loaded when the app starts (such as the root `AppModule`).
If you do that, the module will be loaded immediately.
如果要惰性加载某个模块,就要小心别在应用启动时要急性加载的模块(比如根模块 `AppModule`)中导入它。
如果那么做,该模块就会立刻加载起来。
The bundling configuration must take lazy loading into consideration.
Because lazy-loaded modules aren't imported in JavaScript, bundlers exclude them by default.
Bundlers don't know about the router configuration and can't create separate bundles for lazy-loaded modules.
You would have to create these bundles manually.
配置打包方式时必须考虑惰性加载。
因为默认情况下惰性加载的模块没有在 JavaScript 中导入过,因此打包器默认会排除它们。
打包器不认识路由器配置,也就不能为惰性加载的模块创建独立的包。
你必须手动创建这些包。
The CLI runs the
[Angular Ahead-of-Time Webpack Plugin](https://github.com/angular/angular-cli/tree/master/packages/ngtools/webpack)
which automatically recognizes lazy-loaded `NgModules` and creates separate bundles for them.
CLI 会运行 [Angular Ahead-of-Time Webpack 插件](https://github.com/angular/angular-cli/tree/master/packages/ngtools/webpack),它会自动识别出惰性加载的 `NgModules`,并为它们创建独立的包。
{@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.
Chrome DevTools 的网络和性能页是你开始学习如何测量性能的好地方。
The [WebPageTest](https://www.webpagetest.org/) tool is another good choice
that can also help verify that your deployment was successful.
[WebPageTest](https://www.webpagetest.org/)工具是另一个不错的选择,它还能帮你验证这次部署是否成功。
{@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.
source-map-explorer 工具可以帮你在生产环境构建之后探查 JavaScript 包。
Install `source-map-explorer`:
安装 `source-map-explorer`:
npm install source-map-explorer --save-dev
Build your app for production _including the source maps_
为生产环境构建应用,包括源码映射表(source map)
ng build --prod --source-map
List the generated bundles in the `dist/` folder.
在 `dist/` 目录下列出生成的包。
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.
运行浏览器来生成其中一个包的图形化表示。
下面的例子展示了 `main` 包的图表。
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.
`source-map-explorer` 会分析与包一起生成的 source map,并画出所有依赖的地图,精确展示哪些类包含在哪个包中。
Here's the output for the _main_ bundle of an example app called `cli-quickstart`.
下面是范例应用 `cli-quickstart` 中 `main` 包的输出。
{@a base-tag}
## The `base` tag
## `base` 标签
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 ``, 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.
HTML 的 [_<base href="..."/>_](/guide/router) 标签指定了用于解析静态文件(如图片、脚本和样式表)相对地址的基地址。
比如,对于 ``,浏览器就会把 `some/place/foo.jpg` 这样的 URL 解析成到 `my/app/some/place/foo.jpg` 的请求。
在导航期间,Angular 路由器使用 *base href* 作为到组件模板文件和模块文件的基地址。
See also the [*APP_BASE_HREF*](api/common/APP_BASE_HREF "API: APP_BASE_HREF") alternative.
另一种方式参见 [*APP_BASE_HREF*](api/common/APP_BASE_HREF "API: APP_BASE_HREF")。
In development, you typically start the server in the folder that holds `index.html`.
That's the root folder and you'd add `` near the top of `index.html` because `/` is the root of the app.
在开发期间,你通常会在存有 `index.html` 的目录下启动开发服务器。
那就是根目录,你要在 `index.html` 的顶部附近添加 ``,因为 `/` 就是该应用的根路径。
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 `` to the server version of the `index.html`.
但是在共享或生产服务器上,你可能会在子目录下启动服务器。
比如,当前应用的加载地址可能类似于 `http://www.mysite.com/my/app/`,这里的子目录就是 `my/app/`。所以你就要往服务端版本的 `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.
这里如果不配置 `base` 标签,应用就会失败,并在浏览器的控制台中为缺失的文件显示一个 `404 - Not Found` 错误。看看它*试图*从哪里去查找那些文件,并据此调整 base 标签。
{@a differential-loading}
## Differential Loading
## 差异化加载
When building web applications, you want to make sure your application is compatible with the majority of browsers.
Even as JavaScript continues to evolve, with new features being introduced, not all browsers are updated with support for these new features at the same pace.
在构建 Web 应用时,你肯定想确保你的应用与大多数浏览器兼容。JavaScript 在不断发展,新功能不断推出,不是所有浏览器都能以同样的进度实现这些新功能。
The code you write in development using TypeScript is compiled and bundled into ES2015, the JavaScript syntax that is compatible with most browsers.
All modern browsers support ES2015 and beyond, but in most cases, you still have to account for users accessing your application from a browser that doesn't.
When targeting older browsers, [polyfills](guide/browser-support#polyfills) can bridge the gap by providing functionality that doesn't exist in the older versions of JavaScript supported by those browsers.
你在开发过程中使用 TypeScript 编写的代码会被编译并打包成 ES2015,这种 JavaScript
语法兼容大多数浏览器。
所有现代浏览器都支持 ES2015 和更新的版本,但是大多数情况下,你仍然要让用户能从不支持它的浏览器中访问你的应用。
当以老式浏览器为目标时,[腻子脚本(polyfills)](guide/browser-support#polyfills)可以提供一些老式浏览器中不存在的功能,从而抹平这种差距。
To maximize compatibility, you could ship a single bundle that includes all your compiled code, plus any polyfills that may be needed.
Users with modern browsers, however, shouldn't have to pay the price of increased bundle size that comes with polyfills they don't need.
Differential loading, which is supported by default in Angular CLI version 8 and higher, solves this problem.
为了最大限度地提高兼容性,你可以发布一个包含所有已编译代码的发布包(bundle),以及所有可能会用到的腻子脚本。用户如果在支持大量最新 JavaScript 特性的现代浏览器中使用此应用,就不应该为这些他们用不到的包带来的额外体积付出代价。差异化加载就是解决这个问题的。Angular CLI 8 及更高版本默认就支持它。
Differential loading is a strategy that allows your web application to support multiple browsers, but only load the necessary code that the browser needs. When differential loading is enabled (which is the default) the CLI builds two separate bundles as part of your deployed application.
差异化加载是一种策略,它能让你的应用支持多种浏览器,但是只加载当前浏览器必须用到的代码。
当(默认)启用了差异化加载时,CLI 会构建出两个单独的包,作为你要发布的应用的一部分。
* The first bundle contains modern ES2015 syntax, takes advantage of built-in support in modern browsers, ships fewer polyfills, and results in a smaller bundle size.
第一个包是使用现代的 ES2015 语法,它能发挥现代浏览器内置支持的优势,发布更少的腻子脚本,因此打包尺寸更小。
* The second bundle contains code in the old ES5 syntax, along with all necessary polyfills. This results in a larger bundle size, but supports older browsers.
第二个包使用老式的 ES5 语法,包含所有必要的腻子脚本。其打包尺寸更大,但是支持老式浏览器。
### Differential builds
### 差异化构建
When you deploy using the Angular CLI build process, you can choose how and when to support differential loading.
The [`ng build` CLI command](cli/build) queries the browser configuration and the configured build target to determine if support for legacy browsers is required, and whether the build should produce the necessary bundles used for differential loading.
使用 Angular CLI 构建过程进行部署时,可以选择如何以及何时支持差异化加载。 [`ng build` CLI 命令](cli/build)会查询浏览器配置和配置的构建目标,以确定是否需要支持旧版浏览器,以及该构建是否应产生用于差异化加载的必要捆绑包。
The following configurations determine your requirements.
会根据下列配置确定您的要求。
* Browsers list
浏览器列表
The `browserslist` configuration file is included in your application [project structure](guide/file-structure#application-configuration-files) and provides the minimum browsers your application supports. See the [Browserslist spec](https://github.com/browserslist/browserslist) for complete configuration options.
`browserslist` 配置文件包含在应用的[项目结构中](guide/file-structure#application-configuration-files),它提供了本应用打算支持的最低浏览器版本。有关完整的配置选项,请参阅 [Browserslist 规范](https://github.com/browserslist/browserslist) 。
* TypeScript configuration
TypeScript 配置
In the TypeScript configuration file, `tsconfig.json`, the "target" option in the `compilerOptions` section determines the ECMAScript target version that the code is compiled to.
Modern browsers support ES2015 natively, while ES5 is more commonly used to support legacy browsers.
在 TypeScript 的配置文件 `tsconfig.json` 中,`compilerOptions` 区的 `target` 选项会决定编译后代码的 ECMAScript 目标版本。现代浏览器原生支持 ES2015,而 ES5 则更常用于支持老式浏览器。
Differential loading is currently only supported when using `es2015` as a compilation target. When used with targets higher than `es2015`, the build process emits a warning.
当前仅在将 `es2015` 用作编译目标时才支持差异化加载。当目标高于 `es2015` 时,构建过程将发出警告。
For a development build, the output produced by `ng build` is simpler and easier to debug, allowing you to rely less on sourcemaps of compiled code.
对于开发版本,由 `ng build` 生成的输出更简单且易于调试,从而减小您对编译代码的 sourcemaps 的依赖。
For a production build, your configuration determines which bundles are created for deployment of your application.
When needed, the `index.html` file is also modified during the build process to include script tags that enable differential loading, as shown in the following example.
对于生产版本,您的配置将决定创建哪些捆绑软件来部署您的应用程序。必要时,还会在构建过程中修改 `index.html` 文件,以包括启用差异化加载的脚本标签,如以下示例所示。
<body>
<app-root></app-root>
<script src="runtime-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="polyfills-es5.js" nomodule></script>
<script src="styles-es2015.js" type="module"></script>
<script src="styles-es5.js" nomodule></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule></script>
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule></script>
</body>
Each script tag has a `type="module"` or `nomodule` attribute. Browsers with native support for ES modules only load the scripts with the `module` type attribute and ignore scripts with the `nomodule` attribute. Legacy browsers only load the scripts with the `nomodule` attribute, and ignore the script tags with the `module` type that load ES modules.
每个 script 标签都有一个 `type="module"` 或 `nomodule` 属性。原生支持 ES 模块的浏览器只会加载带有该类型属性的脚本,而忽略那些带有 `nomodule` 属性的脚本。而老式浏览器只会加载带有`nomodule`属性的脚本,而忽略那些 type 为 `module` 的脚本标签。
Some legacy browsers still download both bundles, but only execute the appropriate scripts based on the attributes mentioned above. You can read more on the issue [here](https://github.com/philipwalton/webpack-esnext-boilerplate/issues/1).
一些旧版浏览器仍会下载两个捆绑包,但只会根据上述属性执行适当的脚本。您可以在[此处](https://github.com/philipwalton/webpack-esnext-boilerplate/issues/1)阅读有关此问题的更多[信息](https://github.com/philipwalton/webpack-esnext-boilerplate/issues/1) 。
### Configuring differential loading
### 配置差异化加载
Differential loading is supported by default with version 8 and later of the Angular CLI.
For each application project in your workspace, you can configure how builds are produced based on the `browserslist` and `tsconfig.json` configuration files in your application project.
Angular CLI 第 8 版及更高版本已默认支持构建差异化加载的发布包。工作空间中的每个应用项目,都可以根据其中的 `browserslist` 和 `tsconfig.json` 配置文件来决定发布包的构建方式。
For a newly created Angular application, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015.
对于新创建的 Angular 应用程序,将忽略 IE 9-11 等旧版浏览器,并且编译目标为 ES2015。
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "esnext",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}
The default configuration creates two builds, with differential loading enabled.
默认配置将创建两个版本,并启用差异化加载。
To see which browsers are supported with the default configuration and determine which settings meet to your browser support requirements, see the [Browserslist compatibility page](https://browserl.ist/?q=%3E+0.5%25%2C+last+2+versions%2C+Firefox+ESR%2C+not+dead%2C+not+IE+9-11).
要查看这种默认配置支持哪些浏览器,以及决定哪些设置适合你要支持的浏览器,请参阅“ [浏览器列表兼容性”页面](https://browserl.ist/?q=%3E+0.5%25%2C+last+2+versions%2C+Firefox+ESR%2C+Chrome+41%2C+not+dead%2C+not+IE+9-11) 。
The `browserslist` configuration allows you to ignore browsers without ES2015 support. In this case, a single build is produced.
`browserslist` 配置允许您忽略不支持 ES2015 的浏览器。在这种情况下,将只生成一个版本。
If your `browserslist` configuration includes support for any legacy browsers, the build target in the TypeScript configuration determines whether the build will support differential loading.
如果您的 `browserslist` 配置包括对所有旧版浏览器的支持,则 TypeScript 配置中的构建目标将确定该构建是否将支持差异化加载。
{@a configuration-table }
| browserslist | ES target | Build result |
| -------- | -------- | -------- |
| 浏览器列表 | ES 目标 | 构建结果 |
| ES5 support disabled | es2015 | Single build, ES5 not required |
| 禁用 ES5 支持 | es2015 | 单一构建,不行可 ES5 |
| ES5 support enabled | es5 | Single build w/conditional polyfills for ES5 only |
| 启用 ES5 支持 | es5 | 单一构建,按需附带只供 ES5 使用的腻子脚本 |
| ES5 support enabled | es2015 | Differential loading (two builds w/conditional polyfills) |
| 启用 ES5 支持 | es2015 | 差异化加载(两个构建,按需附带腻子脚本) |
### Opting out of differential loading
### 选择性地排除差异化加载
Differential loading can be explicitly disabled if it causes unexpected issues, or if you need to target ES5 specifically for legacy browser support.
如果差异化加载导致了意外问题,或者您需要专门针对旧版浏览器支持而将 ES5 作为目标,则可以显式禁用差异化加载。
To explicitly disable differential loading and create an ES5 build:
要显式禁用差异化加载并创建 ES5 版本,请执行以下操作:
- Enable the `dead` or `IE` browsers in the `browserslist` configuration file by removing the `not` keyword in front of them.
在 `browserslist` 配置文件中通过移除前面的 `not` 关键字来启用 `dead` 或 `IE` 中的浏览器。
- To create a single ES5 build, set the target in the `compilerOptions` to `es5`.
要创建一个单一的 ES5 的构建,把 `compilerOptions` 中的 `target` 设为 `es5` 。
{@a test-and-serve}
## Local development in older browsers
## 旧版浏览器中的本地开发
In Angular CLI version 8 and higher, differential loading is enabled by default for the `ng build` command.
The `ng serve`, `ng test`, and `ng e2e` commands, however, generate a single ES2015 build which cannot run in older browsers that don't support the modules, such as IE 11.
在 Angular CLI 版本 8 和更高版本中,默认情况下会为 `ng build` 命令启用差异化加载。但是,`ng serve`,`ng test`和 `ng e2e` 命令只会生成一个 ES2015 版本,该版本无法在不支持该模块的旧版浏览器(例如 IE 11)中运行。
If you want to run ES5 code during development, you could disable differential loading completely.
To maintain the benefits of differential loading, however, a better option is to define multiple configurations for `ng serve`, `ng e2e`, and `ng test`.
如果要在开发期间运行 ES5 代码,则可以完全禁用差异化加载。但是,为了保持差异化加载的好处,更好的选择是为 `ng serve` ,`ng e2e` 和 `ng test` 定义多个配置。
{@a differential-serve}
### Configuring serve for ES5
### 为 ES5 配置服务
To do this for `ng serve`, create a new file, `tsconfig-es5.app.json` next to `tsconfig.app.json` with the following content.
要让 `ng serve` 做到这一点,就要在 `tsconfig.app.json` 后面创建一个新的文件 `tsconfig-es5.app.json`,包含以下内容。
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"target": "es5"
}
}
In `angular.json` add two new configuration sections under the `build` and `serve` targets to point to the new TypeScript configuration.
在 `angular.json` 中,在 `build` 和 `serve` 下添加两个新的配置节,其目标指向新的 TypeScript 配置。
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
...
},
"configurations": {
"production": {
...
},
"es5": {
"tsConfig": "./tsconfig-es5.app.json"
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
...
},
"configurations": {
"production": {
...
},
"es5": {
"browserTarget": "<app-name>:build:es5"
}
}
},
You can then run the `ng serve` command with this configuration. Make sure to replace `` (in `":build:es5"`) with the actual name of the app, as it appears under `projects` in `angular.json`. For example, if your app name is `myAngularApp` the config will become `"browserTarget": "myAngularApp:build:es5"`.
然后,您可以使用此配置运行 `ng serve` 命令。务必确保将 ``(在`":build:es5"` 中)替换为应用程序的实际名称,因为它也会出现在 `angular.json` 的 `projects` 中。例如,如果您的应用程序名称为 `myAngularApp` 则配置要变成 `"browserTarget": "myAngularApp:build:es5"`。
ng serve --configuration es5
{@a differential-test}
### Configuring the test command
### 配置 `test` 命令
Create a new file, `tsconfig-es5.spec.json` next to `tsconfig.spec.json` with the following content.
创建一个新的文件,在 `tsconfig.spec.json` 后面 `tsconfig-es5.spec.json`,包含以下内容。
{
"extends": "./tsconfig.spec.json",
"compilerOptions": {
"target": "es5"
}
}
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
...
},
"configurations": {
"es5": {
"tsConfig": "./tsconfig-es5.spec.json"
}
}
},
You can then run the tests with this configuration
然后,您可以使用此配置运行测试了
ng test --configuration es5
### Configuring the e2e command
### 配置 `e2e` 命令
Create an [ES5 serve configuration](guide/deployment#configuring-serve-for-es5) as explained above, and configuration an ES5 configuration for the E2E target.
如上所述创建 [ES5 serve 配置](guide/deployment#configuring-serve-for-es5) ,并为 E2E 目标配置上 ES5 配置。
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
...
},
"configurations": {
"production": {
...
},
"es5": {
"devServerTarget": "<app-name>:serve:es5"
}
}
},
You can then run the `ng e2e` command with this configuration. Make sure to replace `` (in `":serve:es5"`) with the actual name of the app, as it appears under `projects` in `angular.json`. For example, if your app name is `myAngularApp` the config will become `"devServerTarget": "myAngularApp:serve:es5"`.
然后,您就可以使用此配置运行 `ng e2e` 命令了。务必确保将 ``(在`":serve:es5"` 中)替换为应用程序的实际名称,因为它也出现在 `angular.json` 的 `projects`中。例如,如果您的应用程序名称为 `myAngularApp` 则配置要变成 `"devServerTarget": "myAngularApp:serve:es5"` 。
ng e2e --configuration es5