Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

AMD - Why, What and How

7,545 views

Published on

AMD was put together by the JavaScript developer community in response to the wild west of coding styles and lack of standards.

Published in: Technology
  • Sex in your area is here: ❤❤❤ http://bit.ly/369VOVb ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/369VOVb ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

AMD - Why, What and How

  1. 1. AMD - WHY, WHAT, AND HOWMike Wilcox - January2012Tweets: @clubajaxBlogs: clubajax.org
  2. 2. The Problem
  3. 3. The ProblemToday’s complex Web Apps have created theneed for:
  4. 4. The ProblemToday’s complex Web Apps have created theneed for: Structure Some sort of framework, to aid in rapid development
  5. 5. The ProblemToday’s complex Web Apps have created theneed for: Structure Some sort of framework, to aid in rapid development Object orientation To “black box” complex code
  6. 6. The ProblemToday’s complex Web Apps have created theneed for: Structure Some sort of framework, to aid in rapid development Object orientation To “black box” complex code Modules and packages RE: The 2,500 best jQuery plugins...
  7. 7. The ProblemToday’s complex Web Apps have created theneed for: Structure Some sort of framework, to aid in rapid development Object orientation To “black box” complex code Modules and packages RE: The 2,500 best jQuery plugins... Dependencies (includes, requires, imports, what-ev)
  8. 8. The ProblemToday’s complex Web Apps have created theneed for: Structure Some sort of framework, to aid in rapid development Object orientation To “black box” complex code Modules and packages RE: The 2,500 best jQuery plugins... Dependencies (includes, requires, imports, what-ev) Reusable code Scope-isolated, clean API, portable Globals are bad!
  9. 9. Single Files
  10. 10. Single Files The “old fashioned way” to write JavaScript was to do it all in a single file.
  11. 11. Single Files The “old fashioned way” to write JavaScript was to do it all in a single file. // define library ! var!noop = function(){ ! ! }, ! ! isEmpty = function(it){ ! ! ! for(var p in it){ ! ! ! ! return 0; ! ! ! } ! ! ! return 1; ! ! }, ! ! toString = {}.toString, ! ! isFunction = function(it){ ! ! ! return toString.call(it) == "[object Function]"; ! ! }, ! ! isString = function(it){ ! ! ! return toString.call(it) == "[object String]";
  12. 12. Single Files ! ! ! ! ! ! ! ! ! computeMapProg = function(map, dest, packName){ ! ! dest.splice(0, dest.length); var p, i, item, reverseName = 0; The “old fashioned way” to write JavaScript was to do ! ! ! ! for(p in map){ ! ! ! ! ! dest.push([p, map[p]]); it all in a single file. ! ! ! ! ! if(map[p]==packName){ ! ! ! ! ! ! reverseName = p; ! ! ! ! ! } ! ! ! ! } ! ! ! ! dest.sort(function(lhs, rhs){ ! ! ! ! ! return rhs[0].length - lhs[0].length; ! ! ! ! }); ! ! ! ! for(i = 0; i < dest.length;){ ! ! ! ! ! item = dest[i++]; ! ! ! ! ! item[2] = new RegExp("^" + item[0].replace(/([.$?*|{} ()[]/+^])/g, function(c){ return "" + c; }) + "(/|$)"); ! ! ! ! ! item[3] = item[0].length + 1; ! ! ! ! } ! ! ! ! return reverseName; ! ! ! }, ! ! ! fixupPackageInfo = function(packageInfo, baseUrl){ ! ! ! ! // calculate the precise (name, baseUrl, main, mappings) for a package ! ! ! ! var name = packageInfo.name; ! ! ! ! if(!name){
  13. 13. Single File - pros & cons
  14. 14. Single File - pros & cons Pros Fewer resources means faster load times.
  15. 15. Single File - pros & cons Pros Fewer resources means faster load times. No “build step” necessary.
  16. 16. Single File - pros & cons Pros Fewer resources means faster load times. No “build step” necessary.Cons Difficult to maintain and edit a file thousands of lines long. GOTO Line #
  17. 17. Single File - pros & cons Pros Fewer resources means faster load times. No “build step” necessary.Cons Difficult to maintain and edit a file thousands of lines long. GOTO Line # Code reusability is dirt poor. Copy and paste?
  18. 18. Single File - pros & cons Pros Fewer resources means faster load times. No “build step” necessary.Cons Difficult to maintain and edit a file thousands of lines long. GOTO Line # Code reusability is dirt poor. Copy and paste? Makes team development near impossible. GITMERGETOOL
  19. 19. Multiple Files
  20. 20. Multiple FilesMultiple files which follow an object oriented ornamespaced approach are easier to maintain becausethe brain more easily maps files to ideas.
  21. 21. Multiple FilesMultiple files which follow an object oriented ornamespaced approach are easier to maintain becausethe brain more easily maps files to ideas. [dom.js] [lang.js] library.dom = { library.lang = { // code // code } } [events.js] [string.js] library.events = library.string = { { // code // code } }
  22. 22. Multi File - pros & cons
  23. 23. Multi File - pros & cons Pros One-to-one, file-to-class makes organization easier.
  24. 24. Multi File - pros & cons Pros One-to-one, file-to-class makes organization easier. The brain more easily maps files to concepts (objects).
  25. 25. Multi File - pros & cons Pros One-to-one, file-to-class makes organization easier. The brain more easily maps files to concepts (objects). More team friendly.
  26. 26. Multi File - pros & cons Pros One-to-one, file-to-class makes organization easier. The brain more easily maps files to concepts (objects). More team friendly.Cons The files (and server requests) will add up fast and that will slow down the page.
  27. 27. Multi File - pros & cons Pros One-to-one, file-to-class makes organization easier. The brain more easily maps files to concepts (objects). More team friendly.Cons The files (and server requests) will add up fast and that will slow down the page. Lots of <script> tags. BLEAH.
  28. 28. Multi File - pros & cons Pros One-to-one, file-to-class makes organization easier. The brain more easily maps files to concepts (objects). More team friendly.Cons The files (and server requests) will add up fast and that will slow down the page. Lots of <script> tags. BLEAH. The system to track all these files and their order is YOU.
  29. 29. Web App with <script> tags
  30. 30. Web App with <script> tags
  31. 31. Web App with <script> tags
  32. 32. Build solution for <script> tags
  33. 33. Build solution for <script> tags Result can be fed into Google Closure Combiner, Dojo Shrinksafe, UglifyJS, etc, etc.
  34. 34. Dependency Matters
  35. 35. Dependency Matters Scripts load in this order[dom.js] [events.js]library.dom = { // code [lang.js] library.events =} { [string.js] library.lang = { // code } // code } library.string = { // code }
  36. 36. Dependency Matters Scripts load in this order A change is made to dom.js Adds events to node on create.[dom.js] [events.js]library.dom = { // code [lang.js] library.events =} { [string.js] library.lang = { // code } // code } library.string = { // code }
  37. 37. Dependency Matters Scripts load in this order A change is made to dom.js Adds events to node on create.[dom.js] [events.js]library.dom = { // code [lang.js] library.events =} { [string.js] dom.js is trying to access library.lang = { // code } // code events.js but it’s not loaded } library.string = yet { // code }
  38. 38. Dependency Management[dom.js] [events.js]library.dom = { // code [lang.js] library.events =} { [string.js] library.lang = { // code } // code } library.string = { // code }
  39. 39. Dependency Management [player.html][dom.js] [events.js]library.dom = { // code [admin.html] [lang.js] library.events =} { [string.js] library.lang = { // code } // code } library.string = { // code } [test.html]Now script order needsto be changed in all your
  40. 40. I thought Dojo had a build tool with dependency
  41. 41. Dojo’s <1.7 Solution
  42. 42. Dojo’s <1.7 Solution“provide” registers this page of code as “a class” (butactually just an object). dojo.provide(“dijit.Dialog”);
  43. 43. Dojo’s <1.7 Solution“provide” registers this page of code as “a class” (butactually just an object). dojo.provide(“dijit.Dialog”); dojo.require(“dijit.form.Button”); “require” tells Dojo that the provided code depends upon the required code. Dojo guarantees that the required code is loaded before the provided code is executed.
  44. 44. How Dojo <1.7 Worked
  45. 45. How Dojo <1.7 Worked Script files were pulled in as text with XHR. -= XHR =-[dom.js]codecodecoderequire(‘event’)library.dom = { // code}
  46. 46. How Dojo <1.7 Worked Script files were pulled in as text with XHR. One at a time, each text file is eval’d into JavaScript. synchronously! -= XHR =- -= EVAL =-[dom.js] [dom.js] [dom.js]code code codecode code codecode code coderequire(‘event’) require(‘event’) require(‘event’)library.dom = { library.dom = { library.dom = { // code // code // code} } }
  47. 47. Dojo <1.7 Problems
  48. 48. Dojo <1.7 Problems XHR load has same-origin restrictions
  49. 49. Dojo <1.7 Problems XHR load has same-origin restrictions Special, complex, XD loader was needed
  50. 50. Dojo <1.7 Problems XHR load has same-origin restrictions Special, complex, XD loader was needed Eval’d code totally fubar’d syntax-error line numbers
  51. 51. Dojo <1.7 Problems XHR load has same-origin restrictions Special, complex, XD loader was needed Eval’d code totally fubar’d syntax-error line numbers Synchronous XHR is very slow
  52. 52. Dojo <1.7 Problems XHR load has same-origin restrictions Special, complex, XD loader was needed Eval’d code totally fubar’d syntax-error line numbers Synchronous XHR is very slow Some environments do not allow eval (like Adobe AIR)
  53. 53. Dojo <1.7 Problems XHR load has same-origin restrictions Special, complex, XD loader was needed Eval’d code totally fubar’d syntax-error line numbers Synchronous XHR is very slow Some environments do not allow eval (like Adobe AIR) eval executes differently across browsers
  54. 54. Dojo <1.7 Problems XHR load has same-origin restrictions Special, complex, XD loader was needed Eval’d code totally fubar’d syntax-error line numbers Synchronous XHR is very slow Some environments do not allow eval (like Adobe AIR) eval executes differently across browsers Developers are taught that eval is evil
  55. 55. ALTERNATIVE LOADER TECHNIQUES
  56. 56. Async
  57. 57. Async var Employee = require("Employee"); function Manager () { } Manager.prototype = new Employee(); [ ERROR ]
  58. 58. Async var Employee = require("Employee"); function Manager () { } Manager.prototype = new Employee(); [ ERROR ]The Employee code is loaded async, so it happens inthe background while Manager is invoked, whichmeans Employee is not ready and an error occurs.
  59. 59. document.write
  60. 60. document.write write(‘<script src=”Store.js” />’); write(‘<script src=”Employee.js” />’);
  61. 61. document.write write(‘<script src=”Store.js” />’); write(‘<script src=”Employee.js” />’); No access to the script’s dependencies
  62. 62. document.write write(‘<script src=”Store.js” />’); write(‘<script src=”Employee.js” />’); No access to the script’s dependencies Does not work after page load
  63. 63. document.write write(‘<script src=”Store.js” />’); write(‘<script src=”Employee.js” />’); No access to the script’s dependencies Does not work after page load Blocks page rendering
  64. 64. appendChild(‘script’);
  65. 65. appendChild(‘script’); head = document.getElementsByTagName(head)[0]; script = document.createElement(script); script.src = url; head.appendChild(script); No access to the script’s dependencies
  66. 66. appendChild(‘script’); head = document.getElementsByTagName(head)[0]; script = document.createElement(script); script.src = url; head.appendChild(script); No access to the script’s dependencies Has same async issues
  67. 67. THE SOLUTION
  68. 68. Function Wrapping
  69. 69. Function Wrapping dependency dependency dependency code_for_loader_to_execute = function(){ return code_to_be_converted_to_module_later }
  70. 70. Function Wrapping dependency dependency dependency code_for_loader_to_execute = function(){ return code_to_be_converted_to_module_later } Wrapping code in function allows the loader to control when invocation needs to occur
  71. 71. Function Wrapping dependency dependency dependency code_for_loader_to_execute = function(){ return code_to_be_converted_to_module_later } Wrapping code in function allows the loader to control when invocation needs to occur All code can defer until after all dependencies are determined and loaded
  72. 72. AMD’s Methods
  73. 73. AMD’s Methods“define” registers this page of code as “a class”. define();
  74. 74. AMD’s Methods“define” registers this page of code as “a class”. define(); require(); “require” loads in the requested modules and provides them in a callback function.
  75. 75. Anatomy of AMD - define()
  76. 76. Anatomy of AMD - define() define( [ “./depA”, “./depB” ], function(depA, depB){ var myModule = {}; return myModule; } ); * There are other argument options, but these are the most common.
  77. 77. Anatomy of AMD - define()One of twoglobals used inthe spec define( [ “./depA”, “./depB” ], function(depA, depB){ var myModule = {}; return myModule; } ); * There are other argument options, but these are the most common.
  78. 78. Anatomy of AMD - define()One of two Dependencies list definedglobals used in as an array in the firstthe spec argument define( [ “./depA”, “./depB” ], function(depA, depB){ var myModule = {}; return myModule; } ); * There are other argument options, but these are the most common.
  79. 79. Anatomy of AMD - define()One of two Dependencies list definedglobals used in as an array in the firstthe spec argument The second define( [ argument is the “./depA”, Factory which is “./depB” consumed when ], function(depA, depB){ module is requested var myModule = {}; return myModule; } ); * There are other argument options, but these are the most common.
  80. 80. Anatomy of AMD - define()One of two Dependencies list definedglobals used in as an array in the firstthe spec argument The second define( [ argument is the “./depA”, Factory which is “./depB” consumed when ], function(depA, depB){ module is requested var myModule = {}; Dependencies return myModule; passed as factory’s } arguments ); * There are other argument options, but these are the most common.
  81. 81. Anatomy of AMD - define()One of two Dependencies list definedglobals used in as an array in the firstthe spec argument The second define( [ argument is the “./depA”, Factory which is “./depB” consumed when ], function(depA, depB){ module is requested var myModule = {}; Dependencies return myModule; passed as factory’s } arguments All of your module ); magic happens here, complete with scope isolation * There are other argument options, but these are the most common.
  82. 82. Anatomy of AMD - define()One of two Dependencies list definedglobals used in as an array in the firstthe spec argument The second define( [ argument is the “./depA”, Factory which is “./depB” consumed when ], function(depA, depB){ module is requested var myModule = {}; Dependencies return myModule; passed as factory’s } arguments All of your module); magic happens here, complete with scope isolationLooks like a class, smellslike a class... * There are other argument options, but these are the most common.
  83. 83. Anatomy of AMD - require()
  84. 84. Anatomy of AMD - require() require( [ “library/depA”, “library/depB” ], function(depA, depB){ depA.doSomething(); depB.someMore(); } ); * There are other argument options, but these are the most common.
  85. 85. Anatomy of AMD - require()The other global require( [ “library/depA”, “library/depB” ], function(depA, depB){ depA.doSomething(); depB.someMore(); } ); * There are other argument options, but these are the most common.
  86. 86. Anatomy of AMD - require() Modules, or “Imports” listThe other global defined as an array in the first argument require( [ “library/depA”, “library/depB” ], function(depA, depB){ depA.doSomething(); depB.someMore(); } ); * There are other argument options, but these are the most common.
  87. 87. Anatomy of AMD - require() Modules, or “Imports” listThe other global defined as an array in the first argument require( Callback fires when [ modules are loaded “library/depA”, “library/depB” and ready ], function(depA, depB){ depA.doSomething(); depB.someMore(); } ); * There are other argument options, but these are the most common.
  88. 88. Anatomy of AMD - require() Modules, or “Imports” listThe other global defined as an array in the first argument require( Callback fires when [ modules are loaded “library/depA”, “library/depB” and ready ], function(depA, depB){ depA.doSomething(); Modules passed as depB.someMore(); callback’s } arguments ); * There are other argument options, but these are the most common.
  89. 89. Anatomy of AMD - require() Modules, or “Imports” listThe other global defined as an array in the first argument require( Callback fires when [ modules are loaded “library/depA”, “library/depB” and ready ], function(depA, depB){ depA.doSomething(); Modules passed as depB.someMore(); callback’s } arguments ); Modules are ready to access here * There are other argument options, but these are the most common.
  90. 90. Anatomy of AMD - require() Modules, or “Imports” listThe other global defined as an array in the first argument require( Callback fires when [ modules are loaded “library/depA”, “library/depB” and ready ], function(depA, depB){ depA.doSomething(); Modules passed as depB.someMore(); callback’s } arguments ); Modules are ready to access hereLooks like “define”! Simple! * There are other argument options, but these are the most common.
  91. 91. Why is ASYNC fast anyway?
  92. 92. Why is ASYNC fast anyway?In this context, “async” refers to allowing the browserto load the scripts natively. It can load many scripts atonce, concurrently.
  93. 93. Why is ASYNC fast anyway?The “sync” loader needed to block all other processeswhile a script was loaded.
  94. 94. EXTENDING AMD
  95. 95. Plugins
  96. 96. PluginsThe bang! symbol represents a plugin thatperforms a special task. require(["dojo", "dojo/domReady!"], function(dojo){ ! doDomStuff(); }); define([ “dijit/Widget”, “dojo/text!myTemplate.html” ], function(Widget, template){ // build a widget });
  97. 97. PluginsThe bang! symbol represents a plugin thatperforms a special task. domReady! is a common plugin that prevents the callback from firing until the DOM is in fact... ready. require(["dojo", "dojo/domReady!"], function(dojo){ ! doDomStuff(); }); define([ “dijit/Widget”, “dojo/text!myTemplate.html” ], function(Widget, template){ // build a widget });
  98. 98. PluginsThe bang! symbol represents a plugin thatperforms a special task. domReady! is a common plugin that prevents the callback from firing until the DOM is in fact... ready. require(["dojo", "dojo/domReady!"], function(dojo){ ! doDomStuff(); }); define([ “dijit/Widget”, “dojo/text!myTemplate.html” ], function(Widget, template){ // build a widget }); text! knows that it is reading text or HTML and possibly applies transforms to it.
  99. 99. Build Tools
  100. 100. Build ToolsA “profile” is the description file the Dojo Builder uses.The AMD structure works well as individual files or asone combined file. var profile = { ! releaseDir:"../clubajax-deploy", ! packages:[ ! ! { ! ! ! name:"clubajax", ! ! ! location:"." ! ! },{ ! ! ! name:"plugin", ! ! ! location:"../plugin" ! ! } ! ], ! layers:{ ! ! "clubajax/layer":{ ! ! ! include:[ custom/main, plugin/main ] ! ! } ! } };
  101. 101. Packages
  102. 102. PackagesA package.json file will help describe your code, itsexternal dependencies, and how it should be used. { "name": "clubajax.js", "description": "Club AJAX Base Library", "licenses": [{ "type": "AFLv2.1", "url": "http://dojo/LICENSE" }], "bugs": "", "keywords": [], "homepage": "http://clubajax.org/", "dependencies": {}, "dojoBuild": "clubajax.profile.js", "main": "./main"
  103. 103. PackagesA package.json file will help describe your code, itsexternal dependencies, and how it should be used. { "name": "clubajax.js", "description": "Club AJAX Base Library", "licenses": [{ "type": "AFLv2.1", "url": "http://dojo/LICENSE" }], "bugs": "", "keywords": [], "homepage": "http://clubajax.org/", "dependencies": {}, "dojoBuild": "clubajax.profile.js", "main": "./main"“dojoBuild” points to the profile, and “main” points tothe master file that knows of all the files in thepackage.
  104. 104. RESOURCES
  105. 105. AMD Authors
  106. 106. AMD Authors James Burke Original Dojo Loader author Developed RequireJS and spearheaded AMD
  107. 107. AMD Authors
  108. 108. AMD Authors Kevin Dangoor Authored blog post: “What Server Side JavaScript Needs” Founded CommonJS Expressed the need for JS modules and packages RequireJS based on CommonJS module spec
  109. 109. AMD Authors
  110. 110. AMD Authors Rawld Gill Wrote the Dojo 1.7 loader and Node.js build tool key contributor to AMD spec Authored all AMD plugins (text, i18n, domReady, ready) dojo bootstrap (kernel and base load) dojos has.js implementation (enhanced from standard version)
  111. 111. AMD Authors
  112. 112. AMD Authors Kris Zyp Of course he helped. What is there that Kris Zyp DOESN’T do??
  113. 113. AMD LibrariesThe following libraries are either AMD-compliant or AMD loaders jQuery 1.7 Dojo 1.7 MooTools 2.0 EmbedJS curl.js
  114. 114. More AMD Info https://github.com/amdjs/amdjs-api/wiki/AMD http://www.commonjs.org/ http://www.commonjs.org/specs/ http://dojotoolkit.org/reference-guide/loader/ index.html#loader-index http://dojotoolkit.org/reference-guide/loader/amd.html#loader- amd http://arstechnica.com/web/news/2009/12/commonjs-effort- sets-javascript-on-path-for-world-domination.ars http://requirejs.org/docs/history.html http://www.commonjs.org/history/ https://groups.google.com/group/amd-implement?pli=1✴ Special credit to Rawld Gill of Alto Visio for his in depth explanations of Dojo Loader and Build Tool✴ And a very special credit to James Burke - since most of the information in this presentation came from the RequireJS pages.
  115. 115. Description

×