Angular2官方文档学习笔记之部署

20170627149856672173184.jpg

最简化的部署方式

  1. 把一切文件(部分文件可以通过cdn加载)从本地项目目录下复制到服务器目录下
  2. 如果准备把该应用放在子目录下,就要编辑index.html,并适当设置<base href>。 比如,如果到index.html的URL是www.mysite.com/my/app/,就把基地址设置为<base href="/my/app/">(如果使用angular/cli,index.html不用变,ng serve后面加上--base-href /my/app)。如果是放在根路径下就不用动它。
  3. 把服务器上缺失的文件重定向到index.html
  4. 按后面的描述启用生产模式(可选)

从Web上加载npm包(SystemJS)

node_modules文件夹包含着在浏览器中运行应用时所需的代码。 运行应用时其实只需要其中很小的一部分。可以转而从网上下载所需的少量文件,加快页面加载速度。

  1. 复制一份专用于部署的index.html,并把所有的node_module脚本替换成加载网上的版本。代码如下:
1
2
3
4
5
6
<!-- Polyfills -->
<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.8.4?main=browser"></script>
<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
  1. systemjs.config.js脚本改为加载systemjs.config.server.js
1
2
<!-- This SystemJS configuration loads umd packages from the web -->
<script src="systemjs.config.server.js"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* 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({
/*在标准的SystemJS配置中,npm路径指向node_modules/。 在服务器端的配置中,它指向https://unpkg.com(一个专门存放npm包的服务器), 并从网上直接加载它们。*/
paths: {
'npm:': 'https://unpkg.com/' // path serves as alias
},
// 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);
  1. systemjs.config.server.js复制到src/文件夹。 这个版本会从网上加载Angular的UMD版本(和其它第三方包)。

为生产环境优化

减少请求数和体积的方法:

  • 预编译(AOT):预编译Angular的组件模板。
  • 打捆(Bundle):把这些模块串接成一个单独的捆文件(bundle)。
  • 内联:把模板html和css拉到组件中。
  • 最小化:移除不必要的空格、注释和可选令牌(Token)。
  • 混淆:使用短的、无意义的变量名和函数名来重写代码。
  • 消除死代码:移除未引用过的模块和未使用过的代码。
  • 修剪库:移除未使用过的库,并把其它库裁剪到只剩下你需要的那些特性。
  • 性能度量:集中精力做那些能产生可测量差异的优化。

预编译(AOT)

Angular的预编译器会在构建过程中预先编译应用的组件及其模板。

预编译过的应用启动更快,原因如下:

  • 应用组件会立即执行,不需要客户端编译过程。
  • 模板会被内嵌在组件中,因此不会再从客户端请求模板文件。
  • 我们不用再下载Angular编译器模块,它本身太大了。
  • 编译器会丢弃那些摇树优化(tree-shaking)工具能排除的代码。

Webpack(与AOT)

如果用webpack,可以考虑使用官方的 Angular预编译插件来配置Webpack。 这个插件会转译TypeScript代码、独立打包延迟加载的NgModules,而且不用对源码做任何修改就能执行AOT编译。

使用rollup消除死代码

摇树优化是一种消除死代码的技术,它会从JavaScript模块中移除导出。 如果一个库导出了一些东西,但是应用代码没有导入过它,摇树工具就会从代码中移除它。

常用的摇树优化工具是Rollup,一个带有插件的生态系统,可以完成打包、最小化和混淆。 要了解关于摇树优化和消除死代码技术的更多知识,参见这个帖子,它的作者就是rollup之父Rich Harris。

修剪库

不要指望自动移除所有死代码。

手动移除不用的库,特别是index.html中不用的脚本。 为实际使用的那些库则努力选择更小的代用库。

有些库可以构建出只带所需特性的、自定义的、带皮肤的版本。另一些库则可以让你按需导入它的特性。 RxJS就是一个很好的例子,angular会单独导入Observable的操作符(operator),而不是导入整个库。

度量性能

Chrome开发工具的网络性能页是开始学习度量性能的好地方。

WebPageTest工具是另一个不错的选择,它能帮你验证你的部署是否成功了。

Angular配置

base标签

HTML中的用于指定一个解析相对路径的基地址,如图片、脚本和样式表。 比如,指定<base href="/my/app/">时,浏览器就会把some/place/foo.jpg这样的URL解析成到my/app/some/place/foo.jpg的服务端请求。 在浏览期间,Angular路由器会使用base href作为组件、模板和模块文件的基地址。

base标签没有正确配置时,该应用会加载失败,并且浏览器的控制台会对这些缺失的文件显示404 - Not Found错误。

启用生产模式

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

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

切换到生产模式可以通过禁用开发环境下特有的检查(比如双重变更检测周期)来让应用运行得更快。

要在远程运行时启用生产模式,请把下列代码添加到main.ts中。

1
2
3
4
5
6
import { enableProdMode } from '@angular/core';
// Enable production mode unless running locally
if (!/localhost/.test(document.location.host)) {
enableProdMode();
}

惰性加载

通过只加载应用启动时必须展示的那些应用模块,可以显著缩减启动时间。

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

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

服务端配置

带路由的应用必须以index.html作为后备页面。

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

带路由的应用应该支持“深链接”。 所谓深链接就是指一个URL,它用于指定到应用内某个组件的路径。 比如,http://www.mysite.com/heroes/42就是一个到英雄详情页面的深链接,用于显示id: 42的英雄。当用户从运行中的客户端应用导航到这个URL时,Angular路由器会拦截这个URL,并且把它路由到正确的页面。

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

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

生产服务器

1
2
3
4
5
6
7
8
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
1
try_files $uri $uri/ /index.html;
  • IIS:往web.config中添加一条重写规则,类似于这里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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="/src/" />
</rule>
</rules>
</rewrite>
</system.webServer>
1
2
3
4
"rewrites": [ {
"source": "**",
"destination": "/index.html"
} ]

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

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

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

tc9011 wechat
欢迎订阅我的微信公众号
坚持原创技术分享,您的支持将鼓励我继续创作!