SlideShare une entreprise Scribd logo
1  sur  96
Télécharger pour lire hors ligne
Scaling A/B testing 
on Netflix.com with 
_________ Alex Liu 
@stinkydofu
data driven 
product development
Test 1 Test 2 Test 3 Test 4 Test 5 Test 6 Test 7 
A 
B 
C 
D 
E 
F 
G 
A 
B 
C 
D 
E 
F 
G 
A 
B 
C 
D 
E 
F 
G 
A 
B 
C 
D 
E 
F 
G 
A 
B 
C 
D 
E 
F 
G 
A 
B 
C 
D 
E 
F 
G 
A 
B 
C 
D 
E 
F 
G
2,097,152 
unique experiences across 
seven tests
hundreds 
of new A/B tests per year
43351892955034 
94860861172181 
85493567650… 
72061153709996
2105 566 685 
templates CSS JS
2.5M 
unique packages 
every week
<html/> 
<link/> 
<script/>
problem: 
conditional dependencies
▶ Templating 
▶ Packaging 
▶ Bonus Round
Templating
payment.dust 
<div id="payments"> 
<input id="first-name"><input id="last-name"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="card-number"><input id="security-code"> 
<select name="month"></select><select name="year"></select> 
<checkbox id="agree-to-terms"/> 
<button>Start Your Trial</button> 
</div>
<input id=“first-name"><input id=“last-name"> 
{@inTest id="10" cell=“2a"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class=“payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
{@inTest id="10" cell=“3"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
{@inTest id="10" cell=“4"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
{@inTest id="10" cell=“5"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
<checkbox id="agree-to-terms"></checkbox> 
<button>Start Your Trial</button> 
</div>
payment.dust 
if if if if if 
Control Cell 2 Cell 3 Cell 4 Cell 5
<div class="payment-types"> 
<div id="CC"> 
{> payment_type_cc /} 
</div> 
<div id="DD"> 
{> payment_type_dd /} 
</div> 
</div>
payment.dust 
if if if if if 
Control Cell 2 Cell 3 Cell 4 Cell 5 
payment_type_cc.dust payment_type_dd.dust
payment.dust 
Control.dust 
if if if if if 
Cell2.dust Cell3.dust Cell4.dust Cell5.dust 
payment_type_cc.dust payment_type_dd.dust
<div id="payments"> 
<input id="first-name"> 
<input id="last-name"> 
{> payment_method /} 
<input type="checkbox" id="terms"> 
<button>Start Your Trial</button> 
</div>
payment.dust 
? 
payment.json 
Control.dust Cell2.dust Cell3.dust Cell4.dust Cell5.dust 
payment_type_cc.dust payment_type_dd.dust
payment.json 
{ 
"rules": [], 
"templateName": "control" 
}, 
{ 
"rules": ["PaymentTest(2)"], 
"templateName": "payment_cell2" 
}, 
{ 
"rules": ["PaymentTest(3)"], 
"templateName": "payment_cell3" 
}, 
{ 
"rules": ["PaymentTest(4)"], 
"templateName": "payment_cell4" 
}, 
{ 
"rules": ["PaymentTest(5)"], 
"templateName": "payment_cell5" 
}
require('nf-rule-infrastructure')
anatomy of a rule 
var Rule = require('nf-rule-infrastructure'), 
PaymentTest; 
PaymentTest = new Rule('PaymentTest', function(context, params, cb) { 
var test = context.abtests.get(10); 
cb(test && test.cell(params.id)); 
}); 
module.exports = PaymentTest;
require('nf-template-resolver')
payment.dust dustjs partial
resolver payment.json 
(mappings) 
rule
rules 
control.dust 
cell2.dust 
cell3.dust
payment.dust dustjs resolver
<input id=“first-name"><input id=“last-name"> 
{@inTest id="10" cell=“2a"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class=“payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
{@inTest id="10" cell=“3"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
{@inTest id="10" cell=“4"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
{@inTest id="10" cell=“5"} 
<div class="payment-types"> 
<div id="CC"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id=“card-number"><input id=“security-code”> 
</div> 
<div id="DD"> 
<span class="payment-logos"> 
<img src="logo1.png"><img src="logo2.png"> 
<img src="logo3.png"><img src="logo4.png"> 
</span> 
<input id="CPF"><input id="bank-name"> 
<input id="branch-number"><input id="account-number"> 
<input id="digit"> 
</div> 
</div> 
{/@inTest} 
<checkbox id="agree-to-terms"></checkbox> 
<button>Start Your Trial</button> 
</div>
<div id="payments"> 
<input id="first-name"> 
<input id="last-name"> 
{> payment_method /} 
<input type="checkbox" id="terms"> 
<button>Start Your Trial</button> 
</div>
Wins 
▶ combine rules 
▶ improve template legibility 
▶ increase template reuse
▶ Templating 
▶ Packaging 
▶ Bonus Round
Packaging
everything 
is a module
oldSearch 
app.js 
newSearch 
dep1 dep2 dep3 dep4 dep5 
sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
oldSearch 
app.js 
newSearch 
dep1 dep2 dep3 dep4 dep5 
sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
app.js 
import jquery from 'jquery'; 
import oldSearch from 'oldSearch'; 
import newSearch from 'newSearch'; 
export ...
oldSearch 
app.js 
newSearch 
dep1 dep2 dep3 dep4 dep5 
sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
685 files…? 
2.5M packages…?
oldSearch 
app.js 
newSearch 
dep1 dep2 dep3 dep4 dep5 
sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
problem: 
conditional dependencies
build request
require('nf-include-when')
oldSearch.js 
/* 
* @includewhen rule.notInNewSearch 
*/
newSearch.js 
/* 
* @includewhen rule.inNewSearch 
*/
anatomy of a rule 
var Rule = require('nf-rule-infrastructure'), 
inNewSearch; 
inNewSearch = new Rule('inNewSearch', function(context, cb) { 
var test = context.abtests.get(1534); 
cb(test && test.cell(1)); 
}); 
module.exports = inNewSearch;
require('nf-asset-registry')
app.js 
import jquery from 'jquery'; 
import oldSearch from 'oldSearch'; 
import newSearch from 'newSearch'; 
export ...
app.js 
jquery 
oldSearch.js 
newSearch.js 
registry
"app.js": { 
"deps": [ 
"jquery", 
"oldSearch.js", 
"newSearch.js", 
], 
"depsFull": [ 
"jquery", 
"oldSearchDep2.js", 
"oldSearchDep1.js", 
"oldSearch.js", 
"newSearchDep2.js", 
"newSearchDep1.js", 
"newSearch.js" 
] 
}
"newSearch.js": { 
"rule": "inNewSearch", 
"deps": [ 
"jquery", 
"newSearchDep2.js", 
"newSearchDep1.js", 
], 
"depsFull": [ 
"jquery", 
"newSearchSubDep3.js", 
"newSearchSubDep2.js" 
"newSearchSubDep1.js" 
"newSearchDep2.js", 
"newSearchDep1.js" 
] 
} 
nf-include-when
require('nf-packager')
var packager = require('nf-packager'), 
includeWhen = require('nf-include-when'), 
registries = require('nf-asset-registry'); 
function getScriptUrl() 
return packager.getPackageDefinition('app.js', 
registries, 
includeWhen); 
}
"app.js": { 
"deps": [ 
"jquery", 
"oldSearch.js", 
"newSearch.js", 
], 
"depsFull": [ 
"jquery", 
"oldSearchDep2.js", 
"oldSearchDep1.js", 
"oldSearch.js", 
"newSearchDep2.js", 
"newSearchDep1.js", 
"newSearch.js" 
], 
"fileSize": "4.41 kB", 
"fileSizeFull": "120.52 kB" 
} 
Step 1: 
Get the full dependency tree for the 
requested package from the registry.
[ 
"jquery", /* no rule */ 
"oldSearchDep2.js", /* no rule */ 
"oldSearchDep1.js", /* no rule */ 
"oldSearch.js", /* rules.notInNewSearch */ 
"newSearchDep2.js", /* no rule */ 
"newSearchDep1.js”, /* no rule */ 
"newSearch.js" /* rules.inNewSearch */ 
] 
Step 2: 
Determine which files have rules.
[ 
"jquery", /* no rule */ 
"oldSearchDep2.js", /* no rule */ 
"oldSearchDep1.js", /* no rule */ 
"oldSearch.js", /* rules.notInNewSearch */ 
"newSearchDep2.js", /* no rule */ 
"newSearchDep1.js”, /* no rule */ 
"newSearch.js" /* rules.inNewSearch */ 
] 
Step 3: 
Run the rules. Filter out all deps that 
resolved false. 
✓
[ 
"jquery", /* no rule */ 
"oldSearchDep2.js", /* no rule */ 
"oldSearchDep1.js", /* no rule */ 
"oldSearch.js", /* rules.notInNewSearch */ 
"newSearchDep2.js", /* no rule */ 
"newSearchDep1.js”, /* no rule */ 
"newSearch.js" /* rules.inNewSearch */ 
] 
Step 4: 
Filter out all extraneous 
sub deps. 
✓
Step 5: 
Concatenate the files. 
[ 
"jquery", /* no rule */ 
"newSearchDep2.js", /* no rule */ 
"newSearchDep1.js”, /* no rule */ 
"newSearch.js" /* rules.inNewSearch */ 
]
build 
javascript 
registry
request registry 
packager rules
Wins 
▶ leverage build time tools 
▶ leverage the server 
▶ divide and conquer with modules
▶ Templating 
▶ Packaging 
▶ Bonus Round
Bonus Round
be creative 
with the registry
"account/bb/models/ratingHistoryModel.js": { 
"rule": null, 
"deps": [...], 
"depsFull": [...], 
"depsCount": { 
"underscore": 2, 
"backbone": 1, 
"jquery": 2, 
"common/requirejs-plugins.js": 4, 
"requirejs-text": 4, 
"utils/contextData.js": 1, 
"common/nfNamespace.js": 1 
}, 
"hash": "dd23b163", 
"fileSize": "1.21 kB", 
"fileSizeFull": "173.04 kB" 
} 
dependency 
counting 
dependency 
pruning 
file sizes
@import modules 
@import (reference) "/common/_nf_defs.less"; 
@import (reference) "/member/memberCore.less"; 
@import (reference) "/components/menu.less"; 
@import (reference) "/components/breadcrumbs.less";
"account/containerResponsive.css": { 
"rule": null, 
"deps": [...], 
"depsFull": [...], 
"depsCount": [...], 
"hash": "65a431f3", 
"fileSize": "709 B", 
"fileSizeFull": "709 B", 
"css": { 
"selectors": 8, 
"declarationBlocks": 6, 
"declarations": 17, 
"mediaQueries": 3 
} 
} 
css 
analysis
the 
best part
"cache": { 
"account/pin.js": "define('account/pin.js', ['member/memberC…", 
"account/bb/models/changePlanModel.js": "define('account/b…", 
"account/bb/models/ratingHistoryModel.js": "define('account…", 
"account/bb/models/viewingActivityModel.js": "define('account…", 
"account/bb/views/changePlanView.js": "define('account/bb/vi…", 
"account/bb/views/changePlanView.js": "define('account/bb/vi…", 
"account/bb/views/emailSubView.js": "define('account/bb/views…", 
"account/bb/views/viewingActivityView.js": "define('account…", 
"common/UITracking.js": "define('common/UITracking.js, ['me…", 
"common/UITrackingOverlay.js": "define('common/UITrackingOve…", 
… 
… 
…
templates templates 
mappings 
javascript 
css 
mappings 
javascript 
css
templates 
mappings 
javascript 
css 
UI Bundle
deploy UI bundles 
anytime
never 
touch the file system
< 5ms 
package response times
Wins 
▶ static analysis FTW 
▶ independent UI deployments 
▶ requests never touch the fs 
▶ fast package response times
Our Learnings
learn by doing
fail fast 
move faster
“I have not failed. 
I’ve just found 10,000 ways 
that won’t work.” 
Thomas Edison
simplify
thank you 
Alex Liu 
@stinkydofu
questions? 
Alex Liu 
@stinkydofu

Contenu connexe

Dernier

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 

Dernier (20)

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 

En vedette

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

En vedette (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

[HTML5DevConf2014] Scaling AB Testing on Netflix.com with Node.js

  • 1. Scaling A/B testing on Netflix.com with _________ Alex Liu @stinkydofu
  • 2. data driven product development
  • 3.
  • 4.
  • 5.
  • 6.
  • 7. Test 1 Test 2 Test 3 Test 4 Test 5 Test 6 Test 7 A B C D E F G A B C D E F G A B C D E F G A B C D E F G A B C D E F G A B C D E F G A B C D E F G
  • 8. 2,097,152 unique experiences across seven tests
  • 9. hundreds of new A/B tests per year
  • 11. 2105 566 685 templates CSS JS
  • 12. 2.5M unique packages every week
  • 15.
  • 16. ▶ Templating ▶ Packaging ▶ Bonus Round
  • 18.
  • 19. payment.dust <div id="payments"> <input id="first-name"><input id="last-name"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="card-number"><input id="security-code"> <select name="month"></select><select name="year"></select> <checkbox id="agree-to-terms"/> <button>Start Your Trial</button> </div>
  • 20.
  • 21.
  • 22. <input id=“first-name"><input id=“last-name"> {@inTest id="10" cell=“2a"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class=“payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} {@inTest id="10" cell=“3"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} {@inTest id="10" cell=“4"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} {@inTest id="10" cell=“5"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} <checkbox id="agree-to-terms"></checkbox> <button>Start Your Trial</button> </div>
  • 23. payment.dust if if if if if Control Cell 2 Cell 3 Cell 4 Cell 5
  • 24. <div class="payment-types"> <div id="CC"> {> payment_type_cc /} </div> <div id="DD"> {> payment_type_dd /} </div> </div>
  • 25. payment.dust if if if if if Control Cell 2 Cell 3 Cell 4 Cell 5 payment_type_cc.dust payment_type_dd.dust
  • 26. payment.dust Control.dust if if if if if Cell2.dust Cell3.dust Cell4.dust Cell5.dust payment_type_cc.dust payment_type_dd.dust
  • 27. <div id="payments"> <input id="first-name"> <input id="last-name"> {> payment_method /} <input type="checkbox" id="terms"> <button>Start Your Trial</button> </div>
  • 28. payment.dust ? payment.json Control.dust Cell2.dust Cell3.dust Cell4.dust Cell5.dust payment_type_cc.dust payment_type_dd.dust
  • 29. payment.json { "rules": [], "templateName": "control" }, { "rules": ["PaymentTest(2)"], "templateName": "payment_cell2" }, { "rules": ["PaymentTest(3)"], "templateName": "payment_cell3" }, { "rules": ["PaymentTest(4)"], "templateName": "payment_cell4" }, { "rules": ["PaymentTest(5)"], "templateName": "payment_cell5" }
  • 31. anatomy of a rule var Rule = require('nf-rule-infrastructure'), PaymentTest; PaymentTest = new Rule('PaymentTest', function(context, params, cb) { var test = context.abtests.get(10); cb(test && test.cell(params.id)); }); module.exports = PaymentTest;
  • 37. <input id=“first-name"><input id=“last-name"> {@inTest id="10" cell=“2a"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class=“payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} {@inTest id="10" cell=“3"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} {@inTest id="10" cell=“4"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} {@inTest id="10" cell=“5"} <div class="payment-types"> <div id="CC"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id=“card-number"><input id=“security-code”> </div> <div id="DD"> <span class="payment-logos"> <img src="logo1.png"><img src="logo2.png"> <img src="logo3.png"><img src="logo4.png"> </span> <input id="CPF"><input id="bank-name"> <input id="branch-number"><input id="account-number"> <input id="digit"> </div> </div> {/@inTest} <checkbox id="agree-to-terms"></checkbox> <button>Start Your Trial</button> </div>
  • 38. <div id="payments"> <input id="first-name"> <input id="last-name"> {> payment_method /} <input type="checkbox" id="terms"> <button>Start Your Trial</button> </div>
  • 39. Wins ▶ combine rules ▶ improve template legibility ▶ increase template reuse
  • 40. ▶ Templating ▶ Packaging ▶ Bonus Round
  • 42. everything is a module
  • 43.
  • 44.
  • 45. oldSearch app.js newSearch dep1 dep2 dep3 dep4 dep5 sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
  • 46. oldSearch app.js newSearch dep1 dep2 dep3 dep4 dep5 sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
  • 47. app.js import jquery from 'jquery'; import oldSearch from 'oldSearch'; import newSearch from 'newSearch'; export ...
  • 48. oldSearch app.js newSearch dep1 dep2 dep3 dep4 dep5 sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
  • 49.
  • 50. 685 files…? 2.5M packages…?
  • 51. oldSearch app.js newSearch dep1 dep2 dep3 dep4 dep5 sub-dep sub-dep sub-dep sub-dep sub-dep sub-dep
  • 53.
  • 56. oldSearch.js /* * @includewhen rule.notInNewSearch */
  • 57. newSearch.js /* * @includewhen rule.inNewSearch */
  • 58. anatomy of a rule var Rule = require('nf-rule-infrastructure'), inNewSearch; inNewSearch = new Rule('inNewSearch', function(context, cb) { var test = context.abtests.get(1534); cb(test && test.cell(1)); }); module.exports = inNewSearch;
  • 60. app.js import jquery from 'jquery'; import oldSearch from 'oldSearch'; import newSearch from 'newSearch'; export ...
  • 61. app.js jquery oldSearch.js newSearch.js registry
  • 62. "app.js": { "deps": [ "jquery", "oldSearch.js", "newSearch.js", ], "depsFull": [ "jquery", "oldSearchDep2.js", "oldSearchDep1.js", "oldSearch.js", "newSearchDep2.js", "newSearchDep1.js", "newSearch.js" ] }
  • 63. "newSearch.js": { "rule": "inNewSearch", "deps": [ "jquery", "newSearchDep2.js", "newSearchDep1.js", ], "depsFull": [ "jquery", "newSearchSubDep3.js", "newSearchSubDep2.js" "newSearchSubDep1.js" "newSearchDep2.js", "newSearchDep1.js" ] } nf-include-when
  • 65. var packager = require('nf-packager'), includeWhen = require('nf-include-when'), registries = require('nf-asset-registry'); function getScriptUrl() return packager.getPackageDefinition('app.js', registries, includeWhen); }
  • 66. "app.js": { "deps": [ "jquery", "oldSearch.js", "newSearch.js", ], "depsFull": [ "jquery", "oldSearchDep2.js", "oldSearchDep1.js", "oldSearch.js", "newSearchDep2.js", "newSearchDep1.js", "newSearch.js" ], "fileSize": "4.41 kB", "fileSizeFull": "120.52 kB" } Step 1: Get the full dependency tree for the requested package from the registry.
  • 67. [ "jquery", /* no rule */ "oldSearchDep2.js", /* no rule */ "oldSearchDep1.js", /* no rule */ "oldSearch.js", /* rules.notInNewSearch */ "newSearchDep2.js", /* no rule */ "newSearchDep1.js”, /* no rule */ "newSearch.js" /* rules.inNewSearch */ ] Step 2: Determine which files have rules.
  • 68. [ "jquery", /* no rule */ "oldSearchDep2.js", /* no rule */ "oldSearchDep1.js", /* no rule */ "oldSearch.js", /* rules.notInNewSearch */ "newSearchDep2.js", /* no rule */ "newSearchDep1.js”, /* no rule */ "newSearch.js" /* rules.inNewSearch */ ] Step 3: Run the rules. Filter out all deps that resolved false. ✓
  • 69. [ "jquery", /* no rule */ "oldSearchDep2.js", /* no rule */ "oldSearchDep1.js", /* no rule */ "oldSearch.js", /* rules.notInNewSearch */ "newSearchDep2.js", /* no rule */ "newSearchDep1.js”, /* no rule */ "newSearch.js" /* rules.inNewSearch */ ] Step 4: Filter out all extraneous sub deps. ✓
  • 70. Step 5: Concatenate the files. [ "jquery", /* no rule */ "newSearchDep2.js", /* no rule */ "newSearchDep1.js”, /* no rule */ "newSearch.js" /* rules.inNewSearch */ ]
  • 73. Wins ▶ leverage build time tools ▶ leverage the server ▶ divide and conquer with modules
  • 74. ▶ Templating ▶ Packaging ▶ Bonus Round
  • 76. be creative with the registry
  • 77. "account/bb/models/ratingHistoryModel.js": { "rule": null, "deps": [...], "depsFull": [...], "depsCount": { "underscore": 2, "backbone": 1, "jquery": 2, "common/requirejs-plugins.js": 4, "requirejs-text": 4, "utils/contextData.js": 1, "common/nfNamespace.js": 1 }, "hash": "dd23b163", "fileSize": "1.21 kB", "fileSizeFull": "173.04 kB" } dependency counting dependency pruning file sizes
  • 78. @import modules @import (reference) "/common/_nf_defs.less"; @import (reference) "/member/memberCore.less"; @import (reference) "/components/menu.less"; @import (reference) "/components/breadcrumbs.less";
  • 79. "account/containerResponsive.css": { "rule": null, "deps": [...], "depsFull": [...], "depsCount": [...], "hash": "65a431f3", "fileSize": "709 B", "fileSizeFull": "709 B", "css": { "selectors": 8, "declarationBlocks": 6, "declarations": 17, "mediaQueries": 3 } } css analysis
  • 81. "cache": { "account/pin.js": "define('account/pin.js', ['member/memberC…", "account/bb/models/changePlanModel.js": "define('account/b…", "account/bb/models/ratingHistoryModel.js": "define('account…", "account/bb/models/viewingActivityModel.js": "define('account…", "account/bb/views/changePlanView.js": "define('account/bb/vi…", "account/bb/views/changePlanView.js": "define('account/bb/vi…", "account/bb/views/emailSubView.js": "define('account/bb/views…", "account/bb/views/viewingActivityView.js": "define('account…", "common/UITracking.js": "define('common/UITracking.js, ['me…", "common/UITrackingOverlay.js": "define('common/UITrackingOve…", … … …
  • 82. templates templates mappings javascript css mappings javascript css
  • 84.
  • 85. deploy UI bundles anytime
  • 86. never touch the file system
  • 87. < 5ms package response times
  • 88. Wins ▶ static analysis FTW ▶ independent UI deployments ▶ requests never touch the fs ▶ fast package response times
  • 91. fail fast move faster
  • 92. “I have not failed. I’ve just found 10,000 ways that won’t work.” Thomas Edison
  • 94.
  • 95. thank you Alex Liu @stinkydofu
  • 96. questions? Alex Liu @stinkydofu