Are you using progressive booting already? What about tree-shaking and code-splitting in React and Angular? Have you set up Brotli or Zopfli compression, OCSP stapling and HPACK compression? Also, how about resource hints, client hints and CSS containment — not to mention IPv6, HTTP/2 and service workers?
Back in the day, performance was often a mere afterthought. Often deferred till the very end of the project, it would boil down to minification, concatenation, asset optimization and potentially a few fine adjustments on the server’s
config file. Looking back now, things seem to have changed quite significantly.
Performance isn’t just a technical concern: It matters, and when baking it into the workflow, design decisions have to be informed by their performance implications. Performance has to be measured, monitored and refined continually, and the growing complexity of the web poses new challenges that make it hard to keep track of metrics, because metrics will vary significantly depending on the device, browser, protocol, network type and latency (CDNs, ISPs, caches, proxies, firewalls, load balancers and servers all play a role in performance).
So, if we created an overview of all the things we have to keep in mind when improving performance — from the very start of the process until the final release of the website — what would that list look like? Below you’ll find a (hopefully unbiased and objective) front-end performance checklist for 2017 — an overview of the issues you might need to consider to ensure that your response times are fast and your website smooth.
Front-End Performance Checklist 2017 Link
Micro-optimizations are great for keeping a performance on track, but it’s critical to have clearly defined targets in mind — measurable goals that would influence any decisions made throughout the process. There are a couple of different models, and the ones discussed below are quite opinionated — just make sure to set your own priorities early on.
Getting Ready And Setting Goals Link
- Be 20% faster than your fastest competitor.
According to psychological research3, if you want users to feel that your website is faster than any other website, you need to be at least 20% faster. Full-page loading time isn’t as relevant as metrics such as start rendering time, the first meaningful paint4 (i.e. the time required for a page to display its primary content) and the time to interactive5 (the time at which a page — and primarily a single-page application — appears to be ready enough that a user can interact with it).
Measure start rendering (with WebPagetest1686) and first meaningful paint times (with Lighthouse1727) on a Moto G, a mid-range Samsung device and a good middle-of-the-road device like a Nexus 4, preferably in an open device lab8 — on regular 3G, 4G and Wi-Fi connections.
Look at your analytics to see what your users are on. You can then mimic the 90th percentile’s experience for testing. Collect data, set up a spreadsheet10, shave off 20%, and set up your goals (i.e. performance budgets11) this way. Now you have something measurable to test against. If you’re keeping the budget in mind and trying to ship down just the minimal script to get a quick time-to-interactive value, then you’re on a reasonable path.
Share the checklist with your colleagues. Make sure that the checklist is familiar to every member of your team to avoid misunderstandings down the line. Every decision has performance implications, and the project would hugely benefit from front-end developers being actively involved when the concept, UX and visual design are decided on. Map design decisions against performance budget and the priorities defined in the checklist.
- 100-millisecond response time, 60 frames per second.
The RAIL performance model14 gives you healthy targets: Do your best to provide feedback in less than 100 milliseconds after initial input. To allow for <100 milliseconds response, the page must yield control back to main thread at latest after every <50 milliseconds. For high pressure points like animation, it’s best to do nothing else where you can and the absolute minimum where you can’t.
Also, each frame of animation should be completed in less than 16 milliseconds, thereby achieving 60 frames per second (1 second ÷ 60 = 16.6 milliseconds) — preferably under 10 milliseconds. Because the browser needs time to paint the new frame to the screen your code should finish executing before hitting the 16.6 milliseconds mark. Be optimistic15 and use the idle time wisely. Obviously, these targets apply to runtime performance, rather than loading performance.
- First meaningful paint under 1.25 seconds, SpeedIndex under 1000.
Although it might be very difficult to achieve, your ultimate goal should be a start rendering time under 1 second and a SpeedIndex16 value under 1000 (on a fast connection). For the first meaningful paint, count on 1250 milliseconds at most. For mobile, a start rendering time under 3 seconds for 3G on a mobile device is acceptable17. Being slightly above that is fine, but push to get these values as low as possible.
Defining the Environment Link
- Choose and set up your build tools.
Don’t pay much attention to what’s supposedly cool these days. Stick to your environment for building, be it Grunt, Gulp, Webpack, PostCSS or a combination of tools. As long as you are getting results fast and you have no issues maintaining your build process, you’re doing just fine.
- Progressive enhancement.
Keeping progressive enhancement18 as the guiding principle of your front-end architecture and deployment is a safe bet. Design and build the core experience first, and then enhance the experience with advanced features for capable browsers, creating resilient19 experiences. If your website runs fast on a slow machine with a poor screen in a poor browser on a suboptimal network, then it will only run faster on a fast machine with a good browser on a decent network.
- Angular, React, Ember and co.
- AMP or Instant Articles?
Depending on the priorities and strategy of your organization, you might want to consider using Google’s AMP27 or Facebook’s Instant Articles28. You can achieve good performance without them, but AMP does provide a solid performance framework with a free content delivery network (CDN), while Instant Articles will boost your performance on Facebook. You could build progressive web AMPs29, too.
- Choose your CDN wisely.
Depending on how much dynamic data you have, you might be able to “outsource” some part of the content to a static site generator30, pushing it to a CDN and serving a static version from it, thus avoiding database requests. You could even choose a static-hosting platform31 based on a CDN, enriching your pages with interactive components as enhancements (JAMStack32).
Notice that CDNs can serve (and offload) dynamic content as well? So, restricting your CDN to static assets is not necessary. Double-check whether your CDN performs content compression and conversion, smart HTTP/2 delivery, edge-side includes, which assemble static and dynamic parts of pages at the CDN’s edge (i.e. the server closest to the user), and other tasks.
Build Optimizations Link
- Set your priorities straight.
Set up a spreadsheet. Define the basic core experience for legacy browsers (i.e. fully accessible core content), the enhanced experience for capable browsers (i.e. the enriched, full experience) and the extras (assets that aren’t absolutely required and can be lazy-loaded, such as web fonts, unnecessary styles, carousel scripts, video players, social media buttons, large images). We published an article on “Improving Smashing Magazine’s Performance33,” which describes this approach in detail.
- Use the “cutting-the-mustard” technique.
Use the cutting-the-mustard technique34 to send the core experience to legacy browsers and an enhanced experience to modern browsers. Be strict in loading your assets: Load the core experience immediately, the enhancements on
DomContentLoadedand the extras on the
Note that the technique deduces device capability from browser version, which is no longer something we can do these days. For example, cheap Android phones in developing countries mostly run Chrome and will cut the mustard despite their limited memory and CPU capabilities. Beware that, while we don’t really have an alternative, use of the technique has become more limited recently.
- Consider micro-optimization and progressive booting.
In some apps, you might need some time to initialize the app before you can render the page. Display skeleton screens35 instead of loading indicators. Look for modules and techniques to speed up the initial rendering time (for example, tree-shaking36 and code-splitting37), because most performance issues come from the initial parsing time to bootstrap the app. Also, use an ahead-of-time compiler38 to offload some of the client-side rendering39 to the server40 and, hence, output usable results quickly. Finally, consider using Optimize.js41 for faster initial loading by wrapping eagerly invoked functions (it might not be necessary42 any longer, though).
- Are HTTP cache headers set properly?
max-ageand other HTTP cache headers have been set properly. In general, resources should be cacheable either for a very short time (if they are likely to change) or indefinitely (if they are static) — you can just change their version in the URL when needed.
If possible, use
Cache-control: immutable, designed for fingerprinted static resources, to avoid revalidation (as of December 2016, supported only in Firefox47 on
https://transactions). You can use Heroku’s primer on HTTP caching headers48, Jake Archibald’s “Caching Best Practices49” and Ilya Grigorik’s HTTP caching primer50 as guides.
asyncattributes in HTML.
In practice, it turns out we should prefer
async51 (at a cost to users of Internet Explorer52 up to and including version 9, because you’re likely to break scripts for them). Also, limit the impact of third-party libraries and scripts, especially with social sharing buttons and
<iframe>embeds (such as maps). You can use static social sharing buttons53 (such as by SSBG54) and static links to interactive maps55 instead.
- Are images properly optimized?
As far as possible, use responsive images56 with
<picture>element. While you’re at it, you could also make use of the WebP format57 by serving WebP images with the
<picture>element and a JPEG fallback (see Andreas Bovens’ code snippet58) or by using content negotiation (using
Acceptheaders). Sketch natively supports WebP, and WebP images can be exported from Photoshop using a WebP plugin for Photoshop59. Other options are available60, too.
You can also use client hints63, which are now gaining browser support64. Not enough resources to bake in sophisticated markup for responsive images? Use the Responsive Image Breakpoints Generator6562 or a service such as Cloudinary66 to automate image optimization. Also, in many cases, using
sizesalone will reap significant benefits. On Smashing Magazine, we use the postfix
-optfor image names — for example,
brotli-compression-opt.png; whenever an image contains that postfix, everybody on the team knows that it’s been optimized.
- Take image optimization to the next level.
When you’re working on a landing page on which it’s critical that a particular image loads blazingly fast, make sure that JPEGs are progressive and compressed with mozJPEG67 (which improves the start rendering time by manipulating scan levels), Pingo68 for PNG, Lossy GIF69 for GIF and SVGOMG70 for SVG. Blur out unnecessary parts of the image (by applying a Gaussian blur filter to them) to reduce the file size, and eventually you might even start to remove colors or make a picture black and white to reduce the size further. For background images, exporting photos from Photoshop with 0 to 10% quality can be absolutely acceptable as well.
- Are web fonts optimized?
Chances are high that the web fonts you are serving include glyphs and extra features that aren’t being used. You can ask your type foundry to subset web fonts or subset them yourself75 if you are using open-source fonts (for example, by including only Latin with some special accent glyphs) to minimize their file sizes. WOFF2 support76 is great, and you can use WOFF and OTF as fallbacks for browsers that don’t support it. Also, choose one of the strategies from Zach Leatherman’s “Comprehensive Guide to Font-Loading Strategies8077,” and use a service worker cache to cache fonts persistently. Need a quick win? Pixel Ambacht has a quick tutorial and case study78 to get your fonts in order.
If you can’t serve fonts from your server and are relying on third-party hosts, make sure to use Web Font Loader81. FOUT is better than FOIT82; start rendering text in the fallback right away, and load fonts asynchronously — you could also use loadCSS83 for that. You might be able to get away with locally installed OS fonts84 as well.
- Push critical CSS quickly.
To ensure that browsers start rendering your page as quickly as possible, it’s become a common practice85 to collect all of the CSS required to start rendering the first visible portion of the page (known as “critical CSS” or “above-the-fold CSS”) and add it inline in the
<head>of the page, thus reducing roundtrips. Due to the limited size of packages exchanged during the slow start phase, your budget for critical CSS is around 14 KB. If you go beyond that, the browser will need addition roundtrips to fetch more styles. CriticalCSS86 and Critical87 enable you to do just that. You might need to do it for every template you’re using. If possible, consider using the conditional inlining approach88 used by the Filament Group.
With HTTP/2, critical CSS could be stored in a separate CSS file and delivered via a server push without bloating the HTML. The catch is that server pushing isn’t supported consistently and has some caching issues (see slide 114 onwards of Hooman Beheshti’s presentation89). The effect could, in fact, be negative90 and bloat the network buffers, preventing genuine frames in the document from being delivered. Server pushing is much more effective on warm connections91 due to the TCP slow start. So, you might need to create a cache-aware HTTP/2 server push mechanism92. Keep in mind, though, that the new
cache-digestspecification93 will negate the need to manually build these “cache-aware” servers.
- Use tree-shaking and code-splitting to reduce payloads.
Tree-shaking94 is a way to clean up your build process by only including code that is actually used in production. You can use Webpack 2 to eliminate unused exports95, and UnCSS96 or Helium97 to remove unused styles from CSS. Also, you might want to consider learning how to write efficient CSS selectors98 as well as how to avoid bloat and expensive styles99.
Code-splitting100 is another Webpack feature that splits your code base into “chunks” that are loaded on demand. Once you define split points in your code, Webpack takes care of the dependencies and outputted files. It basically enables you to keep the initial download small and to request code on demand, when requested by the application.
Note that Rollup101 shows significantly better results than Browserify exports. While we’re at it, you might want to check out Rollupify102, which converts ECMAScript 2015 modules into one big CommonJS module — because small modules can have a surprisingly high performance cost103 depending on your choice of bundler and module system.
- Improve rendering performance.
Isolate expensive components with CSS containment104 — for example, to limit the scope of the browser’s styles, of layout and paint work for off-canvas navigation, or of third-party widgets. Make sure that there is no lag when scrolling the page or when an element is animated, and that you’re consistently hitting 60 frames per second. If that’s not possible, then at least making the frames per second consistent is preferable to a mixed range of 60 to 15. Use CSS’
will-change105 to inform the browser of which elements and properties will change.
Also, measure runtime rendering performance106 (for example, in DevTools107). To get started, check Paul Lewis’ free Udacity course on browser-rendering optimization108. We also have a lil’ article by Sergey Chikuyonok on how to get GPU animation right109.
- Warm up the connection to speed up delivery.
dns-prefetch111 (which performs a DNS lookup in the background),
preconnect112 (which asks the browser to start the connection handshake (DNS, TCP, TLS) in the background),
prefetch113 (which asks the browser to request a resource),
prerender114 (which asks the browser to render the specified page in the background) and
preload115 (which prefetches resources without executing them, among other things). Note that in practice, depending on browser support, you’ll prefer
dns-prefetch, and you’ll be cautious with using
prerender— the latter should only be used if you are very confident about where the user will go next (for example, in a purchasing funnel).
- Get ready for HTTP/2.
With Google moving towards a more secure web116 and eventual treatment of all HTTP pages in Chrome as being “not secure,” you’ll need to decide on whether to keep betting on HTTP/1.1 or set up an HTTP/2 environment117. HTTP/2 is supported very well118; it isn’t going anywhere; and, in most cases, you’re better off with it. The investment will be quite significant, but you’ll need to move to HTTP/2 sooner or later. On top of that, you can get a major performance boost119 with service workers and server push (at least long term).
The downsides are that you’ll have to migrate to HTTPS, and depending on how large your HTTP/1.1 user base is (that is, users on legacy operating systems or with legacy browsers), you’ll have to send different builds, which would require you to adapt a different build process122. Beware: Setting up both migration and a new build process might be tricky and time-consuming. For the rest of this article, I’ll assume that you’re either switching to or have already switched to HTTP/2.
- Properly deploy HTTP/2.
Again, serving assets over HTTP/2123 requires a major overhaul of how you’ve been serving assets so far. You’ll need to find a fine balance between packaging modules and loading many small modules in parallel.
Still, you can try to load CSS progressively129128. Obviously, by doing so, you are actively penalizing HTTP/1.1 users, so you might need to generate and serve different builds to different browsers as part of your deployment process, which is where things get slightly more complicated. You could get away with HTTP/2 connection coalescing130, which allows you to use domain sharding while benefiting from HTTP/2, but achieving this in practice is difficult.
What to do? If you’re running over HTTP/2, sending around 10 packages seems like a decent compromise (and isn’t too bad for legacy browsers). Experiment and measure to find the right balance for your website.
- Make sure the security on your server is bulletproof.
All browser implementations of HTTP/2 run over TLS, so you will probably want to avoid security warnings or some elements on your page not working. Double-check that your security headers are set properly131, eliminate known vulnerabilities132, and check your certificate133.
Haven’t migrated to HTTPS yet? Check The HTTPS-Only Standard134 for a thorough guide. Also, make sure that all external plugins and tracking scripts are loaded via HTTPS, that cross-site scripting isn’t possible and that both HTTP Strict Transport Security headers135 and Content Security Policy headers136 are properly set.
- Do your servers and CDNs support HTTP/2?
Different servers and CDNs are probably going to support HTTP/2 differently. Use Is TLS Fast Yet?139137 to check your options, or quickly look up how your servers are performing and which features you can expect to be supported.
- Is Brotli or Zopfli compression in use?
Last year, Google introduced140 Brotli141, a new open-source lossless data format, which is now widely supported142 in Chrome, Firefox and Opera. In practice, Brotli appears to be more effective143 than Gzip and Deflate. It might be slow to compress, depending on the settings, and slower compression will ultimately lead to higher compression rates. Still, it decompresses fast. Because the algorithm comes from Google, it’s not surprising that browsers will accept it only if the user is visiting a website over HTTPS — and yes, there are technical reasons for that as well. The catch is that Brotli doesn’t come preinstalled on most servers today, and it’s not easy to set up without self-compiling NGINX or Ubuntu. However, you can enable Brotli even on CDNs that don’t support it144 yet (with a service worker).
Alternatively, you could look into using Zopfli’s compression algorithm145, which encodes data to Deflate, Gzip and Zlib formats. Any regular Gzip-compressed resource would benefit from Zopfli’s improved Deflate encoding, because the files will be 3 to 8% smaller than Zlib’s maximum compression. The catch is that files will take around 80 times longer to compress. That’s why it’s a good idea to use Zopfli on resources that don’t change much, files that are designed to be compressed once and downloaded many times.
- Is OCSP stapling enabled?
By enabling OCSP stapling on your server146, you can speed up your TLS handshakes. The Online Certificate Status Protocol (OCSP) was created as an alternative to the Certificate Revocation List (CRL) protocol. Both protocols are used to check whether an SSL certificate has been revoked. However, the OCSP protocol does not require the browser to spend time downloading and then searching a list for certificate information, hence reducing the time required for a handshake.
- Have you adopted IPv6 yet?
Because we’re running out of space with IPv4147 and major mobile networks are adopting IPv6 rapidly (the US has reached148 a 50% IPv6 adoption threshold), it’s a good idea to update your DNS to IPv6149 to stay bulletproof for the future. Just make sure that dual-stack support is provided across the network — it allows IPv6 and IPv4 to run simultaneously alongside each other. After all, IPv6 is not backwards-compatible. Also, studies show150 that IPv6 made those websites 10 to 15% faster due to neighbor discovery (NDP) and route optimization.
- Is HPACK compression in use?
If you’re using HTTP/2, double-check that your servers implement HPACK compression151 for HTTP response headers to reduce unnecessary overhead. Because HTTP/2 servers are relatively new, they may not fully support the specification, with HPACK being an example. H2spec152 is a great (if very technically detailed) tool to check that. HPACK works153.
- Are service workers used for caching and network fallbacks?
No performance optimization over a network can be faster than a locally stored cache on user’s machine. If your website is running over HTTPS, use the “Pragmatist’s Guide to Service Workers157” to cache static assets in a service worker cache and store offline fallbacks (or even offline pages) and retrieve them from the user’s machine, rather than going to the network. Also, check Jake’s Offline Cookbook158 and the free Udacity course “Offline Web Applications159.” Browser support? It’s getting there160, and the fallback is the network anyway.
Testing and Monitoring Link
- Monitor mixed-content warnings.
If you’ve recently migrated from HTTP to HTTPS, make sure to monitor both active and passive mixed-content warnings, with a tool such as Report-URI.io161. You can also use Mixed Content Scan162 to scan your HTTPS-enabled website for mixed content.
- Is your development workflow in DevTools optimized?
- Have you tested in proxy browsers and legacy browsers? Testing in Chrome and Firefox is not enough. Look into how your website works in proxy browsers and legacy browsers. UC Browser and Opera Mini, for instance, have a significant market share in Asia165 (up to 35% in Asia). Measure average Internet speed166 in your countries of interest to avoid big surprises down the road. Test with network throttling, and emulate a high-DPI device. BrowserStack167 is fantastic, but test on real devices as well.
- Is continuous monitoring set up?
Having a private instance of WebPagetest1686 is always beneficial for quick and unlimited tests. Set up continuous monitoring of performance budgets with automatic alerts. Set your own user-timing marks to measure and monitor business-specific metrics. Look into using SpeedCurve169 to monitor changes in performance over time, and/or New Relic170 to get insights that WebPagetest cannot provide. Also, look into SpeedTracker171, Lighthouse1727 and Calibre173.
Quick Wins Link
This list is quite comprehensive, and completing all of the optimizations might take quite a while. So, if you had just 1 hour to get significant improvements, what would you do? Let’s boil it all down to 10 low-hanging fruits. Obviously, before you start and once you finish, measure results, including start rendering time and SpeedIndex on a 3G and cable connection.
- Your goal is a start rendering time under 1 second on cable and under 3 seconds on 3G, and a SpeedIndex value under 1000. Optimize for start rendering time and time-to-interactive.
- Prepare critical CSS for your main templates, and include it in the
<head>of the page. (Your budget is 14 KB).
- Add resource hints to speed up delivery with faster
- Subset web fonts and load them asynchronously (or just switch to system fonts instead).
- Optimize images, and consider using WebP for critical pages (such as landing pages).
- Check that HTTP cache headers and security headers are set properly.
- Enable Brotli or Zopfli compression on the server. (If that’s not possible, don’t forget to enable Gzip compression.)
- If HTTP/2 is available, enable HPACK compression and start monitoring mixed-content warnings. If you’re running over LTS, also enable OCSP stapling.
Download The Checklist (PDF, Apple Pages) Link
With this checklist in mind, you should be prepared for any kind of front-end performance project. Feel free to download the print-ready PDF of the checklist as well as an editable Apple Pages document to customize the checklist for your needs:
Off We Go! Link
Some of the optimizations might be beyond the scope of your work or budget or might just be overkill given the legacy code you have to deal with. That’s fine! Use this checklist as a general (and hopefully comprehensive) guide, and create your own list of issues that apply to your context. But most importantly, test and measure your own projects to identify issues before optimizing. Happy performance results in 2017, everyone!
Huge thanks to Anselm Hannemann, Patrick Hamann, Addy Osmani, Andy Davies, Tim Kadlec, Yoav Weiss, Rey Bango, Matthias Ott, Mariana Peralta, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson and Rodney Rehm for reviewing this article, as well as our fantastic community, which has shared techniques and lessons learned from its work in performance optimization for everybody to use. You are truly smashing! (al)
- 1 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pdf
- 2 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pages
- 3 https://www.smashingmagazine.com/2015/09/why-performance-matters-the-perception-of-time/#the-need-for-performance-optimization-the-20-rule
- 4 https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint
- 5 https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive
- 6 http://www.webpagetest.org/
- 7 https://github.com/GoogleChrome/lighthouse
- 8 https://www.smashingmagazine.com/2016/11/worlds-best-open-device-labs/
- 9 https://github.com/GoogleChrome/lighthouse
- 10 http://danielmall.com/articles/how-to-make-a-performance-budget/
- 11 http://bradfrost.com/blog/post/performance-budget-builder/
- 12 http://bradfrost.com/blog/post/performance-budget-builder/
- 13 http://bradfrost.com/blog/post/performance-budget-builder/
- 14 https://www.smashingmagazine.com/2015/10/rail-user-centric-model-performance/
- 15 http://info.meteor.com/blog/optimistic-ui-with-meteor-latency-compensation
- 16 https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index
- 17 https://www.soasta.com/blog/google-mobile-web-performance-study/
- 18 https://www.aaron-gustafson.com/notebook/insert-clickbait-headline-about-progressive-enhancement-here/
- 19 https://resilientwebdesign.com/
- 20 https://www.youtube.com/watch?v=6I_GwgoGm1w
- 22 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
- 23 https://developers.google.com/web/updates/2015/11/app-shell
- 24 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
- 25 https://developers.google.com/web/updates/2015/11/app-shell
- 26 https://developers.google.com/web/updates/2015/11/app-shell
- 27 https://www.ampproject.org/
- 28 https://instantarticles.fb.com/
- 29 https://www.smashingmagazine.com/2016/12/progressive-web-amps/
- 30 https://www.smashingmagazine.com/2015/11/static-website-generators-jekyll-middleman-roots-hugo-review/
- 31 https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/
- 32 https://jamstack.org/
- 33 https://www.smashingmagazine.com/2014/09/improving-smashing-magazine-performance-case-study/
- 34 http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
- 35 https://twitter.com/lukew/status/665288063195594752
- 36 https://medium.com/@richavyas/aha-moments-from-ngconf-2016-part-1-angular-2-0-compile-cycle-6f462f68632e#.8b9afnsub
- 37 https://webpack.github.io/docs/code-splitting.html
- 38 https://www.lucidchart.com/techblog/2016/09/26/improving-angular-2-load-times/
- 39 https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express/
- 40 http://redux.js.org/docs/recipes/ServerRendering.html
- 41 https://github.com/nolanlawson/optimize-js
- 42 https://twitter.com/tverwaes/status/809788255243739136
- 43 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fmp-and-tti-opt.jpeg
- 44 https://aerotwist.com/blog/when-everything-is-important-nothing-is/
- 45 https://aerotwist.com/blog/when-everything-is-important-nothing-is/
- 46 https://aerotwist.com/blog/when-everything-is-important-nothing-is/#which-to-use-progressive-booting
- 47 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
- 48 https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers
- 49 https://jakearchibald.com/2016/caching-best-practices/
- 50 https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en
- 51 http://calendar.perfplanet.com/2016/prefer-defer-over-async/
- 52 https://github.com/h5bp/lazyweb-requests/issues/42
- 53 https://www.savjee.be/2015/01/Creating-static-social-share-buttons/
- 54 https://simplesharingbuttons.com
- 55 https://developers.google.com/maps/documentation/static-maps/intro
- 56 https://www.smashingmagazine.com/2014/05/responsive-images-done-right-guide-picture-srcset/
- 57 https://www.smashingmagazine.com/2015/10/webp-images-and-performance/
- 58 https://dev.opera.com/articles/responsive-images/#different-image-types-use-case
- 59 http://telegraphics.com.au/sw/product/WebPFormat#webpformat
- 60 https://developers.google.com/speed/webp/docs/using
- 61 https://www.smashingmagazine.com/wp-content/uploads/2016/12/responsive-image-breakpoints-generator-large-opt.jpeg
- 62 http://www.responsivebreakpoints.com/
- 63 https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/
- 64 http://caniuse.com/#search=client-hints
- 65 http://www.responsivebreakpoints.com/
- 66 http://cloudinary.com/documentation/api_and_access_identifiers
- 67 https://github.com/mozilla/mozjpeg
- 68 http://css-ig.net/pingo
- 69 https://kornel.ski/lossygif
- 70 https://jakearchibald.github.io/svgomg/
- 71 http://csswizardry.com/2016/10/improving-perceived-performance-with-multiple-background-images/
- 72 https://jmperezperez.com/medium-image-progressive-loading-placeholder/
- 73 https://manu.ninja/dominant-colors-for-lazy-loading-images#tiny-thumbnails
- 74 https://css-tricks.com/the-blur-up-technique-for-loading-background-images/
- 75 https://www.fontsquirrel.com/tools/webfont-generator
- 76 http://caniuse.com/#search=woff2
- 77 https://www.zachleat.com/web/comprehensive-webfonts/
- 78 https://pixelambacht.nl/2016/font-awesome-fixed/
- 79 https://www.zachleat.com/web/comprehensive-webfonts/
- 80 https://www.zachleat.com/web/comprehensive-webfonts/
- 81 https://github.com/typekit/webfontloader
- 82 https://www.filamentgroup.com/lab/font-events.html
- 83 https://github.com/filamentgroup/loadCSS
- 84 https://www.smashingmagazine.com/2015/11/using-system-ui-fonts-practical-guide/
- 85 https://www.smashingmagazine.com/2015/08/understanding-critical-css/
- 86 https://github.com/filamentgroup/criticalCSS
- 87 https://github.com/addyosmani/critical
- 88 https://www.filamentgroup.com/lab/performance-rwd.html
- 89 http://www.slideshare.net/Fastly/http2-what-no-one-is-telling-you
- 90 http://calendar.perfplanet.com/2016/http2-push-the-details/
- 91 https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0/edit
- 92 https://css-tricks.com/cache-aware-server-push/
- 93 http://calendar.perfplanet.com/2016/cache-digests-http2-server-push/
- 95 http://www.2ality.com/2015/12/webpack-tree-shaking.html
- 96 https://github.com/giakki/uncss
- 97 https://github.com/geuis/helium-css
- 98 http://csswizardry.com/2011/09/writing-efficient-css-selectors/
- 99 https://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/
- 100 https://webpack.github.io/docs/code-splitting.html
- 101 http://rollupjs.org/
- 102 https://github.com/nolanlawson/rollupify
- 103 https://nolanlawson.com/2016/08/15/the-cost-of-small-modules/
- 104 http://caniuse.com/#search=contain
- 105 http://caniuse.com/#feat=will-change
- 106 https://aerotwist.com/blog/my-performance-audit-workflow/#runtime-performance
- 107 https://developers.google.com/web/tools/chrome-devtools/rendering-tools/
- 108 https://www.udacity.com/course/browser-rendering-optimization--ud860
- 109 https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
- 110 https://w3c.github.io/resource-hints
- 111 http://caniuse.com/#search=dns-prefetch
- 112 http://www.caniuse.com/#search=preconnect
- 113 http://caniuse.com/#search=prefetch
- 114 http://caniuse.com/#search=prerender
- 115 https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/
- 116 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
- 117 https://http2.github.io/faq/
- 118 http://caniuse.com/#search=http2
- 119 https://www.youtube.com/watch?v=RWLzUnESylc&t=1s&list=PLNYkxOF6rcIBTs2KPy1E6tIYaWoFcG3uj&index=25
- 120 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
- 121 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
- 122 https://rmurphey.com/blog/2015/11/25/building-for-http2
- 123 https://www.youtube.com/watch?v=yURLTwZ3ehk
- 124 https://rmurphey.com/blog/2015/11/25/building-for-http2
- 125 http://engineering.khanacademy.org/posts/js-packaging-http2.htm
- 126 https://www.chromium.org/developers/design-documents/inter-process-communication
- 127 https://jakearchibald.com/2016/link-in-body/
- 128 https://jakearchibald.com/2016/link-in-body/
- 129 https://jakearchibald.com/2016/link-in-body/
- 130 https://daniel.haxx.se/blog/2016/08/18/http2-connection-coalescing/
- 131 https://securityheaders.io/
- 132 https://www.smashingmagazine.com/2016/01/eliminating-known-security-vulnerabilities-with-snyk/
- 133 https://www.ssllabs.com/ssltest/
- 134 https://https.cio.gov/faq/
- 135 https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet
- 136 https://content-security-policy.com/
- 137 https://istlsfastyet.com
- 138 https://istlsfastyet.com
- 139 https://istlsfastyet.com
- 140 https://opensource.googleblog.com/2015/09/introducing-brotli-new-compression.html
- 141 https://github.com/google/brotli
- 142 http://caniuse.com/#search=brotli
- 143 https://samsaffron.com/archive/2016/06/15/the-current-state-of-brotli-compression
- 144 http://calendar.perfplanet.com/2016/enabling-brotli-even-on-cdns-that-dont-support-it-yet/
- 145 https://blog.codinghorror.com/zopfli-optimization-literally-free-bandwidth/
- 146 https://www.digicert.com/enabling-ocsp-stapling.htm
- 147 https://en.wikipedia.org/wiki/IPv4_address_exhaustion
- 148 https://www.google.com/intl/en/ipv6/statistics.html#tab=ipv6-adoption&tab=ipv6-adoption
- 149 https://www.paessler.com/blog/2016/04/08/monitoring-news/ask-the-expert-current-status-on-ipv6
- 150 https://www.cloudflare.com/ipv6/
- 151 https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2/
- 152 https://github.com/summerwind/h2spec
- 153 https://www.keycdn.com/blog/http2-hpack-compression/
- 154 https://www.smashingmagazine.com/wp-content/uploads/2016/12/h2spec-example-large-opt.png
- 155 https://www.smashingmagazine.com/wp-content/uploads/2016/12/h2spec-example-large-opt.png
- 156 https://github.com/summerwind/h2spec
- 157 https://github.com/lyzadanger/pragmatist-service-worker
- 158 https://jakearchibald.com/2014/offline-cookbook/
- 159 https://www.udacity.com/course/offline-web-applications--ud899
- 160 http://caniuse.com/#search=serviceworker
- 161 https://report-uri.io/
- 162 https://github.com/bramus/mixed-content-scan
- 163 https://umaar.github.io/devtools-optimise-your-web-development-workflow-2016/#/
- 164 https://www.youtube.com/watch?v=N33lYfsAsoU
- 165 http://gs.statcounter.com/#mobile_browser-as-monthly-201511-201611
- 166 https://www.webworldwide.io/
- 167 https://www.browserstack.com
- 168 http://www.webpagetest.org/
- 169 https://speedcurve.com/
- 170 https://newrelic.com/browser-monitoring
- 171 https://speedtracker.org
- 172 https://github.com/GoogleChrome/lighthouse
- 173 https://calibreapp.com
- 174 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pdf
- 175 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pages
- 176 https://github.com/drublic/checklist
- 177 http://jonyablonski.com/designers-wpo-checklist/