Front-End Performance Checklist 2017 (PDF, Apple Pages)

Front-End Performance Checklist 2017 (PDF, Apple Pages)

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.

(You can also just download the checklist PDF1 (0.129 MB) or download the checklist in Apple Pages2 (0.236 MB). Happy optimizing!)

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

  1. 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.

    9

    Lighthouse, a new performance auditing tool by Google.

    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.

    12

    Performance budget builder13 by Brad Frost.

    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.

  2. 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.

  3. 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

  1. 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.
  2. 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.
  3. Angular, React, Ember and co.

    Favor a framework that enables server-side rendering. Be sure to measure boot times in server- and client-rendered modes on mobile devices before settling on a framework (because changing that afterwards, due to performance issues, can be extremely hard). If you do use a JavaScript framework, make sure your choice is informed20 and well considered21. Different frameworks will have different effects on performance and will require different strategies of optimization, so you have to clearly understand all of the nuts and bolts of the framework you’ll be relying on. When building a web app, look into the PRPL pattern22 and application shell architecture23.
  4. 24

    PRPL stands for Pushing critical resource, Rendering initial route, Pre-caching remaining routes and Lazy-loading remaining routes on demand.
    25

    An application shell26 is the minimal HTML, CSS, and JavaScript powering a user interface.
  5. 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.
  6. 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

  1. Set your priorities straight.

    It’s a good idea to know what you are dealing with first. Run an inventory of all of your assets (JavaScript, images, fonts, third-party scripts and “expensive” modules on the page, such as carousels, complex infographics and multimedia content), and break them down in groups.

    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.

  2. 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 DomContentLoaded and the extras on the load event.

    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.

  3. 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).

    Progressive booting43

    Progressive booting44 means using server-side rendering to get a quick first meaningful paint, but also include some minimal JavaScript to keep the time-to-interactive close to the first meaningful paint.

    Client-side rendering or server-side rendering? In both scenarios, our goal should be to set up progressive booting45: Use server-side rendering to get a quick first meaningful paint, but also include some minimal JavaScript to keep the time-to-interactive close to the first meaningful paint. We can then, either on demand or as time allows, boot non-essential parts of the app. Unfortunately, as Paul Lewis noticed46, frameworks typically have no concept of priority that can be surfaced to developers, and hence progressive booting is difficult to implement with most libraries and frameworks. If you have the time and resources, use this strategy to ultimately boost performance.

  4. Are HTTP cache headers set properly?

    Double-check that expires, cache-control, max-age and 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.

  5. Limit third-party libraries, and load JavaScript asynchronously.

    When the user requests a page, the browser fetches the HTML and constructs the DOM, then fetches the CSS and constructs the CSSOM, and then generates a rendering tree by matching the DOM and CSSOM. If any JavaScript needs to be resolved, the browser won’t start rendering the page until it’s resolved, thus delaying rendering. As developers, we have to explicitly tell the browser not to wait and to start rendering the page. The way to do this for scripts is with the defer and async attributes in HTML.

    In practice, it turns out we should prefer defer to 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.

  6. Are images properly optimized?

    As far as possible, use responsive images56 with srcset, sizes and the <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 Accept headers). Sketch natively supports WebP, and WebP images can be exported from Photoshop using a WebP plugin for Photoshop59. Other options are available60, too.

    Responsive Image Breakpoints Generator61

    Responsive Image Breakpoints Generator6562 automates images and markup generation.

    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 srcset and sizes alone will reap significant benefits. On Smashing Magazine, we use the postfix -opt for image names — for example, brotli-compression-opt.png; whenever an image contains that postfix, everybody on the team knows that it’s been optimized.

  7. 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.

    Not good enough? Well, you can also improve perceived performance for images with the multiple71background72images73technique74.

  8. 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.

    79

    Zach Leatherman’s Comprehensive Guide to Font-Loading Strategies8077 provides a dozen of options for bettern web font delivery.

    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.

  9. 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-digest specification93 will negate the need to manually build these “cache-aware” servers.

  10. 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.

  11. 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.

  12. Warm up the connection to speed up delivery.

    Use skeleton screens, and lazy-load all expensive components, such as fonts, JavaScript, carousels, videos and iframes. Use resource hints110 to save time on 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 preconnect to dns-prefetch, and you’ll be cautious with using prefetch and 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).

