single page webapp architecture
TRANSCRIPT
Single-Page-WebApp Architecture
程墨 Morgan Cheng@morgancheng
Traditional Web
Web Page
Web PagePage HTML
Server Browser
Navigate
Page HTML
Single Page WebApp
Web Page
XHR Response
Server Browser
Navigate
XHR Response
Navigate
Page HTML
Not Just AJAX
It Should Work as Web
Bookmark-able
Navigable
Search-Engine-Friendly, if necessary
VS
Why to Single-Page?
Squeeze Bits for Better Experience
When to Single-Page?
Frequently Navigated Page
Partial Difference Among Pages
Performance Critical
How to Single-Page?
Now we totally depend on JavaScript
"The secret to building large apps is never build large apps. Break your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application"
-Justin Meyer, author JavaScriptMVC
Singe Page App
Client Side Routing Client Side Rendering
=
+
First, Client-Side Routing
Multiple Framework Choices
https://github.com/addyosmani/todomvc
3.4.0 App F/W
Ryan Grove
Why YUI3.4 app framework doesn't allow to use hash style URL for all browsers?
It was very important to make doing the right thing easy and doing the wrong thing hard.
Server Just Render HTML Skeleton
Define Routesvar controller = new Y.Controller({
routes: [
{path: “/”,callback: onHomePage
},{
path: “/user/:guid”,callback: onUserPage
}
]});
onHomePage is invoked when route “/” is triggered
Dispatch on DOM Ready
controller.dispatch();
Trigger route according to current page URL
Save on Navigation
Y.delegate('click', onNaviLinkClick, 'body', '.navi-link', this);
function onNaviLinkClick() { … var newPath = currTarget.getAttribute('href');
if (controller.getPath() != newPath) {controller.save(newPagePath);
}} Trigger route according to
newPagePath
Routing Module
Page A Page B Page C
Page Load&Page Navigation
Second, Client-Side Rendering
Routing Module
Page A Page B Page C
Page Load&Page Navigation
Widget X Widget Y Widget Z
Widget or View-Model
Decouple Modules with Events
Routing Module
Page A Page B Page C
Page Load&Page Navigation
Widget X
Event System
Widget Y Widget Z
Don’t Repeat Yourself
Logic-less Template: Mustache
http://mustache.github.com/
<div id="post_{{pid}}”{{#post}}data-original-pid="{{pid}}" {{/post}}
>
<div id="post_123”data-original-pid=”456"
>
{pid: ‘123’, post: {
pid: ‘456’}
}
Ask Again :Why to Single-Page?
It should be Fast
近身 == Download It Fast发力 == Run It Fast
Download It Fast
Non-Blocking JavaScript
function loadJS(path) { var script = document.createElement("script"); script.type = "text/javascript"; script.src = path; document.getElementsByTagName("head")[0].appendChild(script);}
Insert into <head>
Flush It!
…</head><?phpob_flush();flush();?><body>
Flush for browser incremental rendering
WTF?
Position Inline JavaScript
http://www.stevesouders.com/blog/2009/05/06/positioning-inline-scripts/
function loadJS(path) { var script = document.createElement("script"); script.type = "text/javascript"; script.src = path; var first = document.getElementsByTagName(‘script’)[0]; first.parentNode.insertBefore(script, first);}
Insert before first <script>
Position Inline JavaScript Before External Style Link
Caching:Better Than Downloading
Widget
Data Source
CacheAJAX Inline Script
Run It Fast
JavaScript Execution is Not Free
Client-side Rendering Depends on CPU & JS Engine
Mustache Performance Suffers From Nested Data
{ pid: ‘123’, entities: { images:
[{image_medium: … ,image_small: … ,image_big: … ,}]
}}
Performance is Not Good
{ pid: ‘123’, entities_images_0_image_medium: …, entities_images_0_image_medium: …, entities_images_0_image_medium: …,}
Twice faster!
Chunked Computation
Web Worker
How to Render First Page?
Twitter Approach
• The first page response is just HTML skeleton
• Web is a client of its Open API
• The page is initialized with multiple AJAX response
Facebook Approach
• The first page response is HTML Skeleton with tailing inline JavaScript
• Init data is flushed in tailing JavaScript block– It is called BigPipe
• The sequence of module rendering depends
Google+ Approach
• The first page response is complete HTML
Which is Better?
A. Twitter Approach
B. Facebook Approach
C. Google+ Approach
Take-Away
• Leverage Framework
• Make decision according to app requirement
• Watch the Performance
Thank You!