Build Lightweight Web Module

1,027 views

Published on

Published in: Technology, Design
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,027
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
11
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Build Lightweight Web Module

  1. 1. Build Lightweight Web Module<br />Morgan Cheng<br />@morgancheng<br />May 26th, 2011<br />
  2. 2. Expand Thriving Web Site<br />
  3. 3. Inject Your Content Into Other Sites<br />
  4. 4. Partner Website Server<br />Your Website Server<br />Browser<br />
  5. 5. Partner Website Server<br />Your Website Server<br />Web Module<br />Browser<br />
  6. 6. Cross Domain<br />
  7. 7. JSONP<br />
  8. 8. Inject Content with JSONP<br />Create one hidden element<br />Send JSONP request <br />When JSONP data is received, compose HTML<br />Fill the hidden element with composed HTML<br />Show hidden element<br />
  9. 9. Inject an iframe<br />
  10. 10.
  11. 11. iframe covering whole viewport<br />
  12. 12. It is easy to create abigiframe. The hard part is how to close it.<br />
  13. 13. Same Domain Callback<br />Hidden Proxy Iframe<br />
  14. 14. Time to Wear Hacker’s Hat<br />
  15. 15. Cannot be “javascript: … ”<br />Hidden Proxy Iframe<br />
  16. 16. API Design First<br />
  17. 17. <script src=“XXXXX_loader.js”></script><script>XXXXX.load(parameter);</script><br />
  18. 18. YAHOO.ABC.load(parameter);<br />
  19. 19. YAHOO.ABC.load(parameter);<br />Y.ABC.load(parameter);<br />
  20. 20. YAHOO.ABC.load(parameter);<br />Y.ABC.load(parameter);<br />YABC.load(parameter);<br />
  21. 21. YABC.load(<br /> ‘wretch’, // appid. Mandatory<br /> 1234, // spaceid. Mandatory<br /> 100 // delay in ms. Optional<br />);<br />
  22. 22. YABC.load(<br /> ‘wretch’, // appid. Mandatory<br /> 1234, // spaceid. Mandatory<br /> 100, // delay in ms. Optional<br /> ‘tw’ // intl. Mandatory<br />);<br />What if new Mandatory parameter is added?<br />
  23. 23. YABC.load({<br />appid: ‘wretch’,<br />spaceid: ‘1234’,<br /> delay: 100,<br />intl: ‘tw’<br />});<br />Better!<br />Config Object Pattern<br />
  24. 24. Be Disciplined<br />
  25. 25. Rules #1: <br />Don’t Assume Too Much on Hosting Page<br />What?<br />You Don’t Have YUI?<br />
  26. 26. Rules #2: <br />Don’t Be Obstructive to Hosting Page<br />
  27. 27. Rules #3: <br />Don’t Impact Hosting Page Performance<br />
  28. 28. In a Word, We Have To DIY<br />
  29. 29. And, It MUST Be Lightweight<br />
  30. 30. Simplest Feature vs. Rich Feature<br />
  31. 31. YAHOO.util.Connect.asyncRequest(<br /> ‘GET’,<br /> ‘http://www.example.com/jsonp’,<br /> {<br />success: sucessHandler,<br />failure: failureHandler,<br />argument: argumentObj<br /> },<br />postData<br />};<br />
  32. 32. We Don’t Need Full Feature<br />YAHOO.util.Connect.asyncRequest(<br /> ‘GET’,<br /> ‘http://www.example.com/jsonp’,<br /> {<br />success: sucessHandler,<br />failure: failureHandler,<br />argument: argumentObj<br /> },<br />postData<br />};<br />
  33. 33. This is What We Need<br />
  34. 34. Minify-Friendly JavaScript<br />
  35. 35. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />
  36. 36. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Before 287 bytes<br />After 119 bytes<br />Compression Rate: 59%<br />Minify<br />
  37. 37. What Can Be Minified?<br />
  38. 38. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Comments are stripped<br />
  39. 39. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Unnecessary White Spaces are Stripped<br />
  40. 40. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Argument Names are Obfuscated<br />
  41. 41. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams= [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){vara=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Local Variable Names are Minified<br />
  42. 42. What Can NOT Be Minified?<br />
  43. 43. /*<br /> * Gets query string presentation of given object.<br /> */<br />functiontoQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br />return encParams.join('&');<br />}<br />functiontoQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Keywords are NOT Minified<br />
  44. 44. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Global Variables are NOT Minified<br />
  45. 45. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />Object Properties are NOT Minified<br />
  46. 46. /*<br /> * Gets query string presentation of given object.<br /> */<br />function toQueryString(params) {<br />varencParams = [], encode = encodeURIComponent;<br />for(key in params) {<br />encParams.push(encode(key) + '=' + encode(params[key]));<br /> }<br /> return encParams.join('&');<br />}<br />function toQueryString(c){var a=[],b=encodeURIComponent;for(key in c){a.push(b(key)+"="+b(c[key]))}returna.join("&")};<br />How About This?<br />
  47. 47. Wait, Do We Need Minify If All Browsers Support Gzip?<br />
  48. 48. JavaScript?<br />Gzip<br />Gzip is no-loss compressionIt Doesn’t Understand JavaScript<br />
  49. 49. ~15% “Accept-Encoding: gzip, deflate”HTTP Headers Are Stripped<br />
  50. 50. Evolution of Code<br />
  51. 51. YABC = {<br />load: function() {<br /> // do something<br /> }<br />};<br />
  52. 52. YABC = {<br />privateVariable: ‘hello’,<br />privateFunction: function() {<br /> // do some private thing<br /> },<br />load: function() {<br /> // do something<br /> }<br />};<br />
  53. 53. YABC = {<br />privateVariable: ‘hello’,<br />privateFunction: function() {<br /> // do some helping<br /> },<br />load: function() {<br /> // do something<br /> }<br />};<br />Not Minifiable<br />
  54. 54. (function() {<br />var _privateVariable = ‘hello’;<br />function _privateFunction () {<br /> // do some private thing<br />}<br />YABC = {<br /> load: function() {<br /> // do something<br /> }<br />};<br />}())<br />Immediate Function Pattern<br />
  55. 55. (function() {<br />var_privateVariable= ‘hello’;<br />function _privateFunction() {<br /> // do some private thing<br />}<br />YABC = {<br /> load: function() {<br /> // do something<br /> }<br />};<br />}())<br />Minifiable<br />
  56. 56. (function() {<br />var win = window; <br />_privateVariable = ‘hello’;<br />function _privateFunction () {<br /> // do some private thing<br />}<br />YABC = {<br /> load: function() {<br /> // do something<br /> }<br />};<br />}())<br />“window” is used more than once<br />
  57. 57. (function() {<br />var win = window; <br />_privateVariable = ‘hello’;<br />function _privateFunction () {<br /> // do some private thing<br />}<br />YABC = {<br /> unload: function() {<br /> },<br /> load: function() {<br /> // do something<br /> }<br />};<br />}())<br />
  58. 58. (function() {<br />var win = window; <br />_privateVariable = ‘hello’;<br />function _privateFunction () {<br /> // do some private thing<br />}<br />YABC = {<br />unload: function() {<br /> },<br /> load: function() {<br /> // do something<br /> }<br />};<br />}())<br />Every invocation of this method has to be “YABC.unload”<br />
  59. 59. (function() {<br />var win = window; <br />_privateVariable = ‘hello’,<br />yabc;<br />function _privateFunction () {<br /> // do some private thing<br />}<br />varyabc= {<br />unload: function() {<br /> },<br /> load: function() {<br /> // do something<br /> }<br />};<br />YABC = yabc;<br />}())<br />Local Invocation of “yabc.unload” can be minfied<br />
  60. 60. (function() {<br />var win = window; <br />_privateVariable = ‘hello’,<br />yabc;<br />function _privateFunction () {<br /> // do some private thing<br />}<br />varyabc= {<br /> unload: function() {<br /> },<br /> load: function() {<br /> // do something<br /> }<br />};<br />YABC = yabc;<br />}())<br />YUI Developers,<br />Looks Familiar?<br />
  61. 61. Be a JavaScript Ninjia<br />
  62. 62. (function() {<br /> // immediate functioning<br />}())<br />
  63. 63. (function() {<br /> // immediate functioning<br />}())<br />!function() {<br /> // immediate functioning<br />}()<br />Saving 1 Byte<br />
  64. 64. if (-1===indexOf(foo,’bar’)) {<br /> // do something<br />}<br />
  65. 65. if (-1!==foo.indexOf(’bar’)) {<br /> // do something<br />}<br />if (~foo.indexOf(’bar’)) {<br /> // do something<br />}<br />Saving 4 Bytes<br />
  66. 66. function escapeHTML(s) {<br /> return s.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g,'&lt;').replace(/"/g, '&quot').replace(/'/g,''').replace(///g,'/');<br />}<br />
  67. 67. function escapeHTML(s) {<br /> return s.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g,'&lt;').replace(/"/g, '&quot').replace(/'/g,''').replace(///g,'/');<br />}<br />function escapeHTML(s, r) {<br />r='replace';returns[r](/&/g,'&amp;')[r](/>/g,'&gt;')[r](/</g,'&lt;')[r](/"/g, '&quot')[r](/'/g,''')[r](///g,'/’);<br />}<br />Saving 19 Bytes<br />
  68. 68. History of code size<br />
  69. 69. JavaScript is NOT SlowBut, DOM is Slow<br />
  70. 70. Module Versioning<br />
  71. 71. Traditionally …<br />http://www.example.com/v1/loader.js<br />http://www.example.com/loader_20110510.js<br />
  72. 72. Short Time Caching<br />
  73. 73. Takeaways<br />Make your partners happy<br />Hack your own code. Hack it Hard!<br />Minify JavaScript Code<br />
  74. 74. Thank You!<br />

×