SlideShare una empresa de Scribd logo
1 de 67
Descargar para leer sin conexión
Engineering the New Profile
Josh Clemm
Tech Lead for the New Profile
March 2013 | LinkedIn
David Fleming!
Senior Product Manager at Zoomjax!
San Francisco Bay Area | Software!
!
Previous!
Education!
Golden Phase, FixDex!
Silicon Valley Business Academy!
Let's compare...
Really a brand new product
Refreshed Look & Feel
Simplified Design
Surfaced New &
Interactive
Modules
New Data Insights
New Features
 Improved in-line
editing experience
Modules with In-line
searching &
pagination
The New Profile - Goals
●  Represent your entire professional identity
o  Not just your resume
o  Activity, Groups, Following, Connections,
Insights about you and your network
The New Profile - Goals
●  Represent your entire professional identity
o  Not just your resume
o  Activity, Groups, Following, Connections,
Insights about you and your network

●  Needs to be more interactive
o  Keep users engaged on the page
o  Inline pagination, editing, searching
The New Profile - Goals
●  Represent your entire professional identity
o  Not just your resume
o  Activity, Groups, Following, Connections,
Insights about you and your network

●  Needs to be more interactive
o  Keep users engaged on the page
o  Inline pagination, editing, searching

●  Needs to be fluid, flexible, fast
o  Progressive rendering
o  Maintain high performance
So how did we achieve
all that?
Using a lot of Technologies
And in particular...
Let's look at our High Level
Frontend Architecture
Groups
Content
Service
Connections
Content
Service
Profile
Content
Service
Client/Browser
 CDN
Load Balancer
SCDS
Fizzy
Profile Web
App
Profile
Content
Service
Profile Web
App
Connections
Content
Service
Groups
Content
Service
Dust/JS/CSS
Server
Retrieve Data
Models from
Mid-tier
/profile/view?id=32
top_card.tl,
background.tl
/profile/topcard
 /profile/background
Groups
Content
Service
Connections
Content
Service
Profile
Content
Service
Client/Browser
 CDN
Load Balancer
SCDS
Fizzy
Profile Web
App
Profile
Content
Service
Profile Web
App
Connections
Content
Service
Groups
Content
Service
Dust/JS/CSS
Server
Retrieve Data
Models
/profile/view?id=32
top_card.tl,
background.tl
/profile/topcard
 /profile/background
Our new
architecture
uses new tech
at all layers
Groups
Content
Service
Connections
Content
Service
Profile
Content
Service
Client/Browser
 CDN
Load Balancer
SCDS
Fizzy
Profile Web
App
Profile
Content
Service
Profile Web
App
Connections
Content
Service
Groups
Content
Service
Dust/JS/CSS
Server
Retrieve Data
Models
/profile/view?id=32
top_card.tl,
background.tl
/profile/topcard
 /profile/background
