Date post: | 19-May-2015 |
Category: |
Technology |
Upload: | indeedeng |
View: | 2,649 times |
Download: | 3 times |
Building Indeed Resume SearchDavid Tulig
DAVID TULIGTECH LEADJOB SEARCH TEAM
I help people get jobs.
Jobseekers Job
Jobseekers Job
We learned from Job Search
The web evolved
PRINCIPLES
SimpleFastComprehensiveRelevant
PRINCIPLES
SimpleFastComprehensiveRelevant
GOALS
Responsive user experience
javas
javas
javascriptjavascript jqueryjavascript htmljavascript html css
javascript
javascriptjavascript jqueryjavascript htmljavascript html css
Maintainable code
Re-usable components
Separate presentation and logic
Fast
GOALS
Responsive UXMaintainable codeFast
Library support
Google Closure Tools
Closure Library
array asserts async color crypt cssom date disposable dom ds editor events format functions fx gears global graphics history i18n iter json locale math messaging module net positioning proto proto2 pubsub result soy spell stats storage string structs style testing text tweak ui userAgent vec
array asserts async color crypt cssom date disposable dom ds editor events format functions fx gears global graphics history i18n iter json locale math messaging module net positioning proto proto2 pubsub result soy spell stats storage string structs style testing text tweak ui userAgent vec
Modular and independent
Application
dom events style
Application
dom events style
arrayobject
Application
dom events style
arrayobject string
Application
dom events style
arrayobject string
Application
dom events style
arrayobject string
Application
dom
events
style
array
object
string
goog.provide('indeed.Search');
goog.require('goog.dom');goog.require('goog.events');
/* Search */indeed.Search.validateLocation =
function() {...};
goog.provide('indeed.Search');
goog.require('goog.dom');goog.require('goog.events');
/* Search */indeed.Search.validateLocation =
function() {...};
Application
dom events style
arrayobject string
Unit testing
Closure Templates
Closure Compiler
whitespace_only
simple_optimizations
advanced_optimizations
Type checking
Unused code removal
/** Alias for getElementById. If a DOM node ispassed in then we just return */goog.dom.getElement = function(element) {...};
/** Looks up elements by both tag and class name,using browser native functions */goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {...};
/** Returns an array of all the elementswith the provided className. */goog.dom.getElementsByClass = function(className, opt_el) {...};
/** Returns the first element with the provided className. */goog.dom.getElementByClass = function(className, opt_el) {...};
/** Alias for getElementById. If a DOM node ispassed in then we just return */goog.dom.getElement = function(element) {...};
/** Looks up elements by both tag and class name,using browser native functions */goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {...};
/** Returns the first element with the provided className. */goog.dom.getElementByClass = function(className, opt_el) {...};
/** Alias for getElementById. If a DOM node ispassed in then we just return */goog.dom.getElement = function(element) {...};
/** Looks up elements by both tag and class name,using browser native functions */goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {...};
/** Returns an array of all the elementswith the provided className. */goog.dom.getElementsByClass = function(className, opt_el) {...};
/** Returns the first element with the provided className. */goog.dom.getElementByClass = function(className, opt_el) {...};
/** Alias for getElementById. If a DOM node ispassed in then we just return */goog.dom.getElement = function(element) {...};
/** Looks up elements by both tag and class name,using browser native functions */goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {...};
/** Returns the first element with the provided className. */goog.dom.getElementByClass = function(className, opt_el) {...};
/** Alias for getElementById. If a DOM node ispassed in then we just return */goog.dom.getElement = function(element) {...};
/** Returns an array of all the elementswith the provided className. */goog.dom.getElementsByClass = function(className, opt_el) {...};
Aggressive renaming
Let's build Resume Search
Resume Search architecture
Browser Server
q=javasc
Browser Server
q=javasc
{ "suggestions" : [ "javascript", "javascript jquery", "javascript html", "javascript html css", "javascript ajax" ]}
AutoCompleteAutoComplete
Search
Preview
AutocompleteSearchPreview
LocationAutocomplete
Search Preview
QueryAutocomplete
A Possible Approach: Tightly Coupled Modules
Use events
{ "suggestions" : [ "javascript", "javascript jquery", "javascript html", "javascript html css", "javascript ajax" ]}
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
1. N
ew te
xt "j
avas
c"
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
2. Get suggestions
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
3. Suggestions
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
4. Render
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
6. Click on "javascript"
Autocomplete
Text HandlerDrop Down
HandlerRPC Handler
6. S
et te
xt to
"jav
ascr
ipt"
Search App
AutoComplete
Text HandlerDrop Down
Handler
Search
RPC Handler
Search App
AutoComplete
Text HandlerDrop Down
Handler
Search
RPC Handler
Awesome
Search App
AutoComplete
Text HandlerDrop Down
Handler
Search
RPC Handler
Search App
AutoComplete
Text HandlerDrop Down
Handler
Search
RPC Handler
Search App
AutoComplete
Text HandlerDrop Down
Handler
Search
RPC Handler
User interface
Templates
Server or client?
indeed.com/resumes?q=java
indeed.com/resumes?q=java
HTML
Time
indeed.com/resumes?q=java
LOAD JSHTML
Time
indeed.com/resumes?q=java
AJAX RESULTSLOAD JSHTML
indeed.com/resumes?q=java
JS REQ JS RESP AJAX REQ AJAX RESPHTML + DATA AJAX RESULTSLOAD JS
Time
indeed.com/resumes?q=java
JS REQ JS RESPHTML + DATA LOAD JS
indeed.com/resumes?q=java
HTML + RESULTS
Time
indeed.com/resumes?q=java
HTML + RESULTS JS REQ JS RESPLOAD JS
indeed.com/resumes?q=java
HTML + RESULTS JS RESPLOAD JS
Server or client?
Server AND client!
Don't repeat yourself
Closure Templates
template.soy
Closure Template Compilernew TofuRenderer()
template.js
one template. all requests.
/resumes?q=javascript Server Rendering
/resumes?q=javascript Server Rendering
Controller
/resumes?q=javascript
Controller
Model
Server Rendering
/resumes?q=javascript
Controller
Model
new TofuRenderer()
Server Rendering
/resumes?q=javascript
Controller
Model
new TofuRenderer()
HTML
Server Rendering
/instant?q=javascriptClient Rendering
/instant?q=javascript
Controller
Client Rendering
/instant?q=javascript
Controller
Model
Client Rendering
/instant?q=javascript
Controller
Model
JSON
Client Rendering
/instant?q=javascript
Controller
Model
template.js
JSON
Client Rendering
/instant?q=javascript
Controller
Model
template.js
JSON
Client Rendering
HTML
/resumes?q=javascript /instant?q=javascript
Controller
Model
new TofuRenderer()
HTML
template.js
JSON
Don't repeat yourself
Application
Application
Browser
Library
Browser
Library
Browser
Templates
Library
Browser
Templates Application
HTML LIBRARY TEMPLATES APPLICATION
Time
COMBINED
Time
HTML
COMPILED
Time
HTML
Application size
whitespace_only 126k
whitespace_only 126k
simple_optimizations 108k
whitespace_only 126k
simple_optimizations 108k
49k advanced_optimizations
RESUME SEARCH
Re-usable componentsResponsive UXFast initial load
We learned from Resume Search
jobsearch.js
jobsearch.js 41k
jobsearch.js 41k
jobsearch_v2.js 35k
6K MATTERS
6K MATTERS
6k reduction
6K MATTERS
6k reduction546 GB / month
6K MATTERS
6k reduction546 GB / month428 hours / month
david tuligtwitter: @dtulig
indeed.com/resumes
engineering.indeed.com