User-Centric Web App Performance
Performance in Context of the User
The RAIL Model
per·for·mance
/pərˈfôrməns/
noun
- The time it takes for actions to complete before the user's eyes
suc·cess
səkˈses/
noun
- 😁
Performance ROI
*Diagram courtesy of Google (Paul Lewis & Paul Irish), "Introduction to RAIL (Chrome Dev Summit 2015)"
⌛️⌛️⏳
⏳
😭
😁
The User's Perception
*Diagram courtesy of Google (Paul Lewis & Paul Irish), "Introduction to RAIL (Chrome Dev Summit 2015)"
RAIL Method:
An implementation-agnostic, high level, user-centric performance model
What is too slow?
What does the user feel?
User-centric Performance Goals
*Diagram courtesy of Google (Paul Lewis & Paul Irish), "Introduction to RAIL (Chrome Dev Summit 2015)"
esponse
R
A
I
L
Response
Applicable to inputs:
- buttons
- toggling form controls
- starting animations
Goal: Visual response to click/tap in < 100ms
Where the connection between action and reaction breaks.
Response
🛠 Implementation Strategies:
- Decouple the work from the visual response
- Provide feedback for actions > 500ms
- Instant visual response
- Feedback on status of the action
Response
🛠 Implementation Strategies:
- Optimistic UI's
- Assume Success
- Only delayed notifications are on server error
- Respond with errors within 2 seconds, while still in user's flow
Examples:
nimation
R
A
I
L
Animation
- Reasons why:
- A smooth experience
- Users notice frame rate variations
- The standard for most devices today
Goal: Each frame completes in less than 16ms (60 fps)
Animation
- The browser takes 6ms per frame to paint
- You get 10ms per frame
*Diagram courtesy of Google (Paul Lewis), "Rendering Performance" - developers.google.com
The Pixel Pipeline
Animation
🛠 Implementation Strategies:
**For animations experiencing sub-optimal performance:
- Avoid Animations that change the layout of the page
- Animate using transform and opacity
- Use will-change property - keeps browser from having to consider layout render or painting
.moving-element {
will-change: transform;
}
.moving-element {
transform: translateZ(0);
}
⚠️ Don't overuse
Animation
🛠 Implementation Strategies:
- Profiling animation performance
- Example of will-change and transform
dle
R
A
I
L
Idle Time
- Minimize data loading in pre-rendering stage
- Use idle time to load what you can
- Yield control back to main thread every 50ms, so the 100ms response goal can be met
Goal: Use idle time to do work, while still satisfying the Response goal
// Creating a new Web Worker
const myWorker = new Worker("./worker.js");
// Giving work to the worker thread
myWorker.postMessage(arbitraryObject);
console.log("Message posted to worker");
main.js
- Allows web content to run scripts in background threads
- Each script is a worker
- Can be used for processing, fetching, and storage interactions
Idle Time
Implementation Strategies (freeing up the main thread):
Web Workers
🛠
Idle Time
Web Workers
...
// Handling result event from worker thread
myWorker.onmessage = function(e) {
console.log(`
Message received from worker:
${JSON.stringify(e.data)}
`);
}
main.js
onmessage = function(e) {
console.log(`
Received object from the main script:
${JSON.stringify(e.data)}
`);
const workerResult = doWork(e.data);
// Posting a message back to main.js
postMessage(workerResult);
}
worker.js
Idle Time
Other Implementation Strategies (freeing up the main thread):
- Request Animation Frame (RAF)
- Async script tags
🛠
oad
R
A
I
L
Load
- User attention wanders after 1 second
Goal: First meaningful paint in < 1000ms
Load
🛠 Implementation Strategies
- Lazy loading - React Example:
class View extends React.Component {
...
// This method is invoked immediately after
// a component is mounted to the DOM.
componentDidMount() {
fetch("my-endpoint")
.then(data => data.json())
.then(json => this.setState({ pageData: json }))
.catch(e => this.setState({ pageError: e }));
}
render() {
return (
<MostMeaningfulContent />
{this.state.pageData && <SupplementalContent />}
)
}
}
Load
🛠 Implementation Strategies
- Server-side rendering and caching
- In-house options
- Community options
- Conditional loading:
- Load on scroll
- Load on event
🎊 The End 🎉
Sources
-
RAIL Model
-
https://developers.google.com/web/fundamentals/performance/rail
-
https://www.smashingmagazine.com/2015/10/rail-user-centric-model-performance/
-
-
Web App Performance High Level Strategies
-
https://developers.google.com/web/fundamentals/performance/rendering/
-
https://www.smashingmagazine.com/2016/11/true-lies-of-optimistic-user-interfaces/
-
-
Web App Performance Techniques
-
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
-
-
Optimizing Web App Animations
-
https://developers.google.com/web/fundamentals/design-and-ux/animations/
-
https://developers.google.com/web/fundamentals/design-and-ux/animations/animations-and-performance
-
https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108
-
https://developers.google.com/web/fundamentals/performance/rendering/stick-to-compositor-only-properties-and-manage-layer-count
-
Web App Performance
By Evan Peterson
Web App Performance
Learn about improving the performance of your web app in ways that matter to the user i.e. in ways that will improve user happiness. The Google RAIL method is explained, and implementation strategies are presented as well.
- 757