前言
初学Angular2后很容易被它简洁清晰的思路,方便的开发环境和开发套件所吸引。但是真正考虑生产开发的时候,总是有些不那么美好的东西。所以,在这里总结一下一些最初级、最简单粗暴的优化步骤。
启动时间优化
开启生产压缩与预编译
由于Angular2正处于发展,刚刚稳定下来的阶段,网上的一些教程,甚至包括官方的教程都有点跟不上脚步(比如官方的AOT预编译教程,貌似还有些错误)。好在开发套件angular-cli已经帮我们做好了。
ng build --prod --aot
即可。
--prod
代表生产环境编译,带有代码混淆与压缩功能。我这实际测试时候,默认编译包大小为3.5兆,生产包1.7兆。
--aot
代表预编译,会显著缩短客户端浏览器的启动到展示出真正页面的时间。
开启服务端GZIP压缩
Angular2最大的包就是vendor和main两个js文件,动辄上兆的大小在移动端仍然是不可接受的范围。但好在是文本,压缩比例一般较大,开启服务端或者反向代理的GZIP压缩功能后,可以将js文件的下载体积进一步减小。我的生产实践中原1.7兆的包进过GZIP默认配置的压缩后变为350K左右,已经完全可以接受了。
对静态文件允许客户端缓存
这个一般在SpringSecurity 或者Shiro保护的web项目中有一些坑,这些安全框架可能会在web头中加入no-cache标记,这样,每次打开页面均要从服务器再下载一遍js文件,浪费时间和流量。因此要记得在设置中关闭这些静态资源文件的no-cache标记。这样第二次打开页面,最多就是304 not modified,甚至是200(from cache)。页面显示时间可以压缩至Angular2启动的300ms。
Angular2内的优化
充分利用HTML5的Storage特性
Angular不像普通web页面,不管你是打开连接还是后退,Angular2页面均会重新走一遍页面生命周期的各个流程,重新绘制页面。
所以,若页面数据是从接口获取后,在渲染出来的话,在页面后退时候,也要经历一次空白页面到填充的过程,给用户的体验不太好。
因此优化步骤入下:
STEP1:缓存数据接口数据
这时,可以先利用Storage缓存的数据绘制页面,然后后台异步调用数据接口获取最新数据。
// 1. get from cache
pageItem = JSON.parse(localStorage.getItem('key'));
// 2. get from api
api.getData().then(res => {
pageItem = res;
// 3. save to cache
localStorage.setItem('key',key,JSON.stringify(res));
})
此时有个缺点,从api获取数据后还会触发一次页面重绘,其实如果页面数据没有变化完全可以不必重绘页面。
改进如下
// 1. get from cache
pageItem = JSON.parse(localStorage.getItem('key'));
// 2. get from api
api.getData().then(res => {
if(refreshCache(res,'key')) {
pageItem = res;
} else {
// don't redraw page
}
})
refreshCache(res:any, key:string):boolean {
if(JSON.stirngify(res)===localStorage.getItem(key) {
return false;
} else {
// update cache and return true;
localStorage.setItem(key,JSON.stringify(res));
return true;
}
}
这样,仅当最新数据与缓存不符时才会触发页面重绘,同时更新本地缓存。
利用动画
Angular2的页面跳转时虽然不像普通web需要重新载入,单总归会有几百毫秒的延时,对于体验要求苛刻的用户可能会觉得这个应用有点“卡”。因此,在页面跳转时加入转场动画可以减轻这一感觉,给人感觉这个web应用使用流畅。
Angular2添加转场动画很简单,我们以模拟手机APP常用的转场为例(页面从右往左划入)。
首先定义一个动画参数,可以单独存在一个ts文件中。
// transition-right-2-left.ts
import {trigger, state, animate, style, transition, AnimationEntryMetadata} from '@angular/core';
export const slide2left: AnimationEntryMetadata =
trigger('routerTransition',[
state('void',style({position:'absolute',width:'100%'})),
state('*',style({position:'absolute',width:'100%'})),
transition(':enter',[
style({transform:'translateX(100%)'}),
animate('200ms ease-out',style({transform:'translateX(0%)'})),
]),
transition(':leave',[
style({transform:'translateX(0%)'}),
animate('200ms ease-out',style({transform:'translateX(-100%)'})),
])
])
在需要转场的页面component.ts文件中加入如下代码
// somepage.component.ts
import {slide2left} from '../animations/transition-right-2-left.ts';
@Component({
selector:'xxx',
templateUrl:'xxx.html',
styleUrls:[],
// 添加一下参数
host:{'[@routerTransition]'},//trigger name
animations:[slide2left]// metadata name
})