HTTP/2 Link

  1. 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).

    HTTP/2120

    Eventually, Google plans to label all HTTP pages as non-secure, and change the HTTP security indicator to the red triangle that Chrome uses for broken HTTPS. (Image source121)

    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.

  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.

    On the one hand, you might want to avoid concatenating assets altogether, instead breaking down your entire interface into many small modules, compressing them as a part of the build process, referencing them via the “scout” approach124 and loading them in parallel. A change in one file won’t require the entire style sheet or JavaScript to be redownloaded.

    On the other hand, packaging still matters125 because there are issues with sending many small JavaScript files to the browser. First, compression will suffer. The compression of a large package will benefit from dictionary reuse, whereas small separate packages will not. There’s standard work to address that, but it’s far out for now. Secondly, browsers have not yet been optimized for such workflows. For example, Chrome will trigger inter-process communications126 (IPCs) linear to the number of resources, so including hundreds of resources will have browser runtime costs.

    Progressive CSS loading127

    To achieve best results with HTTP/2, consider to load CSS progressively129128, as suggested by Chrome’s Jake Archibald.

    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.

  3. 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.

  4. 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.
  5. 138

    Is TLS Fast Yet?139137 allows you to check your options for servers and CDNs when switching to HTTP/2.
  6. Is Brotli or Zopfli compression in use?

    Last year, Google introduced140Brotli141, 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.

  7. 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.
  8. 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.
  9. 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.
  10. h2spec154

    H2spec (View large version155) (Image source156)
  11. 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

  1. 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.
  2. Is your development workflow in DevTools optimized?

    Pick a debugging tool and click on every single button. Make sure you understand how to analyze rendering performance and console output, and how to debug JavaScript and edit CSS styles. Umar Hansa recently prepared a (huge) slidedeck163 and talk164 covering dozens of obscure tips and techniques to be aware of when debugging and testing in DevTools.
  3. 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.
  4. 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.

  1. 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.
  2. Prepare critical CSS for your main templates, and include it in the <head> of the page. (Your budget is 14 KB).
  3. Defer and lazy-load as many scripts as possible, both your own and third-party scripts — especially social media buttons, video players and expensive JavaScript.
  4. Add resource hints to speed up delivery with faster dns-lookup, preconnect, prefetch, preload and prerender.
  5. Subset web fonts and load them asynchronously (or just switch to system fonts instead).
  6. Optimize images, and consider using WebP for critical pages (such as landing pages).
  7. Check that HTTP cache headers and security headers are set properly.
  8. Enable Brotli or Zopfli compression on the server. (If that’s not possible, don’t forget to enable Gzip compression.)
  9. If HTTP/2 is available, enable HPACK compression and start monitoring mixed-content warnings. If you’re running over LTS, also enable OCSP stapling.
  10. If possible, cache assets such as fonts, styles, JavaScript and images — actually, as much as possible! — in a service worker cache.

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:

If you need alternatives, you can also check the front-end checklist by Dan Rublic176 and the “Designer’s Web Performance Checklist177” by Jon Yablonski.

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)

