第1页
极致的 Hybrid
——从阿⾥里旅⾏行「去啊」的架构演变看 Web 与 Native 的融合
@拔⾚赤 @坦丁
QCon 2015
第2页
阿⾥里旅⾏行 · 去啊 App 是⼀一款⼩小⽽而美的旅⾏行类客户端
第3页
Native & Web 强混
H5 和 Native ⻚页⾯面数量⽐比例
H5 52%
Native 48%
Native
H5
第4页
Native & Web 强混
7.32 66
IOS(s)
Android(s)
0.5 0.8 0.2 0.3 0.240.4 0.2 0.4 0.010.01 0.1 0.2 0.1 0.2 0.3 0.4
0 精选特惠 客栈 团购 度假 签证 门票 周末游 ⽤用⻋车 国际机票
第5页
Native & Web 强混
IOS(s)
7.32
⼀一个在线⻚页⾯面 优化到死只能这样了
Android(s)
0.5 0.8 0.2 0.3 0.240.4 0.2 0.4 0.010.01 0.1 0.2 0.1 0.2 0.3 0.4
0 精选特惠 客栈 团购 度假 签证 门票 周末游 ⽤用⻋车 国际机票
第6页
“So,我们把 HTML/CSS/JS 预装到 App 中!”
第7页
Thank you. Questions ?
第8页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 虚拟域的实现以及在线离线⻚页⾯面怎么切换?
埋点和数据统计怎么做? H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第9页
原始诉求
• ⽤用户:“快、快、快” —— 界⾯面快点出来 • PD:“快、快、快” —— 功能快点上线 • ⽼老板:“快、快、快” —— 快点回滚问题代码
第10页
Hybrid
产品/设计
⽆无线技术
Web 的 Native 化 vs Native 的 Web 化
第11页
Why Not Native?
1. App 发版周期远远跟不上产品节奏!(Native 的硬伤) 2. 灵活性差,模块化不起来,很难做千⼈人千⾯面(也是Native的硬伤) 3. 外投引流只能靠H5(还是Native的硬伤) 4. App 之间的互联规范必须通过 H5 的桥接(更是Native的硬伤)
第12页
Why not Web?
1. 弱⺴⽹网体验极差(天朝的⺴⽹网络你懂得) 2. Wap 上的交易转化率奇低(本质上是体验差)
第13页
Hybrid
• 融合 · 灵活的 H5 vs 可靠的 Native
桥、H5 容器
• 极速 · H5 的秒出
离线包体系
• 闭环 · 交互/交易流程的多端闭环
购票→Push/短信提醒→⾏行程卡⽚片→⾃自动值机→专⻋车服务→累积淘⾥里程...
• 解耦 · 端与端、M 和 V
Router 链接多端、公⽤用代码与业务代码、数据与视图、⽆无序的需求与有序的研发,快速迭代…
第14页
摆脱思维定势
• HTML 4 到 HTML 5
• 基于 <a> 标签的资源互联⽆无法⾃自然延伸到移动终端领域 • 专注打造 BOM 的超集:Hybrid Bridge
• HTTP 1.1 到 HTTP 2.0(升级spdy?)
• 应⽤用层协议+短链接:是否继续适⽤用于移动互联⺴⽹网?
• 从 Browser 到 App
• App 之间天然存在技术壁垒,阻碍信息互通 • URL 不⻅见了,移动Web⾥里⽤用什么来描述“资源”
第15页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 虚拟域的实现以及在线离线⻚页⾯面怎么切换?
埋点和数据统计怎么做? H5 与 Native 之间的互调如何实现? WebView 的 Crush 的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第16页
App
Hybrid Bridge
Webview H5
H5 离线包缓存池 Diff Controller BundleLoader
project-pkg.zip @ CDN
Config.json
or QA
dist grunt offline Grunt-flexcombo
Gitlab:proj/build_offline/
TMS
Combined HTML
Combined JS
Combined css
Zip 包 Local img
Grunt-comboHTML Build offLine)
Gitlab:proj/src/
Juicer Mock
HTML
Pages/Mods/Widgets JavaScript Files
less/scss
ICON IMG
IMGs
src
KISSY-Seed.js(v1.5.0) / KISSY-mini.js(v .x)
MPI
KISSY Gallery
航旅 H5 离线环境体系
第17页
H5 适配多端(的容器)
App
Hybrid Bridge
Webview H5
H5 离线包缓存池 Diff Controller BundleLoader
project-pkg.zip @ CDN
Config.json
or QA
dist grunt offline Grunt-flexcombo
Gitlab:proj/build_offline/
TMS
Combined HTML
Combined JS
Combined css
Zip 包 Local img
Grunt-comboHTML Build offLine)
Gitlab:proj/src/
Juicer Mock
HTML
Pages/Mods/Widgets JavaScript Files
less/scss
ICON IMG
IMGs
src
KISSY-Seed.js(v1.5.0) / KISSY-mini.js(v .x)
MPI
KISSY Gallery
航旅 H5 离线环境体系
第18页
App 离线包容器边界
H5 容器
虚拟域代理
Virtual Domain
cache_info.json
读取静态(资源)⽂文件
⼿手机硬盘
公⺴⽹网
Native 端取资源的提速:去啊 App 加载离线资源逻辑
第19页
Safari:在线⻚页⾯面
去啊App:离线⻚页⾯面
http://h5.m.taobao.com/trip/tuan/list/index.html
虚拟域:同样 URL 在容器中打开会⾛走到离线⻚页⾯面
第20页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 在线离线⻚页⾯面怎么切换? 埋点和数据统计怎么做?
H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第21页
动态区域(TMS)中的 M 和 V 的解耦
第22页
内嵌模块 运营同学随时更新
异步第三⽅方区块
动态区域(TMS)中的 M 和 V 的解耦
第23页
handle_tms_fragment(function() {/* <section class="tms"> <style> #banner { width:100%; } </style> <div> <img src="http://gtms02.alicdn.com/tps/XX-640-200.png" > </div> </section>
*/}, 1);
通过注释来异步加载⼀一段 HTML 代码
第24页
<!-- #include file=“extra.php" -->
第25页
<!-- #include file=“extra.php" -->
替换成抓取函数
<script id=“tms_fragment_1"> get_tms_fragment("http://proxy.php?src=extra.php", "gbk", “1”); </script>
第26页
<!-- #include file=“extra.php" -->
<script id=“tms_fragment_1"> get_tms_fragment("http://proxy.php?src=extra.php", "gbk", “1”); </script>
异步抓取 TMS 正⽂文
handle_tms_fragment(function() { /*<div>TMS内容</div>*/
}, 1);
第27页
<!-- #include file=“extra.php" -->
<script id=“tms_fragment_1"> get_tms_fragment("http://proxy.php?src=extra.php", "gbk", “1”); </script>
handle_tms_fragment(function() { /*<div>TMS内容</div>*/
}, 1);
将正⽂文塞⼊入⻚页⾯面
function handle_tms_fragment(fn, id) { var content = getFromComment(fn.toString()); //<div>TMS内容</div> $('tms_fragment_' + id).replaceWith(content);
}
第28页
src clean
qa-seed-tmsparser.js
qa-seed.js
grunt build
less sass cssmin
kmb
uglify
replace
combohtml
domman
replace
cacheinfo
format zip
dist
第29页
src clean
qa-seed-tmsparser.js
qa-seed.js
grunt build
less sass cssmin
kmb
uglify
replace
combohtml
domman
replace
cacheinfo
format zip
dist Clam 构建⼯工具对这些逻辑的封装
第30页
src clean
qa-seed-tmsparser.js
qa-seed.js
grunt build
less sass cssmin
kmb
uglify
replace
combohtml
domman
replace
cacheinfo
format zip
dist Cacheinfo.json 本地资源映射表
第31页
去啊前端基础⼯工具
Clam:http://clam.alitrip.net
第32页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 在线离线⻚页⾯面怎么切换? 埋点和数据统计怎么做?
H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第33页
H5 离线包 @version
h5-taxi
build & push
gitlab
WD
h5-visa h5-car
总控配置&离线资源包
⽤用户⼿手机设备
QA
@version pull pull
User
update.zip
⼿手机终端
offline-config H5包配置⽂文件
@ gitlab
grip_gateway.php
离线资源总配置⽂文件
@ TMS
去啊 H5 离线包发布流程
第34页
H5 离线包
总控配置&离线资源包
@version
分散
资源h5-taxi
build & push
h5-visa
源码gitlab
WD
h5-car
开发/预发
开关
offline-config H5包配置⽂文件
@ gitlab
pull
整合/增量 QA
资源@version
pull
update.zip
线上推包
开关
grip_gateway.php 离线资源总配置⽂文件
@ TMS
去啊 H5 离线包发布流程
⽤用户⼿手机设备
端User
⼿手机终端
第35页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 在线离线⻚页⾯面怎么切换? 埋点和数据统计怎么做?
H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第36页
Native
H5
H5
Native
Native
构建 App 内的 Hybrid PageFlow 的传参规范
第37页
Native
H5
唤起
Native
Native
构建 App 之间的互调和传参规范
第38页
1. ⽇日志表的双份存储 2. H5 Page 的别名
第39页
H5 Page 和 Native Page 在命名上的差异
1. ⽇日志表的双份存储 2. H5 Page 的别名
第40页
H5 Page 在容器中的别名通过<meta>标签来标⽰示
第41页
H5 H5
Native H5
Native
Native
H5
Native
Native
Native
构建 App 内的 Hybrid PageFlow 的传参规范
第42页
SPM + ttid
H5
SPM + ttid
H5
Native
SPM + ttid
H5
Native
Native
SPM + ttid
H5
Native
Native
Native
SPM 透传 + ttid 透传
第43页
挖取 H5 和 Native Page 混⽤用场景的漏⽃斗
第44页
新⽤用户转化交易、交互闭环
第45页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 在线离线⻚页⾯面怎么切换? 埋点和数据统计怎么做?
H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第46页
Bridge.js
第47页
去啊App
数据采集
Router
R
阿⾥里系Apps
H5/PC
Router: 导流/引导成交/多端Push/唤起和互调
第48页
航旅 App 桥接外部调⽤用的路由
第49页
UI 开发的灵活性 推包频度
加载/渲染性能 多端兼容
开发者门槛
更新时效
代码回滚效率
Page 资源管理 灵活性 Crush 率
Web ⾼高 ⾼高 低 ⾼高 低 ⾼高 ⾼高 ⾼高 低
Native 低 低 ⾼高 低 ⾼高 低 低 低 低
ReactNative 中 ⾼高 ⾼高 中 中 中 低 低 低
Hybrid ⾼高 ⾼高
⽐比较⾼高 ⾼高 低 中 ⾼高 ⾼高 ⾼高
第50页
重构容器
扩展容器
UI 开发的灵活性 推包频度
加载/渲染性能 多端兼容
开发者门槛
更新时效
代码回滚效率
Page 资源管理 灵活性 Crush 率
Web ⾼高 ⾼高 低 ⾼高 低 ⾼高 ⾼高 ⾼高 低
Native 低 低 ⾼高 低 ⾼高 低 低 低 低
ReactNative 中 ⾼高 ⾼高 中 中 中 低 低 低
Hybrid ⾼高 ⾼高
⽐比较⾼高 ⾼高 低 中 ⾼高 ⾼高 ⾼高
第51页
So
1. 我们重定义了⽆无线领域中 FrontEnd 的⾓角⾊色
向上多端兼容、向下重构 Web 容器
2. 我们重构了 Hybrid 的整个基础设施
构建⼯工具、资源发布系统、资源离线、数据统计规范
3. 打破 H5 和 Native 之间的墙
90% 的场景下,H5 和 Native 互为备份,取⻓长补短
第52页
H5 资源离线化就万事⼤大吉了?
第53页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 虚拟域的实现以及在线离线⻚页⾯面怎么切换?
埋点和数据统计怎么做? H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第54页
UI 开发的灵活性 推包频度
加载/渲染性能 多端兼容
开发者门槛
更新时效
代码回滚效率
Page 资源管理 灵活性 Crush 率
Web ⾼高 ⾼高 低 ⾼高 低 ⾼高 ⾼高 ⾼高 低
Native 低 低 ⾼高 低 ⾼高 低 低 低 低
ReactNative 中 ⾼高 ⾼高 中 中 中 低 低 低
Hybrid ⾼高 ⾼高
⽐比较⾼高 ⾼高 低 中 ⾼高 ⾼高 ⾼高
第55页
Web
Native ReactNative Hybrid
UI 开发的灵活性
⾼高
低
中
⾼高
基于推包J频S度VM 重构⾼高容器:低HTML/C⾼高SS 本地⾼渲高 染
加载/渲染性能
低
⾼高
⾼高 ⽐比较⾼高
多端兼容
⾼高
低
中
⾼高
基于开发V者ir门槛tualDN低S 的路由⾼高:Nativ中e 中的 “低URL”
更新时效
⾼高
低
中
中
代码回滚效率
⾼高
低
低
⾼高
Page 资源管理 灵活性
⾼高
低
低
⾼高
Crush 率 低 低 低 ⾼高
第56页
Web
Native
对内存的⾼高效管理
ReactNative Hybrid
UI 开发的灵活性
⾼高
低
中
⾼高
基于推包J频S度VM 重构⾼高容器:低HTML/C⾼高SS 本地⾼渲高 染
加载/渲染性能
低
⾼高
⾼高 ⽐比较⾼高
多端兼容
⾼高
低
中
⾼高
基于开发V者ir门槛tualDN低S 的路由⾼高:Nativ中e 中的 “低URL”
更新时效
⾼高
低
中
中
代码回滚效率
⾼高
低
低
⾼高
Page 资源管理 灵活性
⾼高
低
低 对资源的⾼高⾼高效管理
Crush 率 低 低 低 ⾼高
第57页
0 JavaScriptCore 0x3087852a JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*) + 30 1 JavaScriptCore 0x3086f5b7 llint_slow_path_call + 123 2 JavaScriptCore 0x30873ef9 llint_op_call + 201 3 JavaScriptCore 0x30858b63 JSC::evaluate(JSC::ExecState*, JSC::SourceCode const&, JSC::JSValue, JSC::JSValue*) + 427 4 WebCore 0x37a480f7 WebCore::ScriptController::evaluateInWorld(WebCore::ScriptSourceCode const&, WebCore::DOMWrapperWorld*) + 255 5 WebCore 0x37a47fb7 WebCore::ScriptController::evaluate(WebCore::ScriptSourceCode const&) + 27 6 WebCore 0x37a47f2d WebCore::ScriptElement::executeScript(WebCore::ScriptSourceCode const&) + 325 7 WebCore 0x37afde33 WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent(WebCore::PendingScript&) + 159 8 WebCore 0x37af709d WebCore::HTMLScriptRunner::executeParsingBlockingScripts() + 245 9 WebCore 0x37a532ff WebCore::HTMLDocumentParser::executeScriptsWaitingForStylesheets() + 27 10 WebCore 0x37a50585 WebCore::Document::didRemoveAllPendingStylesheet() + 41 11 WebCore 0x37b72005 WebCore::HTMLLinkElement::sheetLoaded() + 77 12 WebCore 0x37a5043b WebCore::StyleSheetContents::checkLoaded() + 99 13 WebCore 0x37b71949 WebCore::HTMLLinkElement::setCSSStyleSheet(WTF::String const&, WebCore::KURL const&, WTF::String const&, WebCore::CachedCSSStyleSheet const*) + 857 14 WebCore 0x37afeeb5 WebCore::CachedCSSStyleSheet::checkNotify() + 257 15 WebCore 0x37b71407 WebCore::CachedCSSStyleSheet::finishLoading(WebCore::ResourceBuffer*) + 219 16 WebCore 0x37af9d71 WebCore::SubresourceLoader::didFinishLoading(double) + 109 17 WebCore 0x37af9cd5 WebCore::didFinishLoading(_CFURLConnection*, void const*) + 125 18 CFNetwork 0x2f52d0e7 ___ZN27URLConnectionClient_Classic26_delegate_didFinishLoadingEU13block_pointerFvvE_block_invoke + 75 19 CFNetwork 0x2f52bcf7 ___ZN27URLConnectionClient_Classic18_withDelegateAsyncEPKcU13block_pointerFvP16_CFURLConnectionPK33CFURLConnectionClientCurrent_V MaxE_block_invoke_2 + 55 20 CoreFoundation 0x2f7fa8f1 CFArrayApplyFunction + 37 21 CFNetwork 0x2f4c36bb RunloopBlockContext::perform() + 183 22 CFNetwork 0x2f4c3579 MultiplexerSource::perform() + 221 23 CFNetwork 0x2f4c340d MultiplexerSource::_perform(void*) + 49 24 CoreFoundation 0x2f89220b __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 25 CoreFoundation 0x2f8916db __CFRunLoopDoSources0 + 207 26 CoreFoundation 0x2f88fecf __CFRunLoopRun + 623 27 CoreFoundation 0x2f7faebf CFRunLoopRunSpecific + 523 28 CoreFoundation 0x2f7faca3 CFRunLoopRunInMode + 107 29 WebCore 0x37a921ab RunWebThread(void*) + 419 30 libsystem_pthread.dylib 0x3a6a3919 _pthread_body + 141 31 libsystem_pthread.dylib 0x3a6a388b _pthread_start + 103 32 libsystem_pthread.dylib 0x3a6a1aa4 thread_start + 8
WebView Crash 率为什么这么⾼高!
第58页
0 WebCore 0x00000001928a860c WebCore::CachedResource::unregisterHandle(WebCore::CachedResourceHandleBase*) + 144 1 WebCore 0x00000001928a856c WebCore::CachedResourceHandleBase::~CachedResourceHandleBase() + 32 2 WebCore 0x0000000192a0d6c4 WebCore::MemoryCache::pruneDeadResourcesToSize(unsigned int) + 352 3 WebCore 0x0000000192922de0 WebCore::MemoryCache::prune() + 128 4 WebCore 0x0000000192959aec WebCore::DocumentLoader::detachFromFrame() + 400 5 WebKitLegacy 0x00000001937c2b08 WebDocumentLoaderMac::detachFromFrame() + 20 6 WebCore 0x0000000192d5b914 WebCore::FrameLoader::detachFromParent() + 224 7 WebKitLegacy 0x0000000193829430 __29-[WebView(WebPrivate) _close]_block_invoke + 372 8 WebCore 0x00000001935f78b0 HandleRunSource(void*) + 368 9 CoreFoundation 0x0000000183f94240 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 10 CoreFoundation 0x0000000183f9359c __CFRunLoopDoSources0 + 448 11 CoreFoundation 0x0000000183f91594 __CFRunLoopRun + 712 12 CoreFoundation 0x0000000183ebd2d4 CFRunLoopRunSpecific + 396 13 WebCore 0x0000000192920894 RunWebThread(void*) + 468 14 libsystem_pthread.dylib 0x0000000195fe3dc8 _pthread_body + 164 15 libsystem_pthread.dylib 0x0000000195fe3d24 _pthread_body + 0 16 libsystem_pthread.dylib 0x0000000195fe0ef8 thread_start + 4
第59页
内存啊,内存!
优化前
优化后
JS 执⾏行频繁对内存的影响!
第60页
内存啊,内存!
优化前
优化后
图⽚片质量对内存的影响!
第61页
低质量图⽚片
⾼高质量图⽚片
第62页
低质量图⽚片
⾼高质量图⽚片 ⽆无差别
第63页
运⾏行时 Hybrid 三个阶段
第⼀一阶段:App 内嵌 WebView ⻚页⾯面
第64页
运⾏行时 Hybrid 三个阶段
第⼆二阶段:WebView 容器 + JSBridge
第65页
运⾏行时 Hybrid 三个阶段
第⼆二阶段:WebView 容器 + JSBridge
第66页
运⾏行时 Hybrid 三个阶段
第三阶段:WebView 容器 + JSVM
第67页
WebView 容器 + JSVM
navigation NA H5
第68页
WebView 容器 + JSVM
JSVM
NA H5 H5
第69页
HTML + CSS 本地渲染
Native 端直接解析 CSS
+
第70页
HTML + CSS 本地渲染
parser+layout
第71页
HTML + CSS 本地渲染
发布服务器
版本特征信息 布局信息
parser+layout
推送服务器
第72页
HTML + CSS 本地渲染
1. 可动态更新的⻚页⾯面+布局 2. 更少,更可控的内存 3. H5 开发受到⼀一定局限性
第73页
Questions?
JS/CSS/IMG 资源怎么动态更新? 什么时候更新资源?
活动⻚页⾯面⾥里的动态数据怎么和HTML解耦? 虚拟域的实现以及在线离线⻚页⾯面怎么切换?
埋点和数据统计怎么做? H5 与 Native 之间的互调如何实现? WebView 的 Crush 率的难题怎么解? Native 中 Page 资源的定位怎么规范?
HTML 渲染如何加速? …
第74页
Native 中 Page 资源定位规范
1. ⽤用 URL 规范给所有 Page 设定唯⼀一标⽰示
Page PageName
http://xxx.xxx.xxx/xxx/xxx.html
第75页
Native 中 Page 资源定位规范
1. ⽤用 URL 规范给所有 Page 设定唯⼀一标⽰示 2. 虚拟域:设置本地虚拟 DNS
NA Native ⻚页⾯面
URL
VDNS
LH 离线 H5 ⻚页⾯面
RH 在线 H5 ⻚页⾯面
第76页
Native 中 Page 资源定位规范
1. ⽤用 URL 规范给所有 Page 设定唯⼀一标⽰示 2. 虚拟域:设置本地虚拟 DNS 3. 通过配置服务器和推送服务器来更新虚拟 DNS
dns config
第77页
Native 中 Page 资源定位规范
router navi
A B C D… Page Flow
第78页
Native 中 Page 资源定位规范
vDns router
navi
A B C D…
Page Flow
第79页
Native 中 Page 资源定位规范
vDns router
navi
A B C D…
Page Flow
第80页
Native 中 Page 资源定位规范
vDns router
navi
A
B C D…
Page Flow
第81页
Native 中 Page 资源定位规范
1. 更加灵活的运营 2. ABTest 3. HotPatch
第82页
好的设计驱动技术创新 好的技术给设计⽆无限想象
第83页
永不⽌止步的前端
1. ⺴⽹网⻚页重构、JavaScript 类库、初级性能优化
1. 2006~2010:w3c、YUI、jQuery、prototype、前端代码仓库… 2. 2009~2012:在 HTTP 和 DOM 渲染层⾯面重新组织资源的加载
2. 团队协作、组件化
1. 2010~2013:⻚页⾯面搭建⼯工具、活动⻚页⾯面模板、店铺装修 2. 2012~2014:commonJS、requireJS、SeaJS、AMD、KMD
3. 效率⼯工具、前后端分离
1. 2013~2014:NodeJS、Restful API、理清 BackEnd 和 FrontEnd 的职能边界
4. 移动终端、Hybrid
1. 2015:HTML5、CSS3、H5 和 Native 桥接、资源离线化、NativeScript、ReactNative 2. 2015:JSVM、Virtual DNS
第84页
原始诉求
• ⽤用户:“快、快、快” —— 界⾯面快点出来 • PD:“快、快、快” —— 功能快点上线 • ⽼老板:“快、快、快” —— 快点回滚问题代码
第85页
原始诉求
• ⽤用户:“快、快、快” —— 界⾯面快点出来 • PD:“快、快、快” —— 功能快点上线 • ⽼老板:“快、快、快” —— 快点回滚问题代码
第86页
“⼩小” ⽽而美的去啊 App
第87页
F2E 简历发送⾄至 bachi@taobao.com
第88页
Thank You~