Ajax to the Moon
Upcoming SlideShare
Loading in...5
×
 

Ajax to the Moon

on

  • 5,564 views

CommunityOne presentation about offline Ajax, Ajax push, and Ajax performance issues.

CommunityOne presentation about offline Ajax, Ajax push, and Ajax performance issues.

Statistics

Views

Total Views
5,564
Views on SlideShare
5,556
Embed Views
8

Actions

Likes
0
Downloads
183
Comments
0

4 Embeds 8

http://blogs.nitobi.com 3
http://www.linkedin.com 3
http://www.slideshare.net 1
https://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Remove technical session reference…are we sure we have to use the J1 template?

Ajax to the Moon Ajax to the Moon Presentation Transcript

  • Ajax to the Moon Dave Johnson CTO and Co-founder Nitobi www.nitobi.com
  • Agenda
    • Who I Am
    • Offline Ajax
    • Pushing Ajax
    • Ajax Performance
    • Summary
  • Who I Am
    • Nitobi Enterprise Ajax Podcast
    • Enterprise Ajax book (Prentice Hall)
    • blogs.nitobi.com/dave
  • What Do I Do?
    • Nitobi co-founder
    • Located in Vancouver, Canada
    • Ajax user-interface components for the enterprise
  •  
  • Clients
  • Agenda
    • Who I Am
    • Offline Ajax
    • Pushing Ajax
    • Ajax Performance
    • Summary
  • Offline Ajax http://www.flickr.com/photos/natearcher/378519540/
  • Know your users
  • Why Offline
    • Hard at work
    • Get on a plane
    • Keep on working
  • http://www.flickr.com/photos/plakboek/339017053/
  • Why Offline
    • Hard at work
    • Get on a plane
    • Keep on working
    • Get Internet connection and sync data
    • More common than you may think!
  •  
  •  
  • But Seriously
    • Internet connections do not grow on trees
    • Try going to Sun HQ and getting on their network!
  • How Does it Work?
    • Work offline
    • Store data locally when browser is closed
    • Send data back to server when connected
  •  
  • Storage
    • Cookies
    • Firefox / Internet Explorer only
    • Flash
    • Install software
  • Cookies
    • 4Kb of storage per domain
    • Easily deleted – probably suspected as Spyware
  • Firefox 2.0 Offline Storage
    • Cookies on steroids
    • Data not available across sessions
    • 5Mb of storage by default
    • A bit buggy at the moment but Firefox 3 should have global storage across sessions
    • <html>
    • <head>
    • <script type=”text/javascript”>
    • function saveSession(myparam,myvalue) {
    • // will save the attribute myparam with value myvalue
    • sessionStorage[myparam] = myvalue;
    • }
    • function loadSession(myparam) {
    • // will retrieve myparam from sessionStorage
    • var myresult = sessionStorage[myparam];
    • return myresult;
    • }
    • </script>
    • </head>
    • <body>
    • <form id=&quot;myform&quot; name=&quot;myform&quot;>
    • <input type=&quot;text&quot; id=&quot;myvalue&quot; name=&quot;myvalue&quot;>
    • <input type=&quot;button&quot; value=&quot;Save&quot;
    • onclick=&quot;saveSession('myattribute',myform.myvalue.value)&quot;>
    • <input type=&quot;button&quot; value=&quot;Load&quot;
    • onclick=&quot;alert(loadSession('myattribute'))&quot;>
    • </form>
    • </body>
    • </html>
  • Internet Explorer userData Behavior
    • Access data across sessions
    • 128Kb limit for Internet (512Kb for Intranet)
    • Relies on Internet Explorer Behaviors
    • What about HTML Applications?
    • <html>
    • <head>
    • <script type=”text/javascript”>
    • function save(myparam,myvalue) {
    • $(“storageInput”).setAttribute(myparam, myvalue).save(&quot;mydata&quot;);
    • }
    • function load(myparam) {
    • return $(“storageInput”).load(&quot;mydata&quot;).getAttribute(myparam);
    • }
    • </script>
    • <style>
    • .storage {
    • behavior:url(#default#userData);
    • display:none;
    • }
    • </style>
    • </head>
    • <body>
    • <form id=&quot;myform&quot; name=&quot;myform&quot;>
    • <input type=&quot;text&quot; id=&quot;myvalue&quot; name=&quot;myvalue&quot;>
    • <input type=&quot;button&quot; value=&quot;Save&quot; onclick=&quot;save('myattr',myform.myvalue.value)&quot;>
    • <input type=&quot;button&quot; value=&quot;Load&quot; onclick=&quot;alert(load('myattribute'))&quot;>
    • <div id=”storageInput” class=”storage”></div>
    • </form>
    • </body>
    • </html>
  • Flash SharedObject Storage
    • Access data across sessions
    • User definable storage limit (default of 100Kb)
    • Back to Flash 6 (98% adoption)
  • Flash Movie
    • import flash.external.ExternalInterface;
    • function saveAttribute(datastore, paramname, paramvalue) {
    • mySharedObject = SharedObject.getLocal(datastore);
    • mySharedObject.data[paramname] = paramvalue;
    • mySharedObject.flush();
    • }
    • function loadAttribute(datastore,paramname) {
    • return SharedObject.getLocal(datastore).data[paramname];
    • }
    • ExternalInterface.addCallback(&quot; saveAttribute &quot;, this, saveAttribute);
    • ExternalInterface.addCallback(&quot; loadAttribute &quot;, this, loadAttribute);
    • <html>
    • <head>
    • <script>
    • function thisMovie(movieName) {
    • if (navigator.appName.indexOf(&quot;Microsoft&quot;) != -1)
    • return window[movieName];
    • else
    • return document[movieName];
    • }
    • function saveData(store, param, pvalue) {
    • thisMovie(‘myStorage’).saveAttribute(store,param,pvalue);
    • }
    • function loadData(store, param) {
    • return(thisMovie(‘myStorage’).loadAttribute(store,param));
    • }
    • </script>
    • </head>
    • <body>
    • <object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000“
    • codebase=&quot;…&quot;
    • width=&quot;1&quot; height=&quot;1&quot; id=&quot;myStorage&quot; align=&quot;middle&quot;>
    • <param name=&quot;movie&quot; value=&quot;localstore.swf&quot; />
    • <param nam=&quot;allowScriptAccess&quot; value=&quot;always&quot;>
    • <embed src=&quot;localstore.swf&quot; allowScriptAccess=&quot;always&quot; width=&quot;1&quot; height=&quot;1&quot; name=&quot;myStorage“
    • type=&quot;application/x-shockwave-flash&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot; />
    • </object>
    • </body>
    • </html>
    • <html>
    • <head>
    • <script>
    • function thisMovie(movieName) {
    • if (navigator.appName.indexOf(&quot;Microsoft&quot;) != -1)
    • return window[movieName];
    • else
    • return document[movieName];
    • }
    • function saveData(store, param, pvalue) {
    • thisMovie(‘myStorage’).saveAttribute(store,param,pvalue);
    • }
    • function loadData(store, param) {
    • return(thisMovie(‘myStorage’).loadAttribute(store,param));
    • }
    • </script>
    • </head>
    • <body>
    • <object classid=&quot;clsid:d27cdb6e-ae6d-11cf-96b8-444553540000“
    • codebase=&quot;…&quot;
    • width=&quot;1&quot; height=&quot;1&quot; id=&quot;myStorage&quot; align=&quot;middle&quot;>
    • <param name=&quot;movie&quot; value=&quot;localstore.swf&quot; />
    • <param nam=&quot;allowScriptAccess&quot; value=&quot;always&quot;>
    • <embed src=&quot;localstore.swf&quot; allowScriptAccess=&quot;always&quot; width=&quot;1&quot; height=&quot;1&quot; name=&quot;myStorage“
    • type=&quot;application/x-shockwave-flash&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot; />
    • </object>
    • </body>
    • </html>
  • Apollo
    • Adobe’s new runtime – currently Alpha
    • Offline capable, runs from your computer
    • A lot more than just offline!
      • Flex + WebKit (i.e. Safari) in one
  • Web Proxy
    • Proxy auto-config – browser proxy settings
    • JavaScript file with FindProxyForURL
    • Forward requests to a local proxy for interested domains
    • Used by the Dojo Toolkit
  • Salesforce.com Local Proxy
  • Whole Hog
    • Web server
    • Database
    • Run locally
    • Zimbra uses this approach
  • Issues
    • Performance
    • Concurrency
      • Your own data or shared?
    • End user requirements
      • Are they a captive user?
    • Penetration
  • Proxy Whole Hog Flash Browser Specific Cookies Concurrency Performance End user reqs / Penetration
  • Proxy Whole Hog Flash Browser Specific Cookies Concurrency Performance End user reqs / Penetration
  • Proxy Whole Hog Flash Browser Specific Cookies Concurrency Performance End user reqs / Penetration
  • Proxy Whole Hog Flash Browser Specific Cookies Concurrency Performance End user reqs / Penetration
  • Proxy Whole Hog Flash Browser Specific Cookies Concurrency Performance End user reqs / Penetration
  • Agenda
    • Who I Am
    • Offline Ajax
    • Pushing Ajax
    • Ajax Performance
    • Summary
  • Pushing Ajax http://www.flickr.com/photos/vidiot/69075298/
  • Watch out for your thumb
  • Why Push?
    • Keep client up to date
    • Collaboration
      • Documents
      • Communication
    • Time sensitive data
  • How Does it Work? Big scary Internet Innocent MySpace user MySpace Evil Empire TM
  • Polling
    • Means to the same end
    • Easy to build
    • Request update from server every N seconds
    • Support thousands of concurrent users?
    • users / pollTime = requests per second
  • http://www.flickr.com/photos/roadhunter/68017710/
  • How Does it Work? Big scary Internet Innocent MySpace user MySpace Evil Empire TM thumb twiddling …
  • Push
    • Keep connection to server open
    • Server writes to stream when ready
    • Support thousands of concurrent users?
    • numConnections ≡ numServerThreads
  • http://www.flickr.com/photos/rev_bri/112249215/
  • Asynchronous Servlets
    • Sun – Grizzly HTTP Connector
    • BEA – AbstractAsyncServlet
    • Tomcat 6.x – CometServlet
    • Jetty – Continuations
    • No standards here
  • Cometd / Bayeux
    • Cometd reference implementation
    • Bayeux pub/sub on top of Comet
      • Think JMS for JavaScript
  • DEMO
    • http://localhost:8080/examples/magnets/
  • Piggyback
    • The middle of the road
    • Send data to client with any other responses
  • Other Approaches to Push
    • LiveCycle Data Services
    • LightStreamer
  • Issues
    • Server load
    • Internet Explorer
  • Agenda
    • Who I Am
    • Offline Ajax
    • Pushing Ajax
    • Ajax Performance
    • Summary
  • Ajax Performance http://www.flickr.com/photos/edfladung/451378444/ Ajax Performance
  • Ask questions first, optimize second
  • What is the Bottleneck?
    • Situation dependent
    • How much data?
    • What type of data?
    • How many server hits?
    • What are the common workflows?
    • What browsers are you targeting?
    • What is the existing infrastructure?
  • Lifecycle
  • Data Formats
    • XML
      • <xml>You know this</xml>
    • JSON
      • {“json”:[“maybe”,”you”,don’t”],”know”:”this”}
    • HTML
      • <html>Looks familiar</html>
    • Text
    • Images
  • Server
    • HTML
      • Whatever you use today
    • XML
      • Standard support for object serialization
      • Similar to HTML
    • JSON
      • Easy to add on
  • Bandwidth
    • HTML
      • <div style=“color: red;”>Napoleon</div>
    • XML
      • <customer><name>Napoleon</name></customer>
      • <c n=“Napoleon”/>
    • JSON
      • {“customer”:[{“Name”:”Napoleon”}]}
      • {“c”:[{“n”:”Napoleon”}]}
    • Polling, code size etc
  • JavaScript
    • HTML
      • Nothing to do
    • XML
      • Transform with XSLT (browser dependent)
      • Iterate over XML DOM nodes and string build
      • Iterate over XML DOM nodes and create HTML DOM nodes
    • JSON
      • eval() the block of JSON to a JavaScript object
      • Transform with JSON Templates
      • Iterate through JavaScript arrays and string build
      • Iterate through JavaScript arrays and create HTML DOM nodes
  • Internet Explorer
  • Firefox
  • http://www.jamesward.org/census/ Firefox Internet Explorer
  • XSLT Cross Browser Performance
  • Don’t Lose your Keys
    • <xsl:key name=“sales-by-customer” match=“customer” use=“@name” />
    • <xsl:value-of select=&quot;key(‘sales-by-customer', $CustomerName)&quot;>
  • XSLT Performance
  • JSON with Padding (JSONP)
    • Most apps use XHR
    • Using XHR for JSON necessitates eval()
    • eval() is slow
    • Instead dynamically insert a <script> tag and have the returned JavaScript call a function …
    • http://localhost/javaone/
  • The Fast, Server Dependent Way
    • function getPostsSi() {
    • var elem = document.createElement(&quot;script&quot;);
    • elem.src = &quot;http://del.icio.us/feeds/json/davyjones? callback = buildHtml &quot;;
    • document.body.appendChild(elem);
    • }
    • function buildHtml (obj) {
    • var s = [];
    • for (var i=0; i<obj.length; i++) {
    • s.push(&quot;<div><a href='&quot;+obj[i].u+&quot;'>&quot; + obj[i].d + &quot;</a></div>&quot;);
    • }
    • $(&quot;container&quot;).innerHTML = s.join(&quot;&quot;);
    • }
  • The Slow, Server Agnostic Way
    • function getPostsXhr() {
    • var xhr = new nitobi.ajax.HttpRequest();
    • xhr.handler = &quot;http://localhost/feeds/json/davyjones&quot;;
    • xhr.onComplete.subscribe(xhrDataReady);
    • xhr.send();
    • }
    • function xhrDataReady(evtArgs) {
    • var obj = eval(&quot;(&quot;+evtArgs+&quot;)&quot;);
    • buildHtml (obj);
    • }
  • HTML DOM
    • HTML
      • $(“myNode”).innerHTML = “<div>Napoleon</div>”;
    • XML
      • innerHTML
      • DOM manipulations
        • createElement(“div”), appendChild(node), etc
    • JSON
      • innerHTML
      • DOM manipulations
    • Interactivity
  • General DOM Function
  • Most Wanted
    • innerHTML – consider HTML tags, floats, events
    • offsetTop / Left
    • getBoundingClientRect / getBoxObjectFor
    • Stylesheets
  • Watch Out for Memory Leaks
    • Circular loops between the DOM and JavaScript
    • Use Drip to find them
    <script type=“text/javascript”> var domNode = $(“myDomNode”); domNode .foo = domNode ; </script> expando
  • JavaScript Compression
    • Removing comments
    • Removing whitespace
    • Removing new-line characters
    • Replacing variables with shorter names
  • Simple Example var _a = function (a){ var b=0; var c=a.length; for ( var d=0;d<c;d++){b+=a[d];} return b/c;} var calcAverage =_a; /** * @private */ var _calcAverage = function(aNumber) { var nTotal = 0; var iLength = aNumber.length; for ( var iIndex = 0; i<iLength; i++) { nTotal += aNumber[iIndex]; } return nTotal/iLength; } /** * Calculates the average of an array of numbers. * @param {Array} Array of numbers to average. */ var calcAverage = _calcAverage;
  • Rhino Minification / Obfuscation
    • <target
    • name=&quot;obfuscateJS&quot;
    • description=&quot;compress and obfuscate code&quot;>
    • <java
    • classname=&quot;org.mozilla.javascript.tools.shell.Main“
    • dir=&quot;${basedir}uild hinoin&quot;
    • fork=&quot;true&quot;
    • output=&quot;${basedir}outputsrc_obfuscated.js&quot;>
    • <arg line=&quot;-c ${basedir}inputsrc.js &quot; />
    • <classpath>
    • <pathelement path=&quot;${basedir}uild hinoinjs.jar&quot; />
    • </classpath>
    • </java>
    • </target>
  • Compression
    • Request
      • Accept-Encoding: gzip,deflate
    • Response
      • Content-Encoding: gzip || deflate
    • IIS and Apache dynamically GZip / Deflate content and cache it
    • All modern browsers support compressed content
      • Internet Explorer 6 SP1 had some problems
    • IE, Firefox, Opera accept compressed content _without_ Content-Encoding header
  • Apache Compression
    • # Compress everything unless excluded below.
    • SetOutputFilter DEFLATE
    • SetInputFilter DEFLATE
    • SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary
    • SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|rar)$ no-gzip dont-vary
    • SetEnvIfNoCase Request_URI .(?:pdf|avi|mov|mp3|rm)$ no-gzip dont-vary
    • # Explicity compress certain file types
    • AddOutputFilterByType DEFLATE text/html text/plain text/xml
  • How Small is It? Size (Kb) Original 9.3 Minify 3.9 GZip / Deflate 2.8 Minify + GZip / Deflate 1.3 Size Reduction 86% Expected Results for JavaScript Compression
  • Content Merging
    • Reduce download overhead by merging resources
      • JavaScript
      • Cascading Stylesheets
      • Images
    • Careful with caching though!
  • Image Merging
  • Image Merging
    • <html>
    • <head>
    • <style type=&quot;text/css&quot; media=&quot;screen&quot;>
    • .colour {clip: rect(0px 135px 125px 0px);}
    • .grayscale {
    • left:-135px;
    • clip: rect(0px 270px 125px 135px);
    • }
    • .grayscale, .colour {
    • position:absolute;
    • width: 270px;height: 125px;
    • background: url(images/nitobi.jpg);
    • }
    • .container {
    • height:125px;width:135px;
    • position:relative;
    • }
    • </style>
    • </head>
    • <body>
    • <div class=&quot;container&quot;><div class=&quot;colour&quot;></div></div>
    • <div class=&quot;container&quot;><div class=&quot;grayscale&quot;></div></div>
    • </body>
    • </html>
    clip: rect(0px 135px 125px 0px); clip: rect(0px 270px 125px 135px); background: url(images/nitobi.jpg);
  • Agenda
    • Who I Am
    • Offline Ajax
    • Pushing Ajax
    • Ajax Performance
    • Summary
  • Summary
    • “ Work Offline” – know your users
      • Browser specific, Flash or Install
      • Usability
    • Push – watch out for your thumb
      • Real-time collaboration
      • Usability
    • Performance – ask questions first, optimize later
      • Be careful but not too careful
      • Usability
  • Q&A
    • Dave Johnson
    • www.nitobi.com
    • [email_address]
    • http://blogs.nitobi.com/dave