Upload
minh-hoang
View
2.679
Download
0
Embed Size (px)
Citation preview
Modularize JavaScript with RequireJS
Minh Hoang TO
August 8, 2013
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Agenda
1 Performance Problem
2 Problem Analysis
3 JavaScript Code Organizing
4 RequireJS Library
5 RequireJS Integration
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Bad User ExperienceNumerical Reports
Slow Login Page
Open login form of Dagens Nyheter (http://dn.se) or browse for the firsttime to
https://auth.dn.se/login?appId=dagensnyheter.se
↓
↓
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Bad User ExperienceNumerical Reports
Low PageSpeed Scores
Figure 1: PageSpeed scores of https://auth.dn.se/login?appId=dagensnyheter.se
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Firebug TimelineFundamental CausesInitiative Idea
Firebug Timeline
Figure 2: Loading timeline on all resources
Figure 3: Loading timeline on JavaScript resources
DOMContentLoaded time: 7.6s
Load main.js time: 5s
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Firebug TimelineFundamental CausesInitiative Idea
Blocking JavaScript
Browser loads the entire main.js file (314.4KB) before rendering DOM content
Figure 4: Blocking main.js
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Firebug TimelineFundamental CausesInitiative Idea
Too Sequential Loading
main.js = jquery + jquery-ui + some jquery plugins + business code of DN
→ Should find one way to load library parts in parallel
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Firebug TimelineFundamental CausesInitiative Idea
Initiative Idea
Organize JavaScript code into modules with loose dependencies so that theyare eligible to deferred, lazy and parallel loading
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
Math Functions
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
Math Functions - Drawbacks
Blocking and sequential load of JavaScript resources:
Browser loads square.js and fourthPower.js too early
Evaluation of fourthPower.js requires function declared in square.js,sequential load is inevitable
→ See if new JavaScript code styles help?
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
Asynchronous Module Definition
Provide resource containing factory method of R, denote this resource as F (R),instead of providing directly resource R
F (R) holds:
Name of module R
Names of dependency modules of R
Factory method that generates R
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
Math Functions - AMD Modules
Figure 5: squareAMD module defined in squareAMD.js
Figure 6: fourthPowerAMD module defined in fourthPowerAMD.js
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
AMD - Valuable Features
Browser evaluation of F (R) does not trigger evaluation of R, thatheavy-weight work could be deferred
F (R1),F (R2), . . . ,F (Rk ) have no inter-dependencies at evaluation timeeven if R1,R2, . . . ,Rk do → ideal for parallel loading
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
Math Functions - Use of AMD Modules
Figure 7: Use AMD modules in AMD style
Execution of require block triggers:
Resolution1 of squareAMD and fourthPowerAMD modules
Execution of callback method on completing module resolutionsquareAMD and fourthPowerAMD are wired to sq and fp, respectively.
1Full explanation on resolution is given in RequireJS slides
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Common JavaScript StyleInnovative JavaScript Style
Inversion of Control
Inversion of Control pattern applied to JavaScript
Use of AMD requires JavaScript loader library2 which:
Manages lazy (on demand) and parallel loading of factory resourcesF (R1),F (R2), . . . ,F (Rk )
Invoke factory methods with proper execution order
Provides naming service for modules
2RequireJS is such a library
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
General InformationHow To Use RequireJS
General Information
http://requirejs.org
JavaScript file and module loader library
Supports Asynchronous Module Definition
Minified size: 14.7KB
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
General InformationHow To Use RequireJS
Math Functions
Figure 8: Math Functions example illustrates use of RequireJS
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
General InformationHow To Use RequireJS
Module Resolution
For each module name appears in array parameter, RequireJS looks upassociated module object
FOUND:Assign module object to corresponding parameter of callback function
NOT FOUND:Generate script block loading JavaScript file named ${module name}.jsLooks up dependencies of AMD module declared in ${module name}.js andinvoke factory methodPut return object into a map structure with key ${module name}Assign return object to corresponding parameter of callback function ofrequire block
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
General InformationHow To Use RequireJS
RequireJS Configuration Variable
Provide flexible mapping between AMD module and URL of JavaScriptresource containing module definition
Figure 9: Configuration variable in case squareAMD and fourthPowerAMD module definitions aredeclared in /js/square_amd.js and /js/fourthPower_amd.js
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
General InformationHow To Use RequireJS
Math Functions - Firebug View
Figure 10: Firebug shows that script blocks loading module are added programmatically
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Serviceplus - main.js
Content varies with application (DN,DI ,Expressen, . . .)
/main.js?appId=name_of_requested_application
Average size: ≥ 300KBCommon structure: jQuery + jQuery Plugins + business code of application
→ Better JavaScript code organization:
Serviceplus provides jQuery, jQuery Plugins as AMD modules
Business code part of main.js is moved into callback function of requireblock
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Serviceplus - AMD Modules
Serviceplus provides popular JavaScript libraries in form of AMD modules:
jQuery
jQuery UI
Other jQuery Plugins
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Serviceplus - jQuery
jQuery module = Minified jQuery wrapped in define block
Figure 11: jQuery AMD module, jQuery.noConflict() is used to avoid conflict with other jQueryversions
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Serviceplus - jQuery UI
jQuery UI module = Minified jQuery UI wrapped in define block
Figure 12: jQuery UI AMD moduleMinh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Serviceplus - RequireJS Configuration Variable
Declares mapping between Serviceplus AMD modules and URLs ofJavaScript resources
Merged to RequireJS library to save one HTTP request
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Serviceplus - New main.js Structure
New main.js = Business code part of main.js wrapped in require block
Figure 13: main.js of an application using jQuery and jQuery UI
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Faster Login Page
http://account.qa.newsplus.se/login?appId=dagensnyheter.se
↓
↓
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
PageSpeed Scores
Figure 14: PageSpeed scores of http://account.qa.newsplus.se/?appId=dagensnyheter.se
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
PageSpeed Suggestion
Figure 15: No significant issue on JavaScript resource from PageSpeed suggestions
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Firebug Timeline
Figure 16: Firebug report on JavaScript resource loading
DOMContentLoaded time: 1.88s
Big JavaScript resources jquery, jquery-ui and jquery-custom are loaded inparallel
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
WebPageTest Result
Figure 17: WebPageTest result shows parallel load of large JavaScript resources and sharp reductionon DOMContentLoaded time
Minh Hoang TO Modularize JavaScript with RequireJS
Performance ProblemProblem Analysis
JavaScript Code OrganizingRequireJS Library
RequireJS Integration
Legacy JavaScriptNew JavaScriptAchievementsExtensions
Extensions
Refine Serviceplus AMD modules
Extend relevant server-side functionalities
Minh Hoang TO Modularize JavaScript with RequireJS