第1页
Scalable JavaScript Application Architecture
Nicholas C. Zakas | @slicknet
第2页
Who's this guy?
Ex-tech lead Yahoo!
Co-Creator csslint.net
Contributor, Creator of YUI Test
Author
Lead Author
Contributor
Lead Author
第3页
@slicknet
第4页
Single-page apps
第5页
Model
View
Controller
第6页
Single-page apps &
Multi-page apps
第7页
Building an application framework
第8页
An application framework is like a playground for your code
Provides structure around otherwise unrelated activities
flickr.com/photos/osterwalder/152697503/
第9页
Isn't that what JavaScript libraries do?
第10页
flickr.com/photos/skistz/398429879/
A JavaScript library is like a toolbox You can build any number of things using the tools
第11页
Application Core
Base Library
第12页
Module Theory Everything is a module
第13页
module (n) 1 : a standard or unit of measurement 2 : the size of some one part taken as a unit of measure by which the proportions of an architectural composition are regulated 3 a : any in a series of standardized units for use together: as (1) : a unit of furniture or architecture (2) : an educational unit which covers a single subject or topic b : a usually packaged functional assembly of electronic components for use with other such assemblies 4 : an independently operable unit that is a part of the total structure of a space vehicle 5 a : a subset of an additive group that is also a group under addition b : a mathematical set that is a commutative group under addition and that is closed under multiplication which is distributive from the left or right or both by elements of a ring and for which a(bx) = (ab)x or (xb)a = x(ba) or both where a and b are elements of the ring and x belongs to the set
Source: Merriam-Webster Dictionary
第14页
module (n) 1 : a standard or unit of measurement 2 : the size of some one part taken as a unit of measure by which the proportions of an architectural composition are regulated 3 a : any in a series of standardized units for use together: as (1) : a unit of furniture or architecture (2) : an educational unit which covers a single subject or topic b : a usually packaged functional assembly of electronic components for use with other such assemblies 4 : an independently operable unit that is a part of the total structure of a space vehicle 5 a : a subset of an additive group that is also a group under addition b : a mathematical set that is a commutative group under addition and that is closed under multiplication which is distributive from the left or right or both by elements of a ring and for which a(bx) = (ab)x or (xb)a = x(ba) or both where a and b are elements of the ring and x belongs to the set
Source: Merriam-Webster Dictionary
第17页
How does this apply to web applications?
第18页
web application module (n) 1 : an independent unit of functionality that is part of the total structure of a web application
Source: Me
第20页
Web application modules consist of HTML + CSS + JavaScript
第21页
Any single module should be able to live on its own
第22页
Loose coupling allows you to make changes to one module without affecting the others
flickr.com/photos/quinnanya/3575417671/
第23页
flickr.com/photos/renfield/3414246938/
Each module has its own sandbox
An interface with which the module can interact to ensure loose coupling
第24页
Module
Module
Module
Module
Sandbox
Application Core
Base Library
Module
第25页
Application Architecture
Modules Sandbox Application Core Base Library
第26页
Module Module
Module Sandbox
Module Module
Modules have limited knowledge
Each module knows about their sandbox and that's it
第27页
Core.register("module-name", function(sandbox){
return { init: function(){ //constructor },
destroy: function(){ //destructor
}
};
});
第28页
Which parts know about the web application being built?
第29页
None of them
第30页
Each part of the architecture is like a puzzle piece No single piece needs to know what the picture is All that matters is that the piece does its own job correctly flickr.com/photos/generated/501445202/
第31页
What is a module's job?
第32页
Hello, I'm the weather module. It's my job to tell you the weather.
第33页
Hello, I'm the stocks module. It's my job to tell you about the stock market.
第34页
Each module's job is to create a meaningful user experience
第35页
flickr.com/photos/eljay/2392332379/
The web application is created as a result of all parts doing their job
第36页
This doesn't mean modules can do whatever they want to do their job
第37页
flickr.com/photos/tedsblog/43433812/
Modules are like little kids
They need a strict set of rules so they don't get into trouble
第38页
Module Rules
• Hands to yourself
Only call your own methods or those on the sandbox Don't access DOM elements outside of your box Don't access non-native global objects
• Ask, don't take
Anything else you need, ask the sandbox
• Don't leave your toys around
Don't create global objects
• Don't talk to strangers
Don't directly reference other modules
第39页
Modules must stay within their own sandboxes No matter how restrictive or uncomfortable it may seem
flickr.com/photos/madaise/3406217980/
第40页
Application Architecture
Modules Sandbox Application Core Base Library
第41页
Module
Module
Module
Module
Sandbox
Application Core
Base Library
Module
第42页
Sandbox
The sandbox ensures a consistent interface Modules can rely on the methods to always be there
第43页
Module
Module
Module
Module
Sandbox
Application Core
Base Library
Module
第44页
Module Module
Module Sandbox
Module Module
Modules only know the sandbox
The rest of the architecture doesn't exist to them
第45页
The sandbox also acts like a security guard
Knows what the modules are allowed to access and do on the framework
flickr.com/photos/heraklit/169566548/
第46页
Core.register("module-name", function(sandbox){
return { init: function(){
//not sure if I'm allowed... if (sandbox.iCanHazCheezburger()){
alert("thx u"); } },
destroy: function(){ //destructor
}
};
});
第47页
Sandbox Jobs
• Consistency • Security • Communication
第48页
Take the time to design the correct sandbox interface
It can't change later
第49页
Application Architecture
Modules Sandbox Application Core Base Library
第50页
Module
Module
Module
Module
Sandbox
Application Core
Base Library
Module
第51页
Application Core
The application core manages modules That's it
第52页
Application Core
aka Application Controller
第53页
The application core tells a module when it should initialize and when it should shutdown
flickr.com/photos/bootbearwdc/20817093/ flickr.com/photos/bootbearwdc/20810695/
第54页
Core = function(){ var moduleData = {};
return { register: function(moduleId, creator){ moduleData[moduleId] = { creator: creator, instance: null }; },
start: function(moduleId){ moduleData[moduleId].instance = moduleData[moduleId].creator(new Sandbox(this)); moduleData[moduleId].instance.init();
},
} }();
stop: function(moduleId){ var data = moduleData[moduleId]; if (data.instance){ data.instance.destroy(); data.instance = null; }
}
第55页
Core = function(){
return { //more code here...
startAll: function(){ for (var moduleId in moduleData){ if (moduleData.hasOwnProperty(moduleId)){ this.start(moduleId); } }
},
stopAll: function(){ for (var moduleId in moduleData){ if (moduleData.hasOwnProperty(moduleId)){ this.stop(moduleId); } }
},
//more code here... }; }();
第56页
//register modules Core.register("module1", function(sandbox){ /*...*/ }); Core.register("module2", function(sandbox){ /*...*/ }); Core.register("module3", function(sandbox){ /*...*/ }); Core.register("module4", function(sandbox){ /*...*/ });
//start the application by starting all modules Core.startAll();
第57页
The application core manages communication between modules
flickr.com/photos/markhillary/353738538/
第59页
TimelineFilter = {
changeFilter: function(filter){
Timeline.applyFilter(filter);
} };
Tight
Coupling
StatusPoster = {
postStatus: function(status){
Timeline.post(status);
} };
Tight
Coupling
Timeline = {
applyFilter: function(filter){
//implementation
},
post: function(status){
//implementation
}
};
第60页
Core.register("timeline-filter", function(sandbox){
return {
changeFilter: function(filter){
sandbox.notify({
type: "timeline-filter-change",
data: filter
} };
});
Loose Coupling
});
Core.register("status-poster", function(sandbox){
return {
postStatus: function(statusText){
sandbox.notify({
type: "new-status",
data: statusText
}); Loose
} };
Coupling
});
第61页
Core.register("timeline", function(sandbox){
return { init: function(){ sandbox.listen([ "timeline-filter-change", "post-status" ], this.handleNotification, this); },
Loose Coupling
}; });
handleNotification: function(note){ switch(note.type){ case "timeline-filter-change": this.applyFilter(note.data); return; case "post-status": this.post(note.data); return; }
}
第62页
When modules are loosely coupled, removing a module doesn't break the others
No direct access to another module = no breaking should the module disappear
第63页
The application core handles errors
Uses available information to determine best course of action
flickr.com/photos/brandonschauer/3168761995/
第64页
Core = function(){
var moduleData = {}, debug = false;
function createInstance(moduleId){ var instance = moduleData[moduleId].creator(new Sandbox(this)), name, method;
if (!debug){ for (name in instance){ method = instance[name]; if (typeof method == "function"){ instance[name] = function(name, method){ return function(){ try { return method.apply(this, arguments);} catch(ex) {log(1, name + "(): " + ex.message);} }; }(name, method); } }
}
return instance; }
//more code here
}();
第65页
Learn more
http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation
第66页
Application Core Jobs
• Manage module lifecycle • Enable inter-module communication • General error handling • Be extensible
第67页
Why not?
第68页
Web applications change
Often in ways that you couldn't possibly anticipate
第69页
Plan for extension
第70页
flickr.com/photos/pointnshoot/1443575327/
Anything built for extension can never be obsolete
Extensions augment the capabilities of the core to keep it relevant and useful
第71页
Module
Module
Module
Module
Extension
Sandbox
Application Core
Base Library
Module
Extension
第72页
What Extensions?
• Error handling • Ajax communication • New module capabilities • General utilities • Anything!
第73页
Ajax communication comes in different forms Tends to be tied to something available on the server
第74页
Request format Response format
Entrypoint
Three parts must be in sync for Ajax to work Modules shouldn't know anything about any of this
第75页
Module
Module
Module
Module
Extension
Sandbox
Application Core
Base Library
Module
Ajax/XML
第76页
GET ?name=value&name=value
Request format
/ajax
Entrypoint
Response format
<response> <status>ok|error</status> <data> <results> <result name="..." /> <result name="..." /> </results> </data>
</response>
第77页
Entrypoint
var xhr = new XMLHttpRequest();
xhr.open("get", "/ajax?name=value", true); Request
xhr.onreadystatechange = function(){
format
if (xhr.readyState == 4){
if (xhr.status == 200 || xhr.status == 304){
var statusNode = xhr.responseXML.getElementsByTagName("status")[0],
dataNode = xhr.responseXML.getElementsByTagName("data")[0];
if (statusNode.firstChild.nodeValue == "ok"){ handleSuccess(processData(dataNode));
} else { handleFailure();
}
Response format
} else { handleFailure();
} }
};
xhr.send(null); Basic implementation Lowest-level Ajax with XMLHttpRequest
第78页
Library reference
Entrypoint
var id = Y.io("/ajax?name=value", { method: "get",
Request
on: {
format
success: function(req){
var statusNode = req.responseXML.getElementsByTagName("status")[0],
dataNode = req.responseXML.getElementsByTagName("data")[0];
if (statusNode.firstChild.nodeValue == "ok"){
handleSuccess(processData(dataNode)); } else {
Response
handleFailure();
format
}
},
failure: function(req){
handleFailure();
}
}
});
Implementation using a library
Hides some of the ugliness but still tightly coupled to Ajax implementation
第79页
var id = sandbox.request({ name: "value" }, { success: function(response){ handleSuccess(response.data); }, failure: function(response){ handleFailure(); }
});
Implementation using sandbox
Passes through to core - hides all Ajax communication details
第80页
Request format Response format
Entrypoint
Ajax extension encapsulates all details Any of these three can change without affecting modules
第81页
GET ?name=value&name=value
Request format
Response format
{ status: "ok|error", data: { results: [ "...", "..." ] }
}
/request
Entrypoint
第82页
Module
Module
Module
Module
Extension
Sandbox
Application Core
Base Library
Module
Ajax/JSON
第83页
Ajax Extension Jobs
• Hide Ajax communication details • Provide common request interface • Provide common response interface • Manage server failures
第84页
Application Architecture
Modules Sandbox Application Core Base Library
第85页
Module
Module
Module
Module
Extension
Sandbox
Application Core
Base Library
Module
Extension
第86页
The base library provides basic functionality Ironic, huh? Base Library
第88页
flickr.com/photos/kartik_m/2724121901/
Most applications are too tightly coupled to the base library
Developers get upset when they can't touch the base library directly
第89页
High-Performance JavaScript, OSCON 2007 Joseph Smarr, Plaxo, Inc.
第90页
Learn more
http://josephsmarr.com/2007/07/25/high-performance-javascript-oscon-2007/
第91页
Ideally, only the application core has any idea what base library is
being used
第92页
Module Module
Module
Sandbox Application
Core Dojo
Module Module
第93页
Module Module
Module
Sandbox Application
Core YUI
Module Module
第94页
Base Library Jobs
• Browser normalization • General-purpose utilities
Parsers/serializers for XML, JSON, etc. Object manipulation DOM manipulation Ajax communication
• Provide low-level extensibility
第95页
Module
Module
Module
Module
Extension Extension
Sandbox
Application Core
Base Library
Module
Extension Extension
第96页
Architecture Knowledge
第97页
Module
Module
Module
Module
Extension Extension
Sandbox
Application Core
Base Library
Module
Extension Extension
第98页
Only the base library knows which browser is being used
No other part of the architecture should need to know
Base Library
第99页
Only the application core knows which base library is being used
No other part of the architecture should need to know
Application Core
Base Library
第100页
Sandbox
Application Core
Only the sandbox knows which application core is being used
No other part of the architecture should need to know
第101页
Module Module
Module Sandbox
Module Module
The modules know nothing except that the sandbox exists
They have no knowledge of one another or the rest of the architecture
第102页
Module
Module
Module
Module
Extension
Sandbox
Application Core
Module
Extension
Extension
Base Library
Extension
No part knows about the web application
第103页
Advantages
第104页
flickr.com/photos/kgoldendragon613/278240446/
Multiple different applications can be created with the same framework
Minimize ramp-up time by reusing existing components
第105页
Each part can be tested separately
You just need to verify that each is doing it's unique job
flickr.com/photos/misocrazy/151021636/
第106页
A scalable JavaScript architecture allows you to replace any block without fear of toppling the tower
flickr.com/photos/aku-ma/2424194422/
第107页
The End
第108页
Etcetera
•My blog:
www.nczonline.net
•Twitter:
@slicknet
•These Slides: slideshare.net/nzakas