about me
杨旭 - 自寒
@PP旭
淘宝网
前端工程师
多终端项目
2012年
无线淘宝累计访问用户突破3亿
无线淘宝交易额占比大淘宝
6.87%
2013年
手机淘宝使用用户数超过4亿
双十一当天手机淘宝uv数1.27亿
2013年
- 目前有12亿用户使用移动设备访问互联网
- 全球的互联网访问量中有15%来自移动设备
- 61% 的用户因在移动设备体验良好而对品牌留下更好印象
- 60% 的用户在逛商店时使用移动设备,50% 的用户在前往商店的路上使用
- 2013与2014年将有5亿部平板电脑发货
- 平板电脑用户比桌面电脑用户多愿意花50%的钱
淘宝iPhone
淘宝iPad
淘宝Android
m.taobao.com
WHY?
同一套代码
- pad版
- phone版
- 无页头版
- hybrid版
- …
目标
- 提升移动用户的购物体验
- 提升移动用户的转化率
- 移动用户购物体验保持一致
前期思考
- 做多终端的目的是什么
- 我的产品使用场景是什么样的
- 是不是需要针对不同的设备实现不一样的交互
- 是按设备类型区分还是按分辨率区分
- 是做响应式还是定制版
- 可维护性、可扩展性
- …
前后端分离
- 后端识别设备,输出不同模块,数据
- 前端负责渲染,响应同种类型设备的不同分辨率
UADetect
高效的后台UA检测组件
设备类型,操作系统,版本号,设备型号
mod.js
KISSY.add('mod', function(S){
var modules = [];
var Mod = {
//添加模块
add: function(){
...
},
//执行模块
exec: function(){
...
}
}
})
前端模块管理系统
mod1.vm
<div id="J_Mod1"></div>
<script>
KISSY.use('mod', function(S, Mod){
Mod.add({
name: 'detail/mod1',
data: {...}
})
});
</script>
独立的模块
模块之间通讯
KISSY.add("detail/mod1",function(S){
//事件名称根据自己的需要,做一个简单的约定
S.all(document).fire("message:dosth",{
//这里可以传递值
});
})
KISSY.add("detail/mod2",function(S){
S.all(document).on("message:dosth", function(ev){
//your code
});
})
全局对象的消息机制
layout.vm
...
<script>
KISSY.use('mod', function(S, Mod){
Mod.exec();
});
</script>
在页面最后统一执行
modulet
- 统一的数据请求url,通过参数决定请求的模块
- 支持json,jsonp,html片段等多种数据格式
- 支持请求合并
优点
-
前后端分离,后端只负责数据和指定输出哪些模块,页面渲染都由前端完成
-
模块资源按需加载,只需要加载指定模块的assets
-
定制性,满足不同业务需求
-
可维护性,模块之间都是独立的
缺点
- 无法combo模块脚本,模块是由后端动态输出的
- 无法提前加载样式,样式依赖模块输出
- 同一个模块在pad和phone上表现不同,怎么区分
无法combo脚本
KISSY.config(cfg);
cfg.combine (Boolean) –
是否开启自动 combo 模式,默认 false 不开启. 自动 combo 模式要求 use 前配置好依赖关系
kissy module compiler
模块依赖自动提取
--> deps.js
grunt-kmc
无法提前加载样式
KISSY.importStyle('detail/mod1, detail/mod2, detail/mod3');
提前载入依赖描述文件
阻塞地加载所有依赖的样式
KISSY.add('detail/mod1/pad', function(S, Com){
return function(cfg){
Com(cfg);
//pad function
};
}, {
require: ['./common', './pad.css']
});
KISSY.add('detail/mod1/phone', ...
KISSY.config('modules', {
'detail/mod1': {
alias: ['detail/mod1/' + deviceType]
}
});
--> alias.js
惯性滚动导致的延迟效果
取消浏览器默认滚动方式,自定义实现
transform元素里的fixed定位失效
调整transform或者html结构
touch
click事件会有300ms的延迟
一般情况建议用封装的tap
两个奇怪的情况
orientationchange
旋转设备后计算页面高度会有延迟
var bufferResize = S.buffer(resize, UA.ios ? 100 : 600, this);
$(window).on('orientationchange', bufferResize);
animate
css3动画
translate3d,translateZ
页面闪屏现象
-webkit-backface-visibility: hidden
-webkit-transform-style: preserve-3d
-webkit-perspective: 1000
gif的动画也会导致闪屏
监控
new Image()
会不会消耗很多的请求?
resize
页面上下拖动的时候会无规律触发resize事件
减少resize的监听
-webkit-appearance
-webkit-transform
-webkit-transition
-webkit-perspective
-webkit-backface-visibility
-webkit-overflow-scrolling
-webkit-box
-webkit-text-size-adjust
-webkit-tap-highlight-color
-webkit-font-smoothing
-webkit-user-select
-webkit-touch-callout
KISSY
kissy 1.4.0
scroll-view
xtemplate
image
先根据设备从cdn获取指定大小的图片
再设置 max-width: 100%
区分设备
区分分辨率
区分网速
在相似展示效果下,webp比jpeg小30%
在相同图片尺寸下,webp编码耗时是jpeg的7-8倍
解码耗时相近,但cpu使用率高50-60%
FPS
60fps - 16ms
webkitRequestAnimationFrame
以最合适的间隔来执行动画
lazyload
<textarea class="ks-lazyload hidden">
<script>
KISSY.use("detail/reviews/", function(S,Reviews) {
Reviews();
});
</script>
</textarea>
模块的延迟加载
图片的延迟加载
cache
localStorage
manifest
spdy
- 多路复用,请求优化
- 支持服务器推送
- 压缩HTTP头
prefetch
-
<link rel="dns-prefetch">
-
<link rel="prefetch">
-
<link rel="prerender">