Let's start at the bottom
with Mappers
Mappers - JSON endpoints
●  Convert data models from mid-tier services
into JSON
●  Each have an unique endpoint URL 
( /profile/positions?id=42 )
Positions
Mapper
JSON
"positions": [{
"position": {"id:
{}"},
]}
Biz Profile
Model
Profile
Model
Rich Media
Rest Model
References
Model
Profile Flex
Model
Mappers - an example
public class PictureMapper extends ProfileParametersAwareMapper!
{!
private PictureContentMap pictureContentMap;!
private static final int ZOOMABLE_DIMENSION = 225;!
!
@Override!
public void doService()!
{!
PictureContentModel picCM = getContent(PictureContentModel.class); //declare content needs!
picCM.criteria().setId(getVieweeId()); //supply any input params!
!
assemble(); //invoke framework to retrieve declared content!
!
if (isResolvedWithoutErrors(picCM))!
{!
//all went well, create new content map to hold output (JavaBean-like objects)!
pictureContentMap = ContentMap.proxyNew(PictureContentMap.class);!
!
Integer pictureWidth = picCM.getPictureWidth(); !
pictureContentMap.setIsZoomable(pictureWidth >= ZOOMABLE_DIMENSION);!
!
if(pictureWidth != null && pictureWidth > 0)!
{!
pictureContentMap.setWidth(pictureWidth);!
pictureContentMap.setHeight(picCM.getPictureHeight());!
}!
pictureContentMap.setPictureID(picCM.getPictureID());!
}!
}!
// tell framework to add our map to final output (uses Jackson to process into JSON)!
addOutput(pictureContentMap);!
}!
1!
2!
3!
4!
5!
6!
7!
8!
9!
10!
11!
12!
13!
14!
15!
16!
17!
18!
19!
20!
21!
22!
23!
24!
25!
26!
27!
28!
29!
30!
31!
32!
Mappers - an example
public class PictureMapper extends ProfileParametersAwareMapper!
{!
private PictureContentMap pictureContentMap;!
private static final int ZOOMABLE_DIMENSION = 225;!
!
@Override!
public void doService()!
{!
PictureContentModel picCM = getContent(PictureContentModel.class); //declare content needs!
picCM.criteria().setId(getVieweeId()); //supply any input params!
!
assemble(); //invoke framework to retrieve declared content!
!
if (isResolvedWithoutErrors(picCM))!
{!
//all went well, create new content map to hold output (JavaBean-like objects)!
pictureContentMap = ContentMap.proxyNew(PictureContentMap.class);!
!
Integer pictureWidth = picCM.getPictureWidth(); !
pictureContentMap.setIsZoomable(pictureWidth >= ZOOMABLE_DIMENSION);!
!
if(pictureWidth != null && pictureWidth > 0)!
{!
pictureContentMap.setWidth(pictureWidth);!
pictureContentMap.setHeight(picCM.getPictureHeight());!
}!
pictureContentMap.setPictureID(picCM.getPictureID());!
}!
}!
// tell framework to add our map to final output (uses Jackson to process into JSON)!
addOutput(pictureContentMap);!
}!
1!
2!
3!
4!
5!
6!
7!
8!
9!
10!
11!
12!
13!
14!
15!
16!
17!
18!
19!
20!
21!
22!
23!
24!
25!
26!
27!
28!
29!
30!
31!
32!
Declare the data you need
Set the data you want
coming back as JSON
Mappers - features
●  Modular
o  A single mapper can retrieve data for a section
§  Positions, Educations, Groups, etc. 

●  Reusable & Combinable
o  Mappers can be used more than once
§  Positions Mapper is used for Positions section and the
positions part of Top Card

o  You can Aggregate Mappers under a common
root element and a new URL endpoint
Profile's Many Mappers
●  Each section on Profile has either a single Mapper
or Aggregated Mapper (like Top Card) for its data
Profile's Many Mappers
●  Each section on Profile has either a single Mapper
or Aggregated Mapper (like Top Card) for its data
Summary
Mapper
Positions
Mapper
Educations
Mapper
Picture
Mapper
Top Card
Mapper
"TopCard": {
"positions": {},
"educations":{},
"picture":{}}
Profile Web App
Connections
Mapper
JSON
"Summary":
{ "summary":
"I'm an
experienced..."}
JSON
So we have these Mappers that
return JSON for each section.

Who calls each one?
Groups
Content
Service
Connections
Content
Service
Profile
Content
Service
Client/Browser
 CDN
Load Balancer
SCDS
Fizzy
Profile Web
App
Profile
Content
Service
Profile Web
App
Connections
Content
Service
Groups
Content
Service
Dust/JS/CSS
Server
Retrieve Data
Models
/profile/view?id=32
top_card.tl,
background.tl
/profile/topcard
 /profile/background
Fizzy - the UI aggregator
Fizzy
●  Fizzy is an UI aggregator in 2 parts:
o  Fizzy Server fetches the content you
want
o  Fizzy Client renders it when ready

●  Your base page defines its structure and
which UI components it needs (called
"embeds")
*Fizzy Server is an Apache Traffic Server Plugin, Fizzy Client is a JS library
Profile's Embeds
Top Card Embed
Activity Embed
Embed
Embed
Embed
Embed
Yet another embed
Profile's Embeds in code
<html>
<body>
...
<div id=“wrapper”>
<div id=“profile”>
<script type=“embed” fs-id=“topcard” fs-uri=“/profile/topcard”/>
<script type=“embed” fs-id=“background” fs-uri=“/profile/background”/>
...
<script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/>
</div>
<div id=“insights”>
<script type=“embed” fs-id=“people_you_may_know” fs-uri=“/profile/pymk”/>
<script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/>
...
<script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/>
</div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Profile's Embeds in code
<html>
<body>
...
<div id=“wrapper”>
<div id=“profile”>
<script type=“embed” fs-id=“topcard” fs-uri=“/profile/topcard”/>
<script type=“embed” fs-id=“background” fs-uri=“/profile/background”/>
...
<script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/>
</div>
<div id=“insights”>
<script type=“embed” fs-id=“people_you_may_know” fs-uri=“/profile/pymk”/>
<script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/>
...
<script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/>
</div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Each embed specifies a
Mapper endpoint that
Fizzy will fetch
Fizzy fetches data and sends it
to the browser.

What's rendering the actual
markup?
Groups
Content
Service
Connections
Content
Service
Profile
Content
Service
Client/Browser
 CDN
Load Balancer
SCDS
Fizzy
Profile Web
App
Profile
Content
Service
Profile Web
App
Connections
Content
Service
Groups
Content
Service
Dust/JS/CSS
Server
Retrieve Data
Models
/profile/view?id=32
top_card.tl,
background.tl
/profile/topcard
 /profile/background
You guessed it...
Dust client templates
{Dust} client templates
●  LinkedIn's latest and greatest rendering
layer
●  Logic-less client template language
●  Profile page made up of many* templates
●  Templates + JSON = full markup!
*over 400 actually
{Dust} - what it looks like
<div id="top_card">
<h4>{name}</h4>
<h5>{headline}</h5>
{#info}
<h6>{location} | {industry}</h6>
{/info}
</div>
{
"name": "Frank Stallone",
"headline": "Actor and Less Famous Brother",
"info":{
"location": "Hollywood",
"industry": "Entertainment"
}
}
{Dust} - why it's cool for profile
●  Cached markup in CDNs and browsers
o  Members browse many profiles in a row

●  Very DRY and reusable
o  Improved development speed
o  Templates within templates within templates...
§  date range, degree badge, formatted summary field

●  Super easy to refresh a section on the page
o  Re-render and replace
o  Useful in pagination, inline searching, and inline
editing
{Dust} on profile
<hgroup>
{>"tl/apps/profile/v2/embed/company_logo"/}
<h4>
<a href="{link_title_pivot}" name='title'>{title_highlight|s}</a>
{?selfView}
<span class="edit-tools">
<a class="edit-section">{i18n_Edit}</a>
</span>
{/selfView}
</h4>
<h5>
{?companyName}
{>"tl/apps/profile/v2/embed/company_link" track_param="prof-exp"/}
{/companyName}
</h5>
</hgroup>
<span class="experience-date-locale">
{>"tl/apps/profile/v2/partial/daterange"/}
{! Location !}
{@pre.fmt key="fmt_location" type="geo.region" value="{location}" render="false"/}
{?fmt_location}<span class="locality">{fmt_location}</span>
{:else}
{?locationName}
<span class="locality">{locationName}</span>
{/locationName}
{/fmt_location}
</span>
{>"tl/apps/profile/v2/partial/summary_field" _summary=summary/}
{>"tl/apps/profile/v2/partial/associated_content" trkCodePrefix="exp"/}
{Dust} on profile
<hgroup>
{>"tl/apps/profile/v2/embed/company_logo"/}
<h4>
<a href="{link_title_pivot}" name='title'>{title_highlight|s}</a>
{?selfView}
<span class="edit-tools">
<a class="edit-section">{i18n_Edit}</a>
</span>
{/selfView}
</h4>
<h5>
{?companyName}
{>"tl/apps/profile/v2/embed/company_link" track_param="prof-exp"/}
{/companyName}
</h5>
</hgroup>
<span class="experience-date-locale">
{>"tl/apps/profile/v2/partial/daterange"/}
{! Location !}
{@pre.fmt key="fmt_location" type="geo.region" value="{location}" render="false"/}
{?fmt_location}<span class="locality">{fmt_location}</span>
{:else}
{?locationName}
<span class="locality">{locationName}</span>
{/locationName}
{/fmt_location}
</span>
{>"tl/apps/profile/v2/partial/summary_field" _summary=summary/}
{>"tl/apps/profile/v2/partial/associated_content" trkCodePrefix="exp"/}
Partial templates like this are
used on almost all the
background sections
We have our Mappers, Fizzy,
and Dust templates...

Let's bring it all together.
Feature: Inline Editing
●  Dust + Mappers make this easy
●  Dust templates for view and edit
●  Mappers return just the data we need to refresh
"View" template
"Edit" template
Summary Section
Feature: Inline Editing
●  Dust + Mappers make this easy
●  Dust templates for view and edit
●  Mappers return just the data we need to refresh
"View" template
"Edit" template
Summary Section
When edit link is
clicked, render
"edit" template
Feature: Inline Editing
●  Dust + Mappers make this easy
●  Dust templates for view and edit
●  Mappers return just the data we need to refresh
"View" template
"Edit" template
Summary Section
On submit, our
endpoint sends
back JSON, and
we re-render
Inline editing - Example
Either the "view" or
"edit" template is
shown at a time
Inline editing sounds easy...
●  Issue: Profile data is highly coupled with different
sections.
o  Adding/editing a position needs to be reflected
on Top Card...
o  Deleting a project needs to also be removed
from any associated position...

●  Solution: since we have mappers for each section,
we know which to re-fetch upon a save and
refresh the respective templates
What about pagination, search?
●  Same idea but easier (not coupled with other sections)
●  Mappers can take URL offset params
Switch out a
partial template
containing just list
of profiles
Let's talk performance
High Performance Page
●  Profile is the most trafficked page on
LinkedIn
●  Profile fetches 48+ different types of
content on each page load
o  This content results in 250+ total
downstream calls
High Performance Page
●  Profile is the most trafficked page on
LinkedIn
●  Profile fetches 48+ different types of
content on each page load
o  This content results in 250+ total
downstream calls
Bottom Line: We need to be fast, but
need to consider downstream fanout
High Performance - Parallel Requests
Fizzy
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
In the beginning, Profile had 15
embeds with 15 different endpoints
which is great for speed...
High Performance - Parallel Requests
Fizzy
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
That's a lot of downstream calls, often
requesting the same data too.
Content
Service
Content
Service
High Performance - Parallel Requests
Fizzy
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
and those calls call more and more... until...
High Performance - Parallel Requests
Fizzy
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Profile
App
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
Content
Service
aaaaand the site's down
High Performance - Parallel Requests
●  Tradeoff: Speed vs Scalability
●  15 parallel calls will be fast but with
Profile's load will take down site
High Performance - Parallel Requests
●  Tradeoff: Speed vs Scalability
●  15 parallel calls will be fast but with
Profile's load will take down site
Batched Endpoints to the rescue
Batching Calls to Mappers
Originally, we had
separate endpoints (URIs)
for each embed
<html>
<body>
...
<div id=“wrapper”>
<div id=“profile”>
<script type=“embed” fs-id=“topcard” fs-uri=“/profile/topcard”/>
<script type=“embed” fs-id=“background” fs-uri=“/profile/background”/>
...
<script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/>
</div>
<div id=“insights”>
<script type=“embed” fs-id=“peeps_you_may_know” fs-uri=“/profile/pymk”/>
<script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/>
...
<script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/>
</div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Batching Calls to Mappers
We now tell framework to batch
these two endpoints
(Fizzy knows how to deliver the
right data to the right embed)
<html>
<body>
...
<div id=“wrapper”>
<div id=“profile”>
<script type=“embed” fs-id=“topcard” fs-uri=“/profile/mappers?a=topcard,background”/>
<script type=“embed” fs-id=“background” fs-uri=“/profile/mappers?a=topcard,background”/>
...
<script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/>
</div>
<div id=“insights”>
<script type=“embed” fs-id=“peeps_you_may_know” fs-uri=“/profile/pymk”/>
<script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/>
...
<script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/>
</div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Batching Calls in Profile
●  Today, we use between 3-5 parallel
requests to Profile
●  It's a good balance of speed vs.
scalability
●  Batching requests that need the same
data has the added benefit of less
downstream calls
Progressive Rendering
With parallel fetch, Profile modules render when
ready for improved perceived performance
Progressive Rendering
With parallel fetch, Profile modules render when
ready for improved perceived performance
How else to improve page load
times?
Profiles can be long...
Embed
Embed
Embed
Embed
Embed
Embed
Embed
Profile Page
Optimize for Above the Fold
Embed
Embed
Embed
Embed
Embed
Embed
Embed
Profile Page
The fold
No need
to render
No need
to render
or fetch
Optimize for Above the Fold
●  The New Profile renders above the fold
as fast as we can
o  Deferring everything at the bottom
o  Reduces the static content we need to initially
download
Optimize for Above the Fold
●  The New Profile renders above the fold
as fast as we can
o  Deferring everything at the bottom
o  Reduces the static content we need to initially
download
Sorry guys, we’ll
get to you later
Optimize for Above the Fold
●  The New Profile defers fetching the
modules at the bottom of the page
o  Improves server side assembly times
o  Lowers payload and improves network time
o  Improves client rendering times
Optimize for Above the Fold
●  The New Profile defers fetching the
modules at the bottom of the page
o  Improves server side assembly times
o  Lowers payload and improves network time
o  Improves client rendering times
Go fetch!
So we covered the product,
technologies, and some
features... let's revisit our goals.
Revisiting the New Profile Goals
●  Needs to surface your entire professional identity
o  Easily expose new data endpoints

●  Needs to be more interactive
o  Inline editing, searching

●  Needs to be
o  Fluid
o  Flexible
o  Fast
Revisiting the New Profile Goals
●  Needs to surface your entire professional identity
o  Easily expose new data endpoints (Mappers)

●  Needs to be more interactive
o  Inline editing, searching (Dust + Mappers)

●  Needs to be
o  Fluid (Fizzy progressive rendering)
o  Flexible (Fizzy deferred rendering)
o  Fast (Fizzy parallel calls + defer fetch, batching
Mappers, Dust template caching)
Takeaways
●  Mappers for each module makes sense
o  You can combine and reuse with ease
o  A must if refreshing part of page

●  When structuring your page, start with many
embeds 
o  You can control number of requests, when
embeds are rendered, and when to fetch data

●  Many partial templates are a good thing
o  Allows you finer control over what to re-render
o  Improves developer speed
Takeaways cont.
●  Make these technologies work for you

o  Our Mappers are structured to guarantee
minimal downstream calls

o  Take advantage of decoupling rendering layer
with server side endpoints
§  Engineers can build endpoints
§  Web devs can start the templates with
mocked JSON data
Questions?

Más contenido relacionado

La actualidad más candente

HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1
James Pearce
 
jQuery - the world's most popular java script library comes to XPages
jQuery - the world's most popular java script library comes to XPagesjQuery - the world's most popular java script library comes to XPages
jQuery - the world's most popular java script library comes to XPages
Mark Roden
 
WHAT IS HTML5? (at CSS Nite Osaka)
WHAT IS HTML5? (at CSS Nite Osaka)WHAT IS HTML5? (at CSS Nite Osaka)
WHAT IS HTML5? (at CSS Nite Osaka)
Shumpei Shiraishi
 

La actualidad más candente (20)

Disrupting the application eco system with progressive web applications
Disrupting the application eco system with progressive web applicationsDisrupting the application eco system with progressive web applications
Disrupting the application eco system with progressive web applications
 
HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1
 
10 things you can do to speed up your web app today 2016
10 things you can do to speed up your web app today 201610 things you can do to speed up your web app today 2016
10 things you can do to speed up your web app today 2016
 
Responsive Websites and Grid-Based Layouts by Gabriel Walt
Responsive Websites and Grid-Based Layouts by Gabriel Walt Responsive Websites and Grid-Based Layouts by Gabriel Walt
Responsive Websites and Grid-Based Layouts by Gabriel Walt
 
jQuery - the world's most popular java script library comes to XPages
jQuery - the world's most popular java script library comes to XPagesjQuery - the world's most popular java script library comes to XPages
jQuery - the world's most popular java script library comes to XPages
 
Service workers your applications never felt so good
Service workers   your applications never felt so goodService workers   your applications never felt so good
Service workers your applications never felt so good
 
Using Web Standards to create Interactive Data Visualizations for the Web
Using Web Standards to create Interactive Data Visualizations for the WebUsing Web Standards to create Interactive Data Visualizations for the Web
Using Web Standards to create Interactive Data Visualizations for the Web
 
WHAT IS HTML5? (at CSS Nite Osaka)
WHAT IS HTML5? (at CSS Nite Osaka)WHAT IS HTML5? (at CSS Nite Osaka)
WHAT IS HTML5? (at CSS Nite Osaka)
 
Crx 2.2 Deep-Dive
Crx 2.2 Deep-DiveCrx 2.2 Deep-Dive
Crx 2.2 Deep-Dive
 
State of jQuery June 2013 - Portland
State of jQuery June 2013 - PortlandState of jQuery June 2013 - Portland
State of jQuery June 2013 - Portland
 
Building single page applications
Building single page applicationsBuilding single page applications
Building single page applications
 
Adobe AEM CQ5 - Developer Introduction
Adobe AEM CQ5 - Developer IntroductionAdobe AEM CQ5 - Developer Introduction
Adobe AEM CQ5 - Developer Introduction
 
How to Develop a Rich, Native-quality User Experience for Mobile Using Web St...
How to Develop a Rich, Native-quality User Experience for Mobile Using Web St...How to Develop a Rich, Native-quality User Experience for Mobile Using Web St...
How to Develop a Rich, Native-quality User Experience for Mobile Using Web St...
 
jQuery Conference Boston 2011 CouchApps
jQuery Conference Boston 2011 CouchAppsjQuery Conference Boston 2011 CouchApps
jQuery Conference Boston 2011 CouchApps
 
Naked and afraid Offline Mobile
Naked and afraid Offline MobileNaked and afraid Offline Mobile
Naked and afraid Offline Mobile
 
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
 
December 4 SDForum Java Sig Presentation
December 4 SDForum Java Sig PresentationDecember 4 SDForum Java Sig Presentation
December 4 SDForum Java Sig Presentation
 
Professional Frontend Engineering
Professional Frontend EngineeringProfessional Frontend Engineering
Professional Frontend Engineering
 
From Monoliths to Services: Paying Your Technical Debt
From Monoliths to Services: Paying Your Technical DebtFrom Monoliths to Services: Paying Your Technical Debt
From Monoliths to Services: Paying Your Technical Debt
 
mashraqi_farhan
mashraqi_farhanmashraqi_farhan
mashraqi_farhan
 

Destacado

Memorial Day Pps
Memorial Day PpsMemorial Day Pps
Memorial Day Pps
Beckys47201
 

Destacado (20)

How Lucene Powers the LinkedIn Segmentation and Targeting Platform
How Lucene Powers the LinkedIn Segmentation and Targeting PlatformHow Lucene Powers the LinkedIn Segmentation and Targeting Platform
How Lucene Powers the LinkedIn Segmentation and Targeting Platform
 
Dust.js
Dust.jsDust.js
Dust.js
 
Data presentation with dust js technologies backing linkedin
Data presentation with dust js   technologies backing linkedinData presentation with dust js   technologies backing linkedin
Data presentation with dust js technologies backing linkedin
 
Linkedin Profile_V2 (1)
Linkedin Profile_V2 (1)Linkedin Profile_V2 (1)
Linkedin Profile_V2 (1)
 
Harvesting the Power of Samza in LinkedIn's Feed
Harvesting the Power of Samza in LinkedIn's FeedHarvesting the Power of Samza in LinkedIn's Feed
Harvesting the Power of Samza in LinkedIn's Feed
 
Since...
Since...Since...
Since...
 
Memorial Day Pps
Memorial Day PpsMemorial Day Pps
Memorial Day Pps
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
 
LinkedIn Information Security Talent Pool Research - Black Hat CISO Summit 20...
LinkedIn Information Security Talent Pool Research - Black Hat CISO Summit 20...LinkedIn Information Security Talent Pool Research - Black Hat CISO Summit 20...
LinkedIn Information Security Talent Pool Research - Black Hat CISO Summit 20...
 
Crossing the Chasm from On-prem to Cloud: Managing Identities in a Hybrid World
Crossing the Chasm from On-prem to Cloud: Managing Identities in a Hybrid WorldCrossing the Chasm from On-prem to Cloud: Managing Identities in a Hybrid World
Crossing the Chasm from On-prem to Cloud: Managing Identities in a Hybrid World
 
LinkedIn OAuth: Zero To Hero
LinkedIn OAuth: Zero To HeroLinkedIn OAuth: Zero To Hero
LinkedIn OAuth: Zero To Hero
 
Integrated Cloud Security
Integrated Cloud SecurityIntegrated Cloud Security
Integrated Cloud Security
 
LinkedIn Mobile: How do we do it?
LinkedIn Mobile: How do we do it?LinkedIn Mobile: How do we do it?
LinkedIn Mobile: How do we do it?
 
HBase: How to get MTTR below 1 minute
HBase: How to get MTTR below 1 minuteHBase: How to get MTTR below 1 minute
HBase: How to get MTTR below 1 minute
 
DevOps with Chef
DevOps with ChefDevOps with Chef
DevOps with Chef
 
Using Cloud in an Enterprise Environment
Using Cloud in an Enterprise EnvironmentUsing Cloud in an Enterprise Environment
Using Cloud in an Enterprise Environment
 
Identity and Access Management (IAM)
Identity and Access Management (IAM)Identity and Access Management (IAM)
Identity and Access Management (IAM)
 
Amazon Alexa and AWS Lambda
Amazon Alexa and AWS LambdaAmazon Alexa and AWS Lambda
Amazon Alexa and AWS Lambda
 
(MBL310) Alexa Voice Service Under the Hood
(MBL310) Alexa Voice Service Under the Hood(MBL310) Alexa Voice Service Under the Hood
(MBL310) Alexa Voice Service Under the Hood
 
Whats new in web methods 9.12
Whats new in web methods 9.12Whats new in web methods 9.12
Whats new in web methods 9.12
 

Similar a Engineering the New LinkedIn Profile

A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...
A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...
A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...
DataLeader.io
 
Content Delivery at Aviary - NYC MUG 11/19/13
Content Delivery at Aviary - NYC MUG 11/19/13Content Delivery at Aviary - NYC MUG 11/19/13
Content Delivery at Aviary - NYC MUG 11/19/13
MongoDB
 

Similar a Engineering the New LinkedIn Profile (20)

A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...
A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...
A Microsoft Silverlight User Group Starter Kit Made Available for Everyone to...
 
How We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFHow We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADF
 
Pinkoi Mobile Web
Pinkoi Mobile WebPinkoi Mobile Web
Pinkoi Mobile Web
 
Creating Professional Applications with the LinkedIn API
Creating Professional Applications with the LinkedIn APICreating Professional Applications with the LinkedIn API
Creating Professional Applications with the LinkedIn API
 
Content Delivery at Aviary - NYC MUG 11/19/13
Content Delivery at Aviary - NYC MUG 11/19/13Content Delivery at Aviary - NYC MUG 11/19/13
Content Delivery at Aviary - NYC MUG 11/19/13
 
MongoDB and Content Delivery at Aviary by Nir Zicherman and Jack Sisson
MongoDB and Content Delivery at Aviary by Nir Zicherman and Jack SissonMongoDB and Content Delivery at Aviary by Nir Zicherman and Jack Sisson
MongoDB and Content Delivery at Aviary by Nir Zicherman and Jack Sisson
 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web components
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web Components
 
Headless CMS. Sitecore JSS getting started, tips and tricks
Headless CMS. Sitecore JSS getting started, tips and tricksHeadless CMS. Sitecore JSS getting started, tips and tricks
Headless CMS. Sitecore JSS getting started, tips and tricks
 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
 
Expedite the development lifecycle with MongoDB and serverless - DEM02 - Sant...
Expedite the development lifecycle with MongoDB and serverless - DEM02 - Sant...Expedite the development lifecycle with MongoDB and serverless - DEM02 - Sant...
Expedite the development lifecycle with MongoDB and serverless - DEM02 - Sant...
 
Getting started with titanium
Getting started with titaniumGetting started with titanium
Getting started with titanium
 
AspNetWhitePaper
AspNetWhitePaperAspNetWhitePaper
AspNetWhitePaper
 
AspNetWhitePaper
AspNetWhitePaperAspNetWhitePaper
AspNetWhitePaper
 
Building Web Hack Interfaces
Building Web Hack InterfacesBuilding Web Hack Interfaces
Building Web Hack Interfaces
 
Node in Production at Aviary
Node in Production at AviaryNode in Production at Aviary
Node in Production at Aviary
 
(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide
 
Getting started with Appcelerator Titanium
Getting started with Appcelerator TitaniumGetting started with Appcelerator Titanium
Getting started with Appcelerator Titanium
 
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017 So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
 
Frontend APIs powering fast paced product iterations
Frontend APIs powering fast paced product iterationsFrontend APIs powering fast paced product iterations
Frontend APIs powering fast paced product iterations
 

Último

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Último (20)

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 

Engineering the New LinkedIn Profile

  • 1. Engineering the New Profile Josh Clemm Tech Lead for the New Profile March 2013 | LinkedIn David Fleming! Senior Product Manager at Zoomjax! San Francisco Bay Area | Software! ! Previous! Education! Golden Phase, FixDex! Silicon Valley Business Academy!
  • 3. Really a brand new product Refreshed Look & Feel Simplified Design Surfaced New & Interactive Modules New Data Insights
  • 4. New Features Improved in-line editing experience Modules with In-line searching & pagination
  • 5. The New Profile - Goals ●  Represent your entire professional identity o  Not just your resume o  Activity, Groups, Following, Connections, Insights about you and your network
  • 6. The New Profile - Goals ●  Represent your entire professional identity o  Not just your resume o  Activity, Groups, Following, Connections, Insights about you and your network ●  Needs to be more interactive o  Keep users engaged on the page o  Inline pagination, editing, searching
  • 7. The New Profile - Goals ●  Represent your entire professional identity o  Not just your resume o  Activity, Groups, Following, Connections, Insights about you and your network ●  Needs to be more interactive o  Keep users engaged on the page o  Inline pagination, editing, searching ●  Needs to be fluid, flexible, fast o  Progressive rendering o  Maintain high performance
  • 8. So how did we achieve all that?
  • 9. Using a lot of Technologies
  • 11. Let's look at our High Level Frontend Architecture
  • 12. Groups Content Service Connections Content Service Profile Content Service Client/Browser CDN Load Balancer SCDS Fizzy Profile Web App Profile Content Service Profile Web App Connections Content Service Groups Content Service Dust/JS/CSS Server Retrieve Data Models from Mid-tier /profile/view?id=32 top_card.tl, background.tl /profile/topcard /profile/background
  • 13. Groups Content Service Connections Content Service Profile Content Service Client/Browser CDN Load Balancer SCDS Fizzy Profile Web App Profile Content Service Profile Web App Connections Content Service Groups Content Service Dust/JS/CSS Server Retrieve Data Models /profile/view?id=32 top_card.tl, background.tl /profile/topcard /profile/background Our new architecture uses new tech at all layers
  • 14. Groups Content Service Connections Content Service Profile Content Service Client/Browser CDN Load Balancer SCDS Fizzy Profile Web App Profile Content Service Profile Web App Connections Content Service Groups Content Service Dust/JS/CSS Server Retrieve Data Models /profile/view?id=32 top_card.tl, background.tl /profile/topcard /profile/background Let's start at the bottom with Mappers
  • 15. Mappers - JSON endpoints ●  Convert data models from mid-tier services into JSON ●  Each have an unique endpoint URL ( /profile/positions?id=42 ) Positions Mapper JSON "positions": [{ "position": {"id: {}"}, ]} Biz Profile Model Profile Model Rich Media Rest Model References Model Profile Flex Model
  • 16. Mappers - an example public class PictureMapper extends ProfileParametersAwareMapper! {! private PictureContentMap pictureContentMap;! private static final int ZOOMABLE_DIMENSION = 225;! ! @Override! public void doService()! {! PictureContentModel picCM = getContent(PictureContentModel.class); //declare content needs! picCM.criteria().setId(getVieweeId()); //supply any input params! ! assemble(); //invoke framework to retrieve declared content! ! if (isResolvedWithoutErrors(picCM))! {! //all went well, create new content map to hold output (JavaBean-like objects)! pictureContentMap = ContentMap.proxyNew(PictureContentMap.class);! ! Integer pictureWidth = picCM.getPictureWidth(); ! pictureContentMap.setIsZoomable(pictureWidth >= ZOOMABLE_DIMENSION);! ! if(pictureWidth != null && pictureWidth > 0)! {! pictureContentMap.setWidth(pictureWidth);! pictureContentMap.setHeight(picCM.getPictureHeight());! }! pictureContentMap.setPictureID(picCM.getPictureID());! }! }! // tell framework to add our map to final output (uses Jackson to process into JSON)! addOutput(pictureContentMap);! }! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15! 16! 17! 18! 19! 20! 21! 22! 23! 24! 25! 26! 27! 28! 29! 30! 31! 32!
  • 17. Mappers - an example public class PictureMapper extends ProfileParametersAwareMapper! {! private PictureContentMap pictureContentMap;! private static final int ZOOMABLE_DIMENSION = 225;! ! @Override! public void doService()! {! PictureContentModel picCM = getContent(PictureContentModel.class); //declare content needs! picCM.criteria().setId(getVieweeId()); //supply any input params! ! assemble(); //invoke framework to retrieve declared content! ! if (isResolvedWithoutErrors(picCM))! {! //all went well, create new content map to hold output (JavaBean-like objects)! pictureContentMap = ContentMap.proxyNew(PictureContentMap.class);! ! Integer pictureWidth = picCM.getPictureWidth(); ! pictureContentMap.setIsZoomable(pictureWidth >= ZOOMABLE_DIMENSION);! ! if(pictureWidth != null && pictureWidth > 0)! {! pictureContentMap.setWidth(pictureWidth);! pictureContentMap.setHeight(picCM.getPictureHeight());! }! pictureContentMap.setPictureID(picCM.getPictureID());! }! }! // tell framework to add our map to final output (uses Jackson to process into JSON)! addOutput(pictureContentMap);! }! 1! 2! 3! 4! 5! 6! 7! 8! 9! 10! 11! 12! 13! 14! 15! 16! 17! 18! 19! 20! 21! 22! 23! 24! 25! 26! 27! 28! 29! 30! 31! 32! Declare the data you need Set the data you want coming back as JSON
  • 18. Mappers - features ●  Modular o  A single mapper can retrieve data for a section §  Positions, Educations, Groups, etc. ●  Reusable & Combinable o  Mappers can be used more than once §  Positions Mapper is used for Positions section and the positions part of Top Card o  You can Aggregate Mappers under a common root element and a new URL endpoint
  • 19. Profile's Many Mappers ●  Each section on Profile has either a single Mapper or Aggregated Mapper (like Top Card) for its data
  • 20. Profile's Many Mappers ●  Each section on Profile has either a single Mapper or Aggregated Mapper (like Top Card) for its data Summary Mapper Positions Mapper Educations Mapper Picture Mapper Top Card Mapper "TopCard": { "positions": {}, "educations":{}, "picture":{}} Profile Web App Connections Mapper JSON "Summary": { "summary": "I'm an experienced..."} JSON
  • 21. So we have these Mappers that return JSON for each section. Who calls each one?
  • 22. Groups Content Service Connections Content Service Profile Content Service Client/Browser CDN Load Balancer SCDS Fizzy Profile Web App Profile Content Service Profile Web App Connections Content Service Groups Content Service Dust/JS/CSS Server Retrieve Data Models /profile/view?id=32 top_card.tl, background.tl /profile/topcard /profile/background Fizzy - the UI aggregator
  • 23. Fizzy ●  Fizzy is an UI aggregator in 2 parts: o  Fizzy Server fetches the content you want o  Fizzy Client renders it when ready ●  Your base page defines its structure and which UI components it needs (called "embeds") *Fizzy Server is an Apache Traffic Server Plugin, Fizzy Client is a JS library
  • 24. Profile's Embeds Top Card Embed Activity Embed Embed Embed Embed Embed Yet another embed
  • 25. Profile's Embeds in code <html> <body> ... <div id=“wrapper”> <div id=“profile”> <script type=“embed” fs-id=“topcard” fs-uri=“/profile/topcard”/> <script type=“embed” fs-id=“background” fs-uri=“/profile/background”/> ... <script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/> </div> <div id=“insights”> <script type=“embed” fs-id=“people_you_may_know” fs-uri=“/profile/pymk”/> <script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/> ... <script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/> </div> </div> </body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  • 26. Profile's Embeds in code <html> <body> ... <div id=“wrapper”> <div id=“profile”> <script type=“embed” fs-id=“topcard” fs-uri=“/profile/topcard”/> <script type=“embed” fs-id=“background” fs-uri=“/profile/background”/> ... <script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/> </div> <div id=“insights”> <script type=“embed” fs-id=“people_you_may_know” fs-uri=“/profile/pymk”/> <script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/> ... <script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/> </div> </div> </body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Each embed specifies a Mapper endpoint that Fizzy will fetch
  • 27. Fizzy fetches data and sends it to the browser. What's rendering the actual markup?
  • 28. Groups Content Service Connections Content Service Profile Content Service Client/Browser CDN Load Balancer SCDS Fizzy Profile Web App Profile Content Service Profile Web App Connections Content Service Groups Content Service Dust/JS/CSS Server Retrieve Data Models /profile/view?id=32 top_card.tl, background.tl /profile/topcard /profile/background You guessed it... Dust client templates
  • 29. {Dust} client templates ●  LinkedIn's latest and greatest rendering layer ●  Logic-less client template language ●  Profile page made up of many* templates ●  Templates + JSON = full markup! *over 400 actually
  • 30. {Dust} - what it looks like <div id="top_card"> <h4>{name}</h4> <h5>{headline}</h5> {#info} <h6>{location} | {industry}</h6> {/info} </div> { "name": "Frank Stallone", "headline": "Actor and Less Famous Brother", "info":{ "location": "Hollywood", "industry": "Entertainment" } }
  • 31. {Dust} - why it's cool for profile ●  Cached markup in CDNs and browsers o  Members browse many profiles in a row ●  Very DRY and reusable o  Improved development speed o  Templates within templates within templates... §  date range, degree badge, formatted summary field ●  Super easy to refresh a section on the page o  Re-render and replace o  Useful in pagination, inline searching, and inline editing
  • 32. {Dust} on profile <hgroup> {>"tl/apps/profile/v2/embed/company_logo"/} <h4> <a href="{link_title_pivot}" name='title'>{title_highlight|s}</a> {?selfView} <span class="edit-tools"> <a class="edit-section">{i18n_Edit}</a> </span> {/selfView} </h4> <h5> {?companyName} {>"tl/apps/profile/v2/embed/company_link" track_param="prof-exp"/} {/companyName} </h5> </hgroup> <span class="experience-date-locale"> {>"tl/apps/profile/v2/partial/daterange"/} {! Location !} {@pre.fmt key="fmt_location" type="geo.region" value="{location}" render="false"/} {?fmt_location}<span class="locality">{fmt_location}</span> {:else} {?locationName} <span class="locality">{locationName}</span> {/locationName} {/fmt_location} </span> {>"tl/apps/profile/v2/partial/summary_field" _summary=summary/} {>"tl/apps/profile/v2/partial/associated_content" trkCodePrefix="exp"/}
  • 33. {Dust} on profile <hgroup> {>"tl/apps/profile/v2/embed/company_logo"/} <h4> <a href="{link_title_pivot}" name='title'>{title_highlight|s}</a> {?selfView} <span class="edit-tools"> <a class="edit-section">{i18n_Edit}</a> </span> {/selfView} </h4> <h5> {?companyName} {>"tl/apps/profile/v2/embed/company_link" track_param="prof-exp"/} {/companyName} </h5> </hgroup> <span class="experience-date-locale"> {>"tl/apps/profile/v2/partial/daterange"/} {! Location !} {@pre.fmt key="fmt_location" type="geo.region" value="{location}" render="false"/} {?fmt_location}<span class="locality">{fmt_location}</span> {:else} {?locationName} <span class="locality">{locationName}</span> {/locationName} {/fmt_location} </span> {>"tl/apps/profile/v2/partial/summary_field" _summary=summary/} {>"tl/apps/profile/v2/partial/associated_content" trkCodePrefix="exp"/} Partial templates like this are used on almost all the background sections
  • 34. We have our Mappers, Fizzy, and Dust templates... Let's bring it all together.
  • 35. Feature: Inline Editing ●  Dust + Mappers make this easy ●  Dust templates for view and edit ●  Mappers return just the data we need to refresh "View" template "Edit" template Summary Section
  • 36. Feature: Inline Editing ●  Dust + Mappers make this easy ●  Dust templates for view and edit ●  Mappers return just the data we need to refresh "View" template "Edit" template Summary Section When edit link is clicked, render "edit" template
  • 37. Feature: Inline Editing ●  Dust + Mappers make this easy ●  Dust templates for view and edit ●  Mappers return just the data we need to refresh "View" template "Edit" template Summary Section On submit, our endpoint sends back JSON, and we re-render
  • 38. Inline editing - Example Either the "view" or "edit" template is shown at a time
  • 39. Inline editing sounds easy... ●  Issue: Profile data is highly coupled with different sections. o  Adding/editing a position needs to be reflected on Top Card... o  Deleting a project needs to also be removed from any associated position... ●  Solution: since we have mappers for each section, we know which to re-fetch upon a save and refresh the respective templates
  • 40. What about pagination, search? ●  Same idea but easier (not coupled with other sections) ●  Mappers can take URL offset params Switch out a partial template containing just list of profiles
  • 42. High Performance Page ●  Profile is the most trafficked page on LinkedIn ●  Profile fetches 48+ different types of content on each page load o  This content results in 250+ total downstream calls
  • 43. High Performance Page ●  Profile is the most trafficked page on LinkedIn ●  Profile fetches 48+ different types of content on each page load o  This content results in 250+ total downstream calls Bottom Line: We need to be fast, but need to consider downstream fanout
  • 44. High Performance - Parallel Requests Fizzy Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App In the beginning, Profile had 15 embeds with 15 different endpoints which is great for speed...
  • 45. High Performance - Parallel Requests Fizzy Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service That's a lot of downstream calls, often requesting the same data too. Content Service Content Service
  • 46. High Performance - Parallel Requests Fizzy Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service and those calls call more and more... until...
  • 47. High Performance - Parallel Requests Fizzy Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Profile App Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service Content Service aaaaand the site's down
  • 48. High Performance - Parallel Requests ●  Tradeoff: Speed vs Scalability ●  15 parallel calls will be fast but with Profile's load will take down site
  • 49. High Performance - Parallel Requests ●  Tradeoff: Speed vs Scalability ●  15 parallel calls will be fast but with Profile's load will take down site Batched Endpoints to the rescue
  • 50. Batching Calls to Mappers Originally, we had separate endpoints (URIs) for each embed <html> <body> ... <div id=“wrapper”> <div id=“profile”> <script type=“embed” fs-id=“topcard” fs-uri=“/profile/topcard”/> <script type=“embed” fs-id=“background” fs-uri=“/profile/background”/> ... <script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/> </div> <div id=“insights”> <script type=“embed” fs-id=“peeps_you_may_know” fs-uri=“/profile/pymk”/> <script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/> ... <script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/> </div> </div> </body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  • 51. Batching Calls to Mappers We now tell framework to batch these two endpoints (Fizzy knows how to deliver the right data to the right embed) <html> <body> ... <div id=“wrapper”> <div id=“profile”> <script type=“embed” fs-id=“topcard” fs-uri=“/profile/mappers?a=topcard,background”/> <script type=“embed” fs-id=“background” fs-uri=“/profile/mappers?a=topcard,background”/> ... <script type=“embed” fs-id=“connections” fs-uri=“/profile/connections”/> </div> <div id=“insights”> <script type=“embed” fs-id=“peeps_you_may_know” fs-uri=“/profile/pymk”/> <script type=“embed” fs-id=“strength_meter” fs-uri=“/profile/strength”/> ... <script type=“embed” fs-id=“in_common” fs-uri=“/profile/incommon”/> </div> </div> </body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  • 52. Batching Calls in Profile ●  Today, we use between 3-5 parallel requests to Profile ●  It's a good balance of speed vs. scalability ●  Batching requests that need the same data has the added benefit of less downstream calls
  • 53. Progressive Rendering With parallel fetch, Profile modules render when ready for improved perceived performance
  • 54. Progressive Rendering With parallel fetch, Profile modules render when ready for improved perceived performance
  • 55. How else to improve page load times?
  • 56. Profiles can be long... Embed Embed Embed Embed Embed Embed Embed Profile Page
  • 57. Optimize for Above the Fold Embed Embed Embed Embed Embed Embed Embed Profile Page The fold No need to render No need to render or fetch
  • 58. Optimize for Above the Fold ●  The New Profile renders above the fold as fast as we can o  Deferring everything at the bottom o  Reduces the static content we need to initially download
  • 59. Optimize for Above the Fold ●  The New Profile renders above the fold as fast as we can o  Deferring everything at the bottom o  Reduces the static content we need to initially download Sorry guys, we’ll get to you later
  • 60. Optimize for Above the Fold ●  The New Profile defers fetching the modules at the bottom of the page o  Improves server side assembly times o  Lowers payload and improves network time o  Improves client rendering times
  • 61. Optimize for Above the Fold ●  The New Profile defers fetching the modules at the bottom of the page o  Improves server side assembly times o  Lowers payload and improves network time o  Improves client rendering times Go fetch!
  • 62. So we covered the product, technologies, and some features... let's revisit our goals.
  • 63. Revisiting the New Profile Goals ●  Needs to surface your entire professional identity o  Easily expose new data endpoints ●  Needs to be more interactive o  Inline editing, searching ●  Needs to be o  Fluid o  Flexible o  Fast
  • 64. Revisiting the New Profile Goals ●  Needs to surface your entire professional identity o  Easily expose new data endpoints (Mappers) ●  Needs to be more interactive o  Inline editing, searching (Dust + Mappers) ●  Needs to be o  Fluid (Fizzy progressive rendering) o  Flexible (Fizzy deferred rendering) o  Fast (Fizzy parallel calls + defer fetch, batching Mappers, Dust template caching)
  • 65. Takeaways ●  Mappers for each module makes sense o  You can combine and reuse with ease o  A must if refreshing part of page ●  When structuring your page, start with many embeds o  You can control number of requests, when embeds are rendered, and when to fetch data ●  Many partial templates are a good thing o  Allows you finer control over what to re-render o  Improves developer speed
  • 66. Takeaways cont. ●  Make these technologies work for you o  Our Mappers are structured to guarantee minimal downstream calls o  Take advantage of decoupling rendering layer with server side endpoints §  Engineers can build endpoints §  Web devs can start the templates with mocked JSON data

Notas del editor

  1. New &amp; interactive modules like: Connections, Following, Activity, PYMK, Similar profiles, Data insights, and improved Recommendations and Groups modules.
  2. Profile 2.0 high level architectural diagram. The old page used to make 1 request to the profile web app, where a JSP with its various data was rendered, returning HTML. In the new architecture, we have a base page specifying which content we want on the page, and a new layer called Fizzy makes the requests for us. This results in parallel asynchronous calls to our Profile web app, retreiving JSON instead. Fizzy then streams back that JSON and uses Dust client templates to finally render page in the browser.
  3. Convert incoming data models from mid-tier services into JSON
  4. Convert incoming data models from mid-tier services into JSON