Lessons learned from speeding up HootSuite Homepage
Alexandrine Boissière
2 weeks to make HootSuite homepage faster...
Team of 3 software engineers and 1 product manager
Deterioration in Performance
- Significant increase in file size over the years
- Switch to SSL
Deterioration in Performance
httparchive.org
Front-End Performance Monitoring
- Synthetic tests
- RUM (Real User Monitoring)
RUM - Navigation Timing API
performance.timing
RUM - Navigation Timing API
WebPageTest.org
WebPageTest.org
RUM DIARY
RUM DIARY
RUM DIARY
Metrics
Dulles - Virginia / onLoad Time
14 Rules - HPWS - S.Souders
- Make Fewer HTTP Requests
- Use a Content Delivery Network
- Add an Expires Header
- Gzip Components
- Put Stylesheets at the Top
- Put Scripts at the Bottom
- Avoid CSS Expressions
14 Rules - HPWS - S.Souders
- Make JavaScript and CSS External
- Reduce DNS lookups by using Keep-Alive and fewer domains
- Minify JavaScript
- Avoid Redirects
- Remove Duplicate Scripts
- Configure ETags
- Make AJAX Cacheable
Page Speed Recommendations
Plan Of Attack : follow the rules
- Optimize Images
- Put Scripts at the Bottom
- Reduce DNS lookups
- Minify HTML
- Avoid Redirects
Optimize images
- Shaved off 200 kB
- Saved ~200ms
Put Scripts at the Bottom
- No measurable impact on start render time and load time
- Slightly better visual progress
Minify HTML
- Trim whitespace : reduce file size down to 3%
- HTML content download time represents only ~4% of the total load time anyway
- Saved a few milliseconds
Reduce DNS lookups and SSL Negotiation
- Excessive domain sharding : up to 9 cloudfront domains !
- Moved to SSL for all asset delivery
- Plan
- conduct tests with 1, 2, 3 cloudfront domains
- Use DNS-Prefetch link tag
Github - Hello Singapore : 1 single asset host + cloudfront FTW
Reduce DNS lookups and SSL Negotiation
Issues with SSL session resumption (Cloudfront ?)
Avoid Redirects - 301 vs 302
- 302: Temporary redirect
- 301: Permanent redirect
WebPageTest Configuration
Run 9 tests and return the median values
Test Result Data Plots
Non Optimized:
- 4.807s
- 69.047s
- 8.759s
- 4.608s
- 4.685s
- 7.633s
- 4.682s
- 4.954s
- 5.129s
Optimized:
- 4.659s
- 4.408s
- 3.793s
- 3.877s
- 3.953s
- 4.422s
- 4.272s
- 4.084s
- 4.284s
Plan B
- Go through the RUM DIARY logs
- Find the quickest and slowest runs (from ~2.5 to ~70s)
- Analyse the waterfalls
- Find out why tests were slow or fast
1/5 - Third Party Tracking Libraries
- 26 requests over 65 - 16 different hostnames
- SPOF
- Solution : load them after the load event
- Improvement: more than 1s
2/5 - Request your css and js files first
2/5 - Request your css and js files first
- Remove
- <link rel="icon" href="hs_16x16.png" sizes="16x16">
- <link rel="icon" href="hs_32x32.png" sizes="32x32">
- and 2 others..
- Remove <link rel="shortcut icon" href="/favicon.ico"> from the html doc
- Lazy load inline images displayed under the fold
3/5 - Prefer the load event to $.ready to lazy load resources
Password strength checker : 351.1 KB
Cloudfront often failed to deliver that file quickly
4/5 - Minimize backend data inserted directly into the document
- 50% html document = json data inserted in an inline script
- Big impact on the TTFB
5/5 - Optimize JavaScript Code
DOMContentLoaded event: ~400ms
5/5 - Optimize JavaScript Code
DOMContentLoaded event: ~20ms
Don't initialize code in your JavaScript files.
Use a main bootstrap script.
Final Result
From 4.5s to 2.0s - Firefox, Dulles, Virginia
Lessons learned
- Go beyond WPO Rules !
- Don't focus on WPT median values
- Check all the runs
- Understand the waterfall
- Find out what make you slow : fix it !
- Find out what make you fast : make sure it always happens !
- Optimize your JavaScript code !
Thank You!
@theasta
alexandrine.boissiere@hootsuite.com