Footnotes Link

  1. 1 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pdf
  2. 2 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pages
  3. 3 https://www.smashingmagazine.com/2015/09/why-performance-matters-the-perception-of-time/#the-need-for-performance-optimization-the-20-rule
  4. 4 https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint
  5. 5 https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive
  6. 6 http://www.webpagetest.org/
  7. 7 https://github.com/GoogleChrome/lighthouse
  8. 8 https://www.smashingmagazine.com/2016/11/worlds-best-open-device-labs/
  9. 9 https://github.com/GoogleChrome/lighthouse
  10. 10 http://danielmall.com/articles/how-to-make-a-performance-budget/
  11. 11 http://bradfrost.com/blog/post/performance-budget-builder/
  12. 12 http://bradfrost.com/blog/post/performance-budget-builder/
  13. 13 http://bradfrost.com/blog/post/performance-budget-builder/
  14. 14 https://www.smashingmagazine.com/2015/10/rail-user-centric-model-performance/
  15. 15 http://info.meteor.com/blog/optimistic-ui-with-meteor-latency-compensation
  16. 16 https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index
  17. 17 https://www.soasta.com/blog/google-mobile-web-performance-study/
  18. 18 https://www.aaron-gustafson.com/notebook/insert-clickbait-headline-about-progressive-enhancement-here/
  19. 19 https://resilientwebdesign.com/
  20. 20 https://www.youtube.com/watch?v=6I_GwgoGm1w
  21. 21 https://medium.com/@ZombieCodeKill/choosing-a-javascript-framework-535745d0ab90#.2op7rjakk
  22. 22 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
  23. 23 https://developers.google.com/web/updates/2015/11/app-shell
  24. 24 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
  25. 25 https://developers.google.com/web/updates/2015/11/app-shell
  26. 26 https://developers.google.com/web/updates/2015/11/app-shell
  27. 27 https://www.ampproject.org/
  28. 28 https://instantarticles.fb.com/
  29. 29 https://www.smashingmagazine.com/2016/12/progressive-web-amps/
  30. 30 https://www.smashingmagazine.com/2015/11/static-website-generators-jekyll-middleman-roots-hugo-review/
  31. 31 https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/
  32. 32 https://jamstack.org/
  33. 33 https://www.smashingmagazine.com/2014/09/improving-smashing-magazine-performance-case-study/
  34. 34 http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
  35. 35 https://twitter.com/lukew/status/665288063195594752
  36. 36 https://medium.com/@richavyas/aha-moments-from-ngconf-2016-part-1-angular-2-0-compile-cycle-6f462f68632e#.8b9afnsub
  37. 37 https://webpack.github.io/docs/code-splitting.html
  38. 38 https://www.lucidchart.com/techblog/2016/09/26/improving-angular-2-load-times/
  39. 39 https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express/
  40. 40 http://redux.js.org/docs/recipes/ServerRendering.html
  41. 41 https://github.com/nolanlawson/optimize-js
  42. 42 https://twitter.com/tverwaes/status/809788255243739136
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/12/fmp-and-tti-opt.jpeg
  44. 44 https://aerotwist.com/blog/when-everything-is-important-nothing-is/
  45. 45 https://aerotwist.com/blog/when-everything-is-important-nothing-is/
  46. 46 https://aerotwist.com/blog/when-everything-is-important-nothing-is/#which-to-use-progressive-booting
  47. 47 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
  48. 48 https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers
  49. 49 https://jakearchibald.com/2016/caching-best-practices/
  50. 50 https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en
  51. 51 http://calendar.perfplanet.com/2016/prefer-defer-over-async/
  52. 52 https://github.com/h5bp/lazyweb-requests/issues/42
  53. 53 https://www.savjee.be/2015/01/Creating-static-social-share-buttons/
  54. 54 https://simplesharingbuttons.com
  55. 55 https://developers.google.com/maps/documentation/static-maps/intro
  56. 56 https://www.smashingmagazine.com/2014/05/responsive-images-done-right-guide-picture-srcset/
  57. 57 https://www.smashingmagazine.com/2015/10/webp-images-and-performance/
  58. 58 https://dev.opera.com/articles/responsive-images/#different-image-types-use-case
  59. 59 http://telegraphics.com.au/sw/product/WebPFormat#webpformat
  60. 60 https://developers.google.com/speed/webp/docs/using
  61. 61 https://www.smashingmagazine.com/wp-content/uploads/2016/12/responsive-image-breakpoints-generator-large-opt.jpeg
  62. 62 http://www.responsivebreakpoints.com/
  63. 63 https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/
  64. 64 http://caniuse.com/#search=client-hints
  65. 65 http://www.responsivebreakpoints.com/
  66. 66 http://cloudinary.com/documentation/api_and_access_identifiers
  67. 67 https://github.com/mozilla/mozjpeg
  68. 68 http://css-ig.net/pingo
  69. 69 https://kornel.ski/lossygif
  70. 70 https://jakearchibald.github.io/svgomg/
  71. 71 http://csswizardry.com/2016/10/improving-perceived-performance-with-multiple-background-images/
  72. 72 https://jmperezperez.com/medium-image-progressive-loading-placeholder/
  73. 73 https://manu.ninja/dominant-colors-for-lazy-loading-images#tiny-thumbnails
  74. 74 https://css-tricks.com/the-blur-up-technique-for-loading-background-images/
  75. 75 https://www.fontsquirrel.com/tools/webfont-generator
  76. 76 http://caniuse.com/#search=woff2
  77. 77 https://www.zachleat.com/web/comprehensive-webfonts/
  78. 78 https://pixelambacht.nl/2016/font-awesome-fixed/
  79. 79 https://www.zachleat.com/web/comprehensive-webfonts/
  80. 80 https://www.zachleat.com/web/comprehensive-webfonts/
  81. 81 https://github.com/typekit/webfontloader
  82. 82 https://www.filamentgroup.com/lab/font-events.html
  83. 83 https://github.com/filamentgroup/loadCSS
  84. 84 https://www.smashingmagazine.com/2015/11/using-system-ui-fonts-practical-guide/
  85. 85 https://www.smashingmagazine.com/2015/08/understanding-critical-css/
  86. 86 https://github.com/filamentgroup/criticalCSS
  87. 87 https://github.com/addyosmani/critical
  88. 88 https://www.filamentgroup.com/lab/performance-rwd.html
  89. 89 http://www.slideshare.net/Fastly/http2-what-no-one-is-telling-you
  90. 90 http://calendar.perfplanet.com/2016/http2-push-the-details/
  91. 91 https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXjqKGsCVNYHyLEXIxYMv0/edit
  92. 92 https://css-tricks.com/cache-aware-server-push/
  93. 93 http://calendar.perfplanet.com/2016/cache-digests-http2-server-push/
  94. 94 https://medium.com/@roman01la/dead-code-elimination-and-tree-shaking-in-javascript-build-systems-fb8512c86edf
  95. 95 http://www.2ality.com/2015/12/webpack-tree-shaking.html
  96. 96 https://github.com/giakki/uncss
  97. 97 https://github.com/geuis/helium-css
  98. 98 http://csswizardry.com/2011/09/writing-efficient-css-selectors/
  99. 99 https://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/
  100. 100 https://webpack.github.io/docs/code-splitting.html
  101. 101 http://rollupjs.org/
  102. 102 https://github.com/nolanlawson/rollupify
  103. 103 https://nolanlawson.com/2016/08/15/the-cost-of-small-modules/
  104. 104 http://caniuse.com/#search=contain
  105. 105 http://caniuse.com/#feat=will-change
  106. 106 https://aerotwist.com/blog/my-performance-audit-workflow/#runtime-performance
  107. 107 https://developers.google.com/web/tools/chrome-devtools/rendering-tools/
  108. 108 https://www.udacity.com/course/browser-rendering-optimization–ud860
  109. 109 https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
  110. 110 https://w3c.github.io/resource-hints
  111. 111 http://caniuse.com/#search=dns-prefetch
  112. 112 http://www.caniuse.com/#search=preconnect
  113. 113 http://caniuse.com/#search=prefetch
  114. 114 http://caniuse.com/#search=prerender
  115. 115 https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/
  116. 116 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
  117. 117 https://http2.github.io/faq/
  118. 118 http://caniuse.com/#search=http2
  119. 119 https://www.youtube.com/watch?v=RWLzUnESylc&t=1s&list=PLNYkxOF6rcIBTs2KPy1E6tIYaWoFcG3uj&index=25
  120. 120 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
  121. 121 https://security.googleblog.com/2016/09/moving-towards-more-secure-web.html
  122. 122 https://rmurphey.com/blog/2015/11/25/building-for-http2
  123. 123 https://www.youtube.com/watch?v=yURLTwZ3ehk
  124. 124 https://rmurphey.com/blog/2015/11/25/building-for-http2
  125. 125 http://engineering.khanacademy.org/posts/js-packaging-http2.htm
  126. 126 https://www.chromium.org/developers/design-documents/inter-process-communication
  127. 127 https://jakearchibald.com/2016/link-in-body/
  128. 128 https://jakearchibald.com/2016/link-in-body/
  129. 129 https://jakearchibald.com/2016/link-in-body/
  130. 130 https://daniel.haxx.se/blog/2016/08/18/http2-connection-coalescing/
  131. 131 https://securityheaders.io/
  132. 132 https://www.smashingmagazine.com/2016/01/eliminating-known-security-vulnerabilities-with-snyk/
  133. 133 https://www.ssllabs.com/ssltest/
  134. 134 https://https.cio.gov/faq/
  135. 135 https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet
  136. 136 https://content-security-policy.com/
  137. 137 https://istlsfastyet.com
  138. 138 https://istlsfastyet.com
  139. 139 https://istlsfastyet.com
  140. 140 https://opensource.googleblog.com/2015/09/introducing-brotli-new-compression.html
  141. 141 https://github.com/google/brotli
  142. 142 http://caniuse.com/#search=brotli
  143. 143 https://samsaffron.com/archive/2016/06/15/the-current-state-of-brotli-compression
  144. 144 http://calendar.perfplanet.com/2016/enabling-brotli-even-on-cdns-that-dont-support-it-yet/
  145. 145 https://blog.codinghorror.com/zopfli-optimization-literally-free-bandwidth/
  146. 146 https://www.digicert.com/enabling-ocsp-stapling.htm
  147. 147 https://en.wikipedia.org/wiki/IPv4_address_exhaustion
  148. 148 https://www.google.com/intl/en/ipv6/statistics.html#tab=ipv6-adoption&tab=ipv6-adoption
  149. 149 https://www.paessler.com/blog/2016/04/08/monitoring-news/ask-the-expert-current-status-on-ipv6
  150. 150 https://www.cloudflare.com/ipv6/
  151. 151 https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2/
  152. 152 https://github.com/summerwind/h2spec
  153. 153 https://www.keycdn.com/blog/http2-hpack-compression/
  154. 154 https://www.smashingmagazine.com/wp-content/uploads/2016/12/h2spec-example-large-opt.png
  155. 155 https://www.smashingmagazine.com/wp-content/uploads/2016/12/h2spec-example-large-opt.png
  156. 156 https://github.com/summerwind/h2spec
  157. 157 https://github.com/lyzadanger/pragmatist-service-worker
  158. 158 https://jakearchibald.com/2014/offline-cookbook/
  159. 159 https://www.udacity.com/course/offline-web-applications–ud899
  160. 160 http://caniuse.com/#search=serviceworker
  161. 161 https://report-uri.io/
  162. 162 https://github.com/bramus/mixed-content-scan
  163. 163 https://umaar.github.io/devtools-optimise-your-web-development-workflow-2016/#/
  164. 164 https://www.youtube.com/watch?v=N33lYfsAsoU
  165. 165 http://gs.statcounter.com/#mobile_browser-as-monthly-201511-201611
  166. 166 https://www.webworldwide.io/
  167. 167 https://www.browserstack.com
  168. 168 http://www.webpagetest.org/
  169. 169 https://speedcurve.com/
  170. 170 https://newrelic.com/browser-monitoring
  171. 171 https://speedtracker.org
  172. 172 https://github.com/GoogleChrome/lighthouse
  173. 173 https://calibreapp.com
  174. 174 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pdf
  175. 175 http://provide.smashingmagazine.com/performance-checklist/performance-checklist-1.0.pages
  176. 176 https://github.com/drublic/checklist
  177. 177 http://jonyablonski.com/designers-wpo-checklist/

↑ Back to topTweet itShare on Facebook