Preface: This article I in Denver translation plan together with translation of the article (thanks to the nuggets translation), I translated the third part, then check the second part, this article for the front end performance optimization technology is still relatively new and comprehensive, so decided to read it again in English texts, and then use a mind map to sort out the emphasis, the original English is pretty long, so

  • If you want to get a rough idea of what this article is about, check out the mind map I summarized
  • If you find this article helpful after reading the mind map, you can check out my own translation and other translations
  • If you have no difficulty in Reading English and feel my translation is not good, you can read the original English directly

If you have enough time to read the original English text, this article is based on the nuggets translated four articles +Other translated articles+ my own translation and modification. Because the translation we understand, there will be some mistakes, welcome to point out, I do not guarantee that the translation is not wrong, but have tried to translate, so welcome to read the Original English!! Welcome to read the original English!! Welcome to read the original English!!

We all know that performance is important, but do we really always know where our performance optimization bottlenecks are? Is it expensive JavaScript? Is the Web font slow? Or a bigger picture? Or is it too slow to render? In the following cases: Tree-shaking, scope splitting, code-splitting, intersection Observer and client Hints, CSS Containment, HTTP/2, and Service Workers are all conducive to performance optimization. And, most importantly, where do we start to improve our performance? And how to build long-lasting performance mechanisms.

The translator’s note:

  • tree-shaking:tree-shakingIs a new feature introduced in Webpack 2,tree-shakingIt is a method of dead code elimination (DCE), but it is not quite the same as the traditional method.tree-shakingFind the code you need and fill in the final result; Traditional DCE finds code that cannot be executed and cleans it from the AST. -How to evaluate the tree-shaking code optimization technology introduced in Webpack 2?
  • scope hoisting:scope hoistingIs a new feature of Webpack 3, also translated as “scope enhancement”. Webpack wraps all modules in functions and then implements a set of module loading, execution, and caching capabilities on its own for Code Splitting (including on-demand loading), hot module replacement, and other features. -New functionality in Webpack 3: Scope Collieries
  • code-splittingFor large Web applications, putting all the code in one file is inefficient, especially if you load some blocking code that is only used in certain circumstances. Webpack has a feature that separates your code into chunks, which can be loaded on demand. And that function iscode-splitting. -Use Code Splitting in Webpack for on-demand loading
  • intersection observer: Can automatically “see” whether an element is visible. This API is called “cross viewer” because the nature of visible is that the target element and the viewport intersect. -Tutorial on using the IntersectionObserver API
  • clients hints: Automatic response picture –Automatic responsive images with Client Hints
  • CSS containment: New CSS attribute Containment allows developers to limit the scope of browser style, layout, and paint work. -CSS Containment in Chrome 52
  • service workers: Implement offline page –Service worker concepts and usage

In the past, performance tuning was often considered at the end of the project, often deferred to the end of the project, so that the scope for tuning was narrowed down to tuning static files and tweaking some server configuration files. But now that performance optimization has changed a lot, it’s not enough.

Performance is not just a technical issue: it is important that design decisions be informed by performance when putting it into a workflow. Must be measure, monitor and improve performance, and the complexity of the network is growing also makes the tracking performance measurement was more difficult, because the measurement will be depending on the type of equipment, browser, protocol, network and delays and significant changes (CDN, ISP, cache, agent, firewall, load balancer and all play a role on the performance of the server).

Therefore, we must always keep performance optimization in mind — from the beginning of the project until the final release of the site. So we created a list of performance optimizations. (Hopefully fair and objective) 2018 Front End Performance Checklist – can help you figure out how to optimize your site, such as how to get faster response times, smooth user interactions and not lose bandwidth to users.

(You can also download just the PDF version of the 2018 Front-end Performance Improvements List (0.129MB) or download the Apple Pages version (0.236MB).)

Readiness: Planning and measuring

Small optimizations are also important to maintain performance, but keep in mind that we must have a clear goal, and measurable goals will influence any decisions along the way. There are several different patterns, and the following are all from your own perspective, so identify your own optimization priorities early on.

  1. Establish awareness of performance optimization

In many teams, front-end developers know exactly what the common potential problems are and what load modules should be used to fix them. However, as long as one side of the development or design side is at odds with the market, performance does not last long. So, take a look at common user complaints and see how improving performance can help solve these common problems.

You need to run performance experiments and measure the results on both mobile devices and desktops. It builds a case study tailored to your company using real data. In addition, being good at using data from case studies and experiments published on WPO Stats can help improve your understanding of the potential relationship between performance and business, as well as the impact of performance on user experience and business metrics. Just stating performance isn’t enough – you also need to set measurable and trackable goals to observe performance.

  1. The goal: To be at least 20 percent faster than your fastest competitor

According to psychological research, if you want your users to feel that your site is faster than your competitors’ sites, you need to be at least 20% faster. Study your main competitors, collect their performance on mobile and desktop, and set a threshold by which you can beat them. To get accurate results and goals, first study your analytics and see what your users are doing. You can simulate the 90th percent-user experience, test, collect data, build a table, and subtract another 20% from your target (i.e. performance budget). Now you have some measurable data before testing.

If you care about your budget and try to get the fastest interaction time with the smallest script, then you’re on your “front end optimization journey.” Lara Hogan’s guide on how to use a performance budget to approach a design can be a useful guide for designers, and both the performance budget calculator and Browser Calories can help create a budget (thanks to Karolina Szczur).

In addition to performance, consider the behavior of your customers who are best for your business. Set and discuss acceptable time thresholds for key actions, and set a “UX ready” user time mark that the entire team has agreed upon. In most cases, the user’s behavior involves many different departments, so following an acceptable schedule set up will avoid many problems. Ensure that the additional costs of additional resources and functionality are visible and known to other members.

In addition, as Patrick Meenan suggests, it is best to set up a load queue during the design process and be aware of the pros and cons of these orders. You need to prioritize the more important priorities and define the order in which they are prioritized. You should also know which ones can be deferred. Ideally, this queue should also reflect the load order of JS and CSS, which should be easy to handle during the build process once designed. Another thing to consider is the “in-between state” of the page while it is still loading (for example, when the Web font hasn’t finished loading).

Plan, plan, plan, plan. Say the important things three times! It’s easy to achieve if you optimize early, but it’s hard to maintain performance without a plan or setting realistic, company-specific performance goals.

  1. Choose the right metric

Not all measures are equally important. Research which metrics are most important for your application: Often, it’s about how fast you can start rendering the most important pixels (and their effects) and how quickly you can provide input to those rendered pixels with the fastest response. This will help you provide the best optimization results for subsequent work. In any case, instead of focusing on the entire page load time (such as onLoad and DOMContentLoaded time), prioritize the page load that is perceived by the user. That means focusing on a slightly different set of measures.

For the first time there is a difference between content rendering, visual integrity and interactionable time. From: @denar90

You can refer to the following measurements:

  • First effective render (FMP, the time it takes for the main content to appear on the page),
  • Significant render time (the time it takes to render the most important part of the page),
  • Interactivity time (TTI, where the page layout is stable, key page fonts are visible, and the main process is good enough to handle user input — the basic time mark is that the user can click and interact on the UI),
  • Input response, the time required for the interface to respond to user actions,
  • Speed Index, measures the Speed at which page content is filled. The lower the score, the better,
  • Custom metrics, determined by your business needs and user experience.

Steve Souders explains each measure in detail. In many cases, depending on your application’s usage scenario, interaction time and input response will be the most critical. But these metrics can vary: For the User interface of Netflix TV, for example, critical input responses, memory usage, and interactionable time are more important.

  1. Collect data from devices used by a representative group of users

In order to collect accurate data, we need to select the equipment to be tested as fully as possible. Preferably the Moto G4, or a mid-range Samsung device, or a mediocre device like the Nexus 5X. If you don’t have a device handy, you can use a throttling CPU (5 x deceleration) to limit network speeds (e.g., 150 ms round-trip latency, below 1.5 Mbps and above 0.7 Mbps) to simulate the mobile experience on a desktop device. Finally, switch to regular 3G, 4G and Wi-Fi. To make the impact of the performance experience even more noticeable, you can even use 2G or a throttled 3G network for faster testing.

Fortunately, there are a number of excellent options to help you automatically collect data and measure your site’s performance over a period of time based on these metrics. Keep in mind that good performance measurement requires a combination of passive and active monitoring tools:

  • Passive monitoring tool that simulates user interaction based on request (comprehensive tests like Lighthouse, WebPageTest)
  • Active monitoring tools, those that continuously record and evaluate user interactions (true user monitoring, such as SpeedCurve, New Relic — both tools also provide comprehensive testing)

The former is particularly useful during development because it allows continuous tracking as the product is used. The latter is useful in long-term maintenance because it helps you understand the performance bottlenecks that occur when you actually visit the site. Passive and active performance monitoring tools work together to provide a complete picture of application performance using the built-in RUM API for navigation timing, resource timing, drawing timing, long tasks, and more. For example, you can use PWMetrics, Calibre, SpeedCurve, mPulse, Boomerang, and sitespeed. IO, which are great choices for performance monitoring tools.

Note: It is always safer to choose a network-level restrictor outside the browser, such as DevTools, which has problems interacting with THE HTTP/2 push due to the way it is implemented (thanks Yoav!). .

  1. Share performance lists with your colleagues

To avoid misunderstandings, make sure everyone on your team is familiar with the list. Each decision has an impact on performance. Projects will greatly benefit from front-end developers correctly communicating performance value to the entire team. So that everyone is responsible for it, not just the front-end developers. Design decisions based on priorities defined in the performance budget and checklist.

Set realistic goals

  1. Control the response time within 100ms, control the frame rate at 60 frames/SEC

To make the interaction feel smooth, the interface has 100ms to respond to user input. Any longer than that and the user will think the application is slow. RAIL, a user-centric performance model that gives you robust goals. In order for the page to respond less than 100ms, the page must return control to the main thread no later than 50ms. The estimated input latency tells us that if we can reach this threshold, ideally it should be below 50ms. In areas like animation where performance is expensive, the best thing to do is to optimize as much as possible where you can. Minimize performance overhead where you can’t optimize.

At the same time, each frame of animation should be completed in 16 milliseconds, resulting in 60 frames per second (1 second ÷ 60 = 16.6 milliseconds) — preferably in 10 milliseconds. Because the browser takes time to draw the new frame onto the screen, your code should be completed within 16.6 milliseconds of firing. Be optimistic and use your free time wisely. Obviously, these goals apply to runtime performance, not load performance.

  1. SpeedIndex < 1250, interaction time on 3g < 5s, Critical file size < 170Kb (SpeedIndex < 1250, TTI < 5s on 3G, Critical File size Budget < 170Kb)

While this may be difficult to achieve, a good end goal is to have the first effective render below 1 second and a speed indicator value below 1250. Because we were simulating 400ms round-trip latency and 400KB transfer speed on a $200 Android phone (like the Moto G4) over a slow 3G network, we were aiming for less than 5s interactivity time and less than 2s reaccess time.

Note that when talking about interactibility times, it is a good idea to distinguish between first and continuous interactions to avoid misunderstanding between them. The former is the first point that appears after the main content has been rendered (the window needs at least 5s before the page begins to respond). The latter is the point at which you expect the page to respond to input all the time.

The first 14~ 15KB load of HTML is the most critical payload block — and the only part of the first round trip (which is one second with a 400 ms round trip delay) that can be delivered. In general, in order to achieve the above objectives, we must operate within the critical file size. After the maximum budget compression of 170 Kb (0.8-1MB decompression), it has taken up to 1s (depending on the resource type) to parse and compile. Slightly higher than this is fine, but keep them as low as possible.

However, you can increase the size of the binding budget. For example, you can set performance budgets in activities on the browser main thread, such as drawing time before starting rendering or tracking the front-end CPU. Tools like Calibre, SpeedCurve, and Bundlesize can help you keep your budget under control and integrate into your build process.

Definition of environment

  1. Do a good job in the selection of build tools and build (suitable for their own) build tools

Don’t worry too much about cool tech stacks these days. Use your build tool, whether it’s Grunt, Gulp, Webpack, Parcel, or a combination of tools, depending on your project. As long as you get results quickly and make sure your build process works. Then, you can choose the build tool.

  1. Incremental enhancement

The safe choice is to use incremental enhancements as a guiding principle for front-end architecture and project deployment. Design and build the core experience first, then enhance it with advanced features for capable browsers to create a resilient experience. If your site is running fast on a bad browser with a bad network and a bad display, it will only run faster on a fast browser machine with a fast network.

  1. Choose a strong performance benchmark

There are so many unknowns affecting loading — network, heat protection, cache retaking, third party scripts, parser blocking mode, read and write to disk, IPC Jank, plug-in installation, CPU, hardware and memory limits, L2/L3 cache, RTTS, images, Web font loading behavior differences — JavaScript Web fonts blocking default rendering and image loading consume a lot of memory. As the performance bottleneck moves from the server side to the client side, we as developers must consider all these unknowns more carefully.

With a 170KB budget that already included critical path HTML/CSS/JavaScript, router, state management, utilities, framework, and application logic, we had to thoroughly examine network transmission costs, parse/compile time, and run time to select our framework.

As Seb Markbage has pointed out, a good way to measure the start-up cost of a framework is to render the view first, then remove it, and then render it again, because it tells you how the framework is expanding.

The first rendering tends to preheat a bunch of slow-compiling code, and as it expands, larger branches can benefit. The second rendering basically emulates how code reuse on the page affects performance characteristics as the complexity of the page increases.

Not every project needs a framework. In fact, some projects can benefit from removing some frameworks altogether. Once you choose a framework, you will use it for at least a few years. So, if you need to use it, make sure your choice is well thought out and well understood. At least consider the cost of total size + initial resolution time before making a choice: lightweight options like Preact, Inferno, Vue, Svelte or Polymer work well. The size baseline of the framework will define the constraints for your application code.

Keep in mind that on mobile devices, expect a four – to five-fold speed decline compared to desktop computers. Because mobile devices have different GPU, CPU, memory, and battery features. Parsing times on mobile are 36% higher than on desktop devices. So always test on an average device that best represents the average user.

Different frameworks will have different effects on performance and require different optimization strategies. Therefore, you must clearly understand all the details of the framework you are relying on. When creating a Web application, refer to the PRPL pattern and the application shell architecture. The idea is simple: quickly render the interaction of the initial route with minimal code, then cache and pre-cache the resources using the service worker, and then load the required route asynchronously using lazy loading.

PRPL stands for keeping push critical resources, rendering initial routes, pre-caching remaining routes, and lazy loading necessary remaining routes.

The application shell is a minimal HTML, CSS, and JavaScript driven user interface.

  1. Do you need AMP and Instant Articles for your project?

AMP, or Accelerated Mobile Page, is a way to create lightweight web pages that load quickly, especially on mobile devices.

Depending on your organization’s priorities and strategy, you might consider using Google’s AMP, Facebook’s Instant Articles, or Apple’s Apple News. You can get good performance without using them, but AMP does provide a free CDN performance framework, and Instant Articles will increase your visibility and performance on Facebook.

For users, the main advantage of these technologies is to ensure performance, so sometimes they prefer AMP-/Apple News/Instant Pages links over “regular” and potentially bloated Pages. For content-oriented sites that mainly deal with a lot of third method content, these options greatly speed up rendering time.

For webmasters, these styles are discoverable across platforms and enhance visibility in search engines. You can also reuse AMP as your PWA data source to build progressive Web AMPs. What are the drawbacks? Obviously, within a walled area, developers can create and maintain separate versions of their content, preventing Instant Articles and Apple News from having actual URLs. (Thanks, Addy, Jeremy)

  1. Use CDN wisely

Depending on the amount of dynamic data you have, you can outsource some of your content to static site-generation tools like Jekyll, Hexo, and then push the static files into a CDN that simply provides a static version of the static files. So you can avoid making read and write requests to the database. You can even choose a static HOSTING platform based on a CDN to enrich your pages by adding interactive components to them as a sign of performance improvement (JAMStack).

Note that CDN can also host and offload dynamic content, so there is no need to limit the CDN’s service scope to static resources. The other thing to keep in mind is that whether or not your CDN performs content compression (GZip), content conversion, HTTP/2 transfers, and ESI (a markup language that can be used to divide web pages into separate cacheable entities), we still need to check these operations. This is because the above actions not only aggregate the static and dynamic content of the page at the EDGE of the CDN (where the server is closest to the user), but also perform other tasks.

Build optimization

  1. Set your priorities

You should know what your priorities are. Run all of your static resources (JavaScript, images, fonts, third-party scripts, and “expensive” modules in your pages, such as carousels, complex diagrams, and multimedia content) and group them.

Firstly, we need to make clear that assets can be divided into several categories, which can be roughly divided into:

  • For traditional browsers, define basic core functionality (e.g., fully accessible core content)
  • Improved functionality for multi-functional browsers (e.g. rich, perfect experience)
  • Other resources (resources that are not absolutely required and can be lazily loaded, such as Web fonts, unnecessary styles, carousel scripts, video players, social media buttons, large images)

We have published an article on Improving Smashing Magazine’s Performance that describes this approach in detail.

  1. Consider the “cutting-edge mustard” mode

Although this technology is very old, we can still use cutting-edge Mustard to enable traditional browsers to use core features and enhance the experience of modern browsers. Strictly limit the resources loaded: core features are loaded first, then promoted, and finally the rest. Note: This technique allows you to infer device functionality from the browser version, which we no longer do.

For example: in the developing world, cheap Android phones run mainly on Chrome, and they have limited memory and CPUS. The PRPL schema is a good choice. Finally, using the Device Memory Client Hints Header, we can more reliably identify low-end devices. Headers are now supported only in Blink (Blink supports client hints). Since device storage also has a JavaScript API that can be invoked in Chrome, one option is API-based feature detection, falling back on “conforming” technologies only if they are not supported (thanks, Yoav!). .

  1. Reduce the cost of parsing JavaScript

When working with a single page application, you need to initialize the application before your page can be rendered. Look for modules and techniques to speed up initial render time (e.g., how to debug React performance, and how to improve Angular performance), since most performance problems come from the initial parsing time of starting the application.

JavaScript has a cost, but it’s not necessarily file size that affects performance. The difference in parsing and execution times depends heavily on the hardware of the device. On a normal phone (Moto G4), parsing just 1MB (uncompressed) JavaScript takes about 1.3-1.4 seconds, which is about 15-20% of the time spent parsing on the phone. In performing the compilation process, only JavaScript preparation takes an average of 4 seconds, and First Meaningful Paint takes 11 seconds to show the main content of the page on mobile. Explanation: On low-end mobile devices, parsing and execution times can easily increase by two to five times.

Ember recently ran an experiment using binary templates as a clever way to avoid parsing overhead. These templates do not require parsing. (Thanks, Leonardo!)

This is the key to checking every JavaScript dependency, and tools like Webpack-Bundle-Analyzer, Source Map Explorer, and Bundle Buddy can help you do this. Measure JavaScript parsing and compilation times. Etsy’s DeviceTiming, a gadget that lets your JavaScript measure parsing and execution times on any device or browser. Importantly, while the size of the file is important, it is not the most important thing. Parsing and compilation times do not increase linearly as the script size increases.

Webpack Bundle Analyzer visualizes JavaScript dependencies.

  1. Are you using the ahead-of-time compiler?

Use the Ahead-of-time compiler to reduce the overhead of rendering from client to server, thus producing useful results quickly. Finally, consider using optimistic.js to wrap functions that can be called quickly (at the start of the app) for fast loading (although, it may not be necessary).

  1. Do you use tree-shaking, scope splitting, or code-splitting power

Tree-shaking is a way to clean up the build process by loading only the code that is actually used in production and cleaning up the unused imports in Webpack. With Webpack 3 and Rollup, we can also use scope escalation, which allows the tool to detect which imports can be upgraded or converted to an inline function. With Webpack 4, you can now use JSON Tree Shaking. UnCSS or Helium can help you remove unused CSS styles.

Also, you need to think about how to write efficient CSS selectors and how to avoid writing bloated and wasteful styles. You can also use Webpack to shorten class names and use separate scopes at compile time to rename CSS classes dynamically

Code-splitting is another Webpack feature that allows you to split your Code into “blocks” that you should load on demand. Not all JavaScript has to be downloaded, parsed, and compiled. Once you’ve identified the split point in your code, Webpack handles these dependencies and the output file. When an application sends a request, this basically ensures that the initial download is small enough and loads on demand. Also, consider using the preload-webpack-plugin to get the path of the code split, and then using or to prompt the browser to preload them.

Where is the point of separation defined? By tracking which CSS/JavaScript blocks are used and which are not. Umar Hansa explains how you can do this using Devtools’ Code Coverage.

If you’re not using Webpack, Rollup’s output is better than Browserify’s output. When using Rollup, it’s recommended that you look at Rollupify, It can convert ECMAScript 2015 Modules into a large CommonJS Module — because small modules can have surprisingly high performance overhead (depending on the packaging tool and module loading system choice).

Addy Osmani’s From Fast Defaults: Modern Loading best practices. Slide 76.

Finally, with ES2015 support getting better in modern browsers, consider using babel-preset-env to convert only ES2015+ features that are not supported in modern browsers. Then set up two builds, one for ES6 and one for ES5. We can use script type=”module” to enable browsers with ES modules to load files, whereas older browsers can load the traditional Script Nomodule.

For loadsh, using babel-plugin-lodash will only load modules that you use only in the source code. This could save you quite a bit of JavaScript load.

  1. Optimize it with the JavaScript engine you’re using

Look at the percentage of JavaScript engines in the user base, and then explore ways to optimize them. For example, when the optimized V8 engine is used in the Blink browser, Node.js run, and Electron, use a script stream for each script. Once the download starts, it allows the Async or defer scripts to be parsed in a separate background thread, thus increasing page load times by 10% in some cases. In fact, use

Caveat: Opera Mini does not support the defement script, so if you are working on development in India or Africa, defer will be ignored, blocking the rendering until the script loads (thanks Jeremy)! .

Progressive bootstrap: Uses server-side rendering to get the first effective draw, but also includes some minimal JavaScript necessary to keep the real-time interaction close to the first effective draw.

  1. Client rendering or server rendering?

In both scenarios, the goal should be to establish progressive guidance: to get the first effective draw using server-side rendering, but also to include some minimal JavaScript necessary to keep the real-time interaction close to the first effective draw. If the JavaScript is not acquired at the first effective drawing, the browser may lock the main thread while parsing, compiling and executing the newly discovered JavaScript, thereby limiting the interactivity of the site or application.

To avoid this, always separate the execution functions into asynchronous tasks and places where requestIdleCallback might be used. Consider the lazy loading part of the UI and use WebPack dynamic import support to avoid loading, parsing, and compiling overhead until the user really needs them (thanks Addy!). .

In essence, interaction time (TTI) tells us the time between navigation and interaction. Metrics are defined by the first five seconds after the initial content of the window is rendered, during which JavaScript tasks do not exceed 50ms. If a task of more than 50ms occurs, the search window of five seconds is restarted. Therefore, the browser will first assume that it is interactive, only to switch to a frozen state, and eventually switch back to interactive.

Once we reach interactivity, we can then launch the non-essential parts of the application on demand or when time permits. Unfortunately, as Paul Lewis mentioned, frameworks often have no concept of priority, so progressive bootloader is difficult to implement with most libraries and frameworks. If you have the time and resources, using this strategy can dramatically improve front-end performance.

  1. Do you limit the impact of third-party scripts?

With all the performance tuning in place, we often have no control over third-party scripts from business requirements. The metrics of third-party scripts are not affected by the user experience, so a single script will often end up calling a nasty, long third-party script, thus undermining dedicated efforts for performance. To control and mitigate the performance penalty of these scripts, it is not sufficient to load them asynchronously (possibly through defer) and accelerate them through resource prompts such as dnS-prefetch or preconnect.

As Yoav Weiss explains in his communication About Having to focus on third-party scripts, in many cases these scripts are dynamic for downloading resources. Resources vary between page loads, so we don’t know where the host is downloading resources from and what those resources are.

At this point, what are our options? Consider using service workers to download a resource with a timeout, and if the resource does not respond within a specified interval, return an empty response telling the browser to perform the page parsing. You can record or limit third party requests that fail and requests that do not comply with certain criteria.

Another option is to establish a content security policy (CSP) to limit the impact of third-party scripts, such as not allowing audio and video downloads. The best option is to embed the script in the iframe environment with

For example, it might have to allow scripts to run

To stress test third parties, do a bottom-up summary of page performance on DevTools to test what happens if a request is blocked or times out, for the latter you can use WebPageTest’s Blackhole server 72.66.115.13. You can specify a specific domain name in your hosts file. It is best to have a master host and use a single host name, but at the same time generate a request map that is exposed to fourth party invocation and detection when the script changes.

Harry Roberts

  1. Is the HTTP cache header set properly?

Again, check that the Expires, cache-Control, max-age, and other HTTP cache headers are set correctly. In general, resources should be cacheable, whether for a short time (whether they are likely to change) or indefinitely (whether they are static). You can simply change the version in their URL when you need to update them. Disabling the last-modified header on any resource results in an IF-modified-since query, even If the resource is in the cache. Same as Etag, even if it is in use.

Use the cache-control: Immutable (designed to cache fingerprinted static resources) solves client revalidation issues (as of December 2017 in FireFox, Edge, and Safari; Only FireFox supports this in HTTPS). You can also use Heroku’s HTTP Caching header, Jake Archibald’s “Caching Best Practices”, and Ilya Grigorik’s HTTP Caching Primer as guides. Also, paying attention to different headers, especially when it comes to CDN, and paying attention to and being aware of key headers can help avoid additional validation if the new request is slightly different, but not necessarily from the previous request standard (thanks, Guy!). .

Static resource optimization

  1. Do you use Brotli or Zopfli for plain text compression?

In 2005, Google introduced Brotli, a new open source lossless data compression format that is now supported by all modern browsers. Brotli is actually more effective than Gzip and Deflate. The compression speed can be very slow, depending on the Settings. But a slow compression process improves the compression rate, and you can still decompress quickly. Of course, decompression is fast.

The browser is used only when the user accesses the website through HTTPS. Brotli isn’t pre-installed on some servers yet, and it’s hard to deploy if you don’t build NGINX and UBUNTU yourself. But it’s not that hard. In fact, some CTNS are supported, and it is even possible to enable Brotli through the server without CTNS.

At the highest levels of compression, Brotli becomes so slow that the time it takes for the server to start sending a response while waiting for dynamically compressed resources might invalidate our optimization for file size. However, for static compression, a high compression ratio is preferred — (thanks Jeremy!)

Alternatively, you can consider using Zopfli’s compression algorithm to encode data in Deflate, Gzip, and Zlib formats. Zopfli’s improved Deflate encoding benefits any file compressed using Gzip, as the file size is 3 to 8 percent smaller than the most powerful compression using Zlib. The problem is that it takes about 80 times longer to compress files. This is why while using Zopfli is a good idea, it doesn’t change much. Files need to be designed to be compressed once and downloaded multiple times.

Better yet, you can bypass the cost of dynamically squeezing static resources. Both Brotli and Zopfli can be used for plaintext transport – HTML, CSS, SVG, JavaScript, etc.

What are the methods? Dynamically compress HTML at the highest levels and Brotli levels 1-4 using Brotli+Gzip to pre-compress static resources. Also, check if Brotli supports CDN (KeyCDN, CDN77, Fastly). Make sure the server can handle the content using Brotli or Gzip. If you cannot install or maintain Brotli on your server, use Zopfli.

  1. Is the image properly optimized?

Use response images through srcset, sizes and elements whenever possible. You can also use webp-formatted images (supported by Chrom, Opera, Firefox Soon) through the element, Either a JPEG callback (see Andreas Bovens’ Code snippet) or through content negotiation (using the Accept header).

Sketch itself supports WebP and WebP images can be exported from PhotoShop using the WebP plug-in. There are other options, too. If you’re using WordPress or Joomla, there are extensions that can easily support WebP, such as Optimus and Cache Enabler (via Cody Arsenault).

You can still use Client Hints, but still need to get some browser support. Don’t have enough resources to support responsive graphics? Use a breakpoint generator or a service like Cloudinary to automatically optimize your images. Also, in many cases, using just SRcset and SIZES will work well.

Response image breakpoint generator automatically generates image and tag generation.

  1. Image optimization advanced

Now that there’s a critical landing page, it’s critical to have a specific image load speed, make sure JPEGs are progressive and use Adept, mozJPEG (to improve start rendering time by manipulating scan levels) or Guetzli compression, Google’s new open source encoder focuses on sensory performance, And borrow from Zopfli and WebP. The only downside: slow processing time (one minute per megapixel CPU). For PNG, we can use Pingo, and svgo, and for SVG, we can use Svgo or SVGOMG

Each image optimization article will explain, but always remind, to keep vector resources clean and tight. Make sure to clean up unused resources, remove unnecessary metadata, and reduce the number of waypoints in the artwork (and thus reduce the SVG code). (Thanks, Jeremy!)

So far, these optimizations cover only the basics. Addy Osmani has published a very detailed guide to basic image optimization that dives into the details of image compression and color management. For example, you can blur unnecessary parts of an image (by applying a Gaussian Blur filter to it) to reduce the file size, and eventually you can even start removing colors or turning the image black and white to further reduce the image size. For background images, a photo quality of 0 to 10% exported from Photoshop is also absolutely acceptable.

What about giFs? Instead of the heavy GIF animations that affect rendering performance and bandwidth, we can use a looping HTML5 video. Although

Good news: Hopefully soon we’ll be loading videos using . Early tests show that img tags display more than 20 times faster and parse more than 7 times faster than giFs of the same size.

Not good enough? Then, you can also use multiple background image technology to improve image perception performance. Keep in mind that reducing contrast and blurring unnecessary details (or eliminating colors) can also reduce file size. Do you need to enlarge a small photo without distortion? Consider using letsenhance.io

Zach Leatherman’s comprehensive guide to Font Loading Strategies offers more than a dozen options for better font sending on the Web

  1. Are Web fonts optimized?

The first question to ask is whether you can do without UI system fonts. If you can’t, you’ll most likely use a Web Web font, which will contain glyphs and extra features and boldness that you don’t need. You can obtain Web font subsets or subsets from font design companies, and if you are using an open source font (for example, by including only Latin with certain particular accented glyphs), you can reduce the file size of only part of the Web font by selecting it.

WOFF2 support is very good, for browsers that do not support WOFF2, you can use WOFF and OTF as alternatives to browsers that do not support it. Alternatively, choose a strategy from Zach Leatherman’s Comprehensive Guide to Font Loading Strategies (code fragments can also be used as Web font loading fragments) and cache fonts persistently using server caching. Do you feel like you’ve achieved something? Pixel Ambacht has a quick tutorial and case study to get your fonts in order.

If you can’t get fonts from your server and rely on third-party hosts, be sure to use the font loading event (or the Web font loader for browsers that don’t support it) FOUT over FOIT; Start rendering the text immediately and load the fonts asynchronously — you can also use loadCSS. You can also get rid of a locally installed OS font and use a variable font.

What is a bug-free font loading strategy? Start with the font-display, then go to the Font-loading API, then Bram Stein’s Font-face Observer (thanks Jeremy!). If you’re interested in measuring the performance of Font loading from a user’s perspective, Andreas Marschke explores performance tracking using the Font API and UserTiming API

Also, don’t forget to include font-display: The Optional descriptor provides flexible and fast font fallback, unicoid-range splits large fonts into smaller, language specific fonts, and Monica Dinculescu’s font style matcher addresses the size differences between the two fonts. The problem of vibration on the layout is minimized.

To optimize the delivery

  1. Do you load JavaScript asynchronously?

When a user requests a page, the browser gets the HTML and constructs the DOM, then gets the CSS and constructs the CSSOM, and then generates a render tree by matching the DOM and CSSOM. If any JavaScript needs to be resolved, the browser will not start rendering the page until the JavaScript is resolved, thus delaying rendering. As developers, we must explicitly tell the browser not to wait and to start rendering the page immediately. The method to do this for the script is to use the DEFER and async properties in the HTML.

As it turns out, we should change async to defer (since Ie9 and below does not support async). Also, as mentioned above, limit the impact of third-party libraries and scripts, especially using social share buttons and embedded

  1. Do you use lazy loading and use Intersection Observer for expensive JS?

If you need to lazily load images, videos, AD scripts, A/B test scripts, or any other resource, you can use the Intersection Observer API, which provides A way to asynchronously view the target elements against their ancestor elements or the viewinterfaces of the top-level document. Basically, you need to create a new IntersectionObserver object that accepts a callback function and a set of options. Then we add a target to look at.

The callback function is executed when the target becomes visible or invisible, so when it intercepts the viewport, it can start taking some action before the element becomes visible. In fact, we can control precisely when the observer’s callback is called, using the rootMargin and threshold (a number or array of numbers representing a percentage of the target’s visibility). Alejandro Garcia Anglada has published a simple tutorial on how to actually implement it.

You can even take your web pages to the next level by adding progressive image loading to them. Similar to Facebook, Pinterest and Medium, you can load low-quality or blurry images first, and then as the page continues to load, For a placeholder, replace their clear versions with the LQIP (Low Quality Image Placeholder) technique proposed by Guy Podjarny. (Please refer to Zhihu)

If the technology improves the user experience, the view is different, but it certainly improves the time it takes for the first meaningful drawing. We can even automate this by using SQIP to create lower-quality versions of images as placeholders for SVG. These placeholders can be embedded in HTML because they can naturally be compressed using text compression methods. In his article, Dean Hume describes how this technique can be implemented using the Intersection Observer.

What about browser support? Decent, with Chrome, Firefox, Edge and Samsung Internet is already supported. WebKit is currently under development. What if the browser doesn’t support it? If you don’t support Intersection observers, you can still load a polyfill lazily or load an image immediately. There’s even a library.

In general, lazy loading is used to handle all the costly components such as fonts, JavaScript, rounds, videos, and iframes. You can even tailor your content to the quality of your network. API of network information, especially the navigator. Connection. EffectiveType (62 +) Chrome use RTT and down link value to more accurately represent data connection and the user can handle. You can use it to completely remove video autoplay, background images or Web fonts so that the connection is too slow.

  1. Do you load critical CSS first?

To ensure that the browser starts rendering the page as soon as possible, it is common to collect all the CSS needed to start rendering the first visible part of the page (called “key CSS” or “first screen CSS”) and add it inline to the of the page, thereby reducing round trips. Due to the limited size of switch packages during the slow start phase, the budget for critical CSS is about 14 KB.

Beyond that, browsers will need to make extra rounds to get more style. CriticalCSS and Critical do this. You may need to do this for every template you use. If possible, consider using the conditional inline method used by the Filament Group.

With HTTP/2, critical CSS can be stored in a separate CSS file and delivered via server push without increasing the HTML size. The problem is that server push is cumbersome because there are many issues and race conditions in the browser. It has been unsupported and has had some caching issues (see [Hooman Beheshti’s Presentation] on page 114). In fact, the effect can be negative, swelling the network buffer and preventing real frames in the document from being transmitted. Also, because TCP starts slowly, it seems that server push is more effective on hot connections.

Even with HTTP/1, having critical CSS in a separate file in the root directory can be beneficial, and sometimes even more efficient than caching and inlining. Chrome requests this page by sending an HTTP connection to the root directory, so you don’t need a TCP connection to get the CSS (thank You, Philip!).

One thing to note is that unlike preload, which can trigger preloading from any domain, you can only push resources from your own domain or domains that you authorize. Once the server gets the first request from the client, it can start. The server pushes the resource into the cache and deletes it when the connection terminates. However, because HTTP/2 connections can be reused across multiple tabs, pushed resources can also be declared by requests from other tabs (thanks to Inian!). .

Currently, the server does not have an easy way to know if the resource being pushed is already in the user’s cache, so each user’s access continues to push the resource. Therefore, you may need to create a cache monitoring HTTP/2 server push mechanism. If they are extracted, you can try to get them from the cache to avoid pushing them again.

Keep in mind, however, that the new cache-Digest specification does not need to manually establish such a “caches aware” server; essentially a new frame type declared in HTTP/2 can represent the contents of that host. Therefore, it is also particularly useful for CDN.

For dynamic content, while the server takes some time to generate a response, the browser cannot make any requests because it is unaware of any sub-resources that the page may reference. In this case, we can warm up the connection and increase the TCP congestion window size so that future requests can complete more quickly. Also, all inline configurations are a better choice for server push. In fact, Inian Parameshwaran did a pretty good dive into HTTP/2 Push and HTTP Preload, with all the details you might need. Is the server pushing or not pushing? You can read Colin Bendell’s Should I Push? .

Bottom line: As Sam Saccone says, preload is good for bringing the start download time of the resource closer to the initial request, while server push is a full RTT (or more, depending on your server response time — if you have a server that can prevent unnecessary push.

Do you use stream responses? With streaming, the HTML rendered in the initial navigation request takes full advantage of the browser’s streaming HTML parser.

  1. Do you use stream responses?

Often forgotten and ignored, Streams provides an interface for reading or writing blocks of data asynchronously, with only a portion of the data likely to be available in memory at any given time. Basically, as soon as the first block of data is available, they allow the original requested page to start processing the response and gradually display the content using a parser optimized for the flow.

We can create a stream from multiple sources. For example, instead of providing an empty UI shell and having it fill in, you can have the server build a shell from the cache and the content from the network stream. As Jeff Posnick points out, if your Web application is supported by a CMS, then the server renders THE HTML by stitching parts of the template together, the model translates directly to using streaming responses, and the template logic replicates from the server rather than yours. The Year of Web Streams article by Jake Archibald focuses on how to build it. The performance gains are significant.

An important advantage of streaming the entire HTML response is that the HTML rendered during the initial navigation request can take full advantage of the browser’s streaming HTML parser. HTML blocks inserted into a document after the page loads (as common as content populated with JavaScript) do not take advantage of this optimization.

What about browser support? Chrome 52+, Firefox 57, Safari, and Edge support this API and the server already supports all modern browsers.

  1. Do you use save-data to store Data?

Especially when working in emerging markets, you may want to consider optimizing the experience where users choose to save data. The save-Data client prompt request header allows us to customize the application and payload for users with cost and performance constraints. In fact, you can rewrite requests for high DPI images to low DPI images, remove web page fonts and fancy effects, turn off video autoplay, server push, and even change the way markup is provided.

The header is currently only supported by Chromium, the Android version of Chrome or the Data Saver extension on desktop devices. Finally, you can use the Service Worker and Network Information APIS to provide low/high resolution images based on the Network type.

  1. Have you activated the connection to speed up transmission?

Use resource prompts to save time, such as dnS-prefetch (executing A DNS query in the background), preconnect (telling the browser to do a connection handshake in the background (DNS, TCP, TLS)), Prefetch (telling the browser to request a resource) and preload (fetching resources in advance without executing them).

Recently, we will at least use preconnect and DNS-prefetch, and we will be careful with prefetch and preload; The former can only be used if you’re pretty sure what the user will need next (similar to a purchase channel). Note that prerender has been deprecated and is no longer supported.

Note that even with Preconnect and DNS-Prefetch, the browser limits the number of hosts it will find or connect to in parallel, so it’s best to sort them by priority (thanks Philip!). .

In fact, using resource hints is probably the easiest way to improve performance, and it works. When should you use it? As Addy Osmani has explained, we should preload to determine which resources will be used in the current page. Prefetch resources that may be used for future pages, such as Webpack packages needed for pages that the user has not yet accessed.

Addy’s article on load priorities in Chrome shows how Chrome accurately parses resource hints, so once you’ve decided which resources are important for rendering your page, you can give them a higher priority. You can start the “Priority” column in the Chrome DevTools Web request table (or Safari Technology Preview) to see the priority of your requests.

Priority column in DevTools. Image courtesy of Ben Schwarz, Important request

For example, since fonts are often an important resource on a page, it’s best to use Preload to ask the browser to download them. You can also load JavaScript dynamically, effectively performing lazy loading. Also, because receives a media attribute, you can selectively load resources based on the @media query rule.

A few caveats: Preload can move the download time of a resource to the start of the request, but these preloaded resources cached in memory are bound to the page where the request was sent, meaning that the preloaded request is not shared by the page. Also, preload works well with the HTTP cache: if the cache hits, the network request is not sent.

Therefore, it is also useful for later discovered resources, such as a Hero image loaded via background-image, inlining key CSS (or JavaScript), and preloading other CSS (or JavaScript). In addition, the preload tag can only launch preload if the browser receives HTML from the server and the preload tag is found by the previous parser. Since we don’t wait for the browser to parse the HTML to start the request, it’s faster to preload through the HTTP header. Early hints will help you go one step further and start preloading before sending the HTML response header.

Note: If you are using preload, as must be defined or nothing will load. Also, preloading fonts without the crossorigin property will get it twice

  1. Did you optimize the rendering performance?

Use CSS containment to isolate expensive components – for example, limiting browser styles, layout and painting for non-canvas navigation, and the scope of third-party components. Make sure there is no lag in scrolling the page, or when an element is animated, consistently at 60 frames per second. If that’s not possible, at least keep frames per second in the 60 to 15 range. Use the WILL-change CSS to notify the browser which attribute of which element is about to change.

In addition, evaluate runtime rendering performance (for example, using DevTools). Get started by taking Paul Lewis’s free Udacity course on browser rendering optimization and Emily Hayman’s article on Optimizing Web animation and interaction.

Also, we have Sergey Chikuyonok’s article on how to properly use GPU animation. Note: Changes to the GPU-Composited layer are minimal, if you can trigger compositing with “opacity” and “distortion” then you’re on the right track.

  1. Have you optimized the rendering experience?

The order in which components are displayed on the page and how we provide resources to the browser are important, but the role of performance awareness should also not be underestimated. The concept involves the psychology of waiting, primarily to keep the user busy while something else happens. This involves perception management, starting first, finishing early, and tolerance management.

What does it all mean? We can try to always be one step ahead of the customer when loading resources, so we put a lot of processing in the background and the response is quick. To get the customer involved, we can use skeleton screens (demos) instead of loading instructions and adding some animations/transitions to cheat the user experience when there is no more optimization to do.

HTTP/2

  1. Migrate to HTTPS, then open HTTP/2.

The move to HTTP/2 is inevitable in an environment where Google is proposing to move towards more secure web pages and Chrome will consider (all HTTP) web pages “insecure”. HTTP/2 is very well supported so far, and, in some scenarios, using HTTP/2 will work wonders. Once running over HTTPS, you can at least get a significant performance boost for service workers and server push.

Eventually, Google plans to mark all HTTP pages as insecure and change the HTTP security indicator for the HTTPS in question to a red triangle. (Photo source)

The most time-consuming task will be to migrate to HTTPS. Depending on how big your HTTP/1.1 user base is (that is, users who use older operating systems or browsers), you will have to send different builds for older browser performance optimization, which requires you to use different build processes. Note: Starting the migration and new build process can be tricky and time consuming. Everything that follows is developed for those who have previously cut HTTP/2 environments or are about to do so now.

  1. Deploy HTTP/2 correctly.

Again, before you start requesting resources using HTTP/2, you need to understand how you’ve been requesting resources before. You also need to find a balance between loading large modules and loading small modules in parallel. . In the end, the best request is still no request, but the goal is to find a good balance between transferring resources quickly and caching.

On the one hand, you might want to avoid merging all the resources and instead break up the entire interface into many smaller modules, then compress those modules during the build process, and finally reference and load those modules in parallel via the “scount” approach method. This way, a change to a file does not require a re-download of the entire stylesheet or JavaScript. This also minimizes parsing time and keeps the load on individual pages low.

On the other hand, packing is still important. First, compression will benefit. In the process of compressing large files, the directory reuse feature is used to optimize performance, while small individual files do not. There is standard work to solve this problem, but it’s not nearly enough right now. Second, browsers have not yet been optimized for this kind of workflow. Chrome, for example, triggers inter-process communications (IPCs) that are linear to the number of resources, so containing hundreds of resources on a page can cost the browser performance.

To get the best results with HTTP/2, consider loading CSS incrementally, as recommended by Chrome’s Jake Archibald.

You can try loading CSS incrementally. Obviously, by doing this, this is not good for HTTP/1.1 users, so when you deploy HTTP/2, you may need to create and send headers for different browsers that support the HTTP protocol, and that’s just the slightly more complicated part of the deployment process. You can get around this by using HTTP/2 connection coalescing, which lets you use domain name sharing in an HTTP/2 environment), but achieving this goal is difficult in practice.

How do you do that? If you’re running over HTTP/2, sending 6-10 packets is an ideal compromise (not too bad for older browsers). For your own site, you can experiment and measure to find the best compromise.

  1. Do your services and CDNs support HTTP/2?

Different services and CDNs may have different support for HTTP/2, but you can use TLS to see your alternative services, or to quickly see the performance of your service and the features you want it to support. The TLS tool has the following functions:

Is TLS Fast Yet? Allows you to check your server and CDN options when you switch to HTTP /2.

  1. Is OCSP stapling enabled?

You can accelerate TLS handshakes by starting OCSP stapling on your service. The Online Certificate Status Protocol (OCSP) was proposed to replace the Certificate Deregistration List (CRL) protocol. Both protocols are used to check whether an SSL certificate has been withdrawn. However, THE OCSP protocol does not require the browser to spend time downloading and then searching for authentication information in the list, thus reducing handshake time.

  1. Have you adopted IPv6?

Because IPv4 is running out and major mobile networks are rapidly adopting IPv6 (the U.S. has reached the 50% threshold for IPv6 usage), it’s a good idea to update your DNS to IPv6 for the future. You can run both IPv6 and IPv4 as long as you ensure dual-stack support is available on the network. After all, IPv6 is not backward compatible. Studies have shown that because of IPv6’s built-in NDP and routing optimizations, sites can load 10 to 15 percent faster.

  1. Did you use the HPACK compression algorithm (for HTTP response header compression)?

If you use HTTP/2, double check to make sure your service implements HPACK compression for the HTTP response header to reduce unnecessary overhead. Because HTTP/2 services are relatively new, they may not fully support the specification; HPACK is an example. You can check with the H2spec, a great (if technically detailed) tool. HPACK works.

H2spec (View large version) (Image source)

H2spec (Image source)

  1. Ensure server security

Against the backdrop that all browsers that implement HTTP/2 run on TLS, if you encounter the following issues:

  • A security warning appears in the browser
  • Some elements on the page don’t work.

Well, you need to

  • Double-check the security-related HTTP headers to see if they are set correctly
  • Using tools to eliminate known vulnerabilities,
  • Check your certificate to see if it is invalid
  • Ensure that all external plug-ins and trace scripts are loaded over HTTPS, cross-site scripting is not allowed
  • The strict-transport-security and Content-security-policy request headers in HTTP are correctly set.
  1. Are service workers used for caching and for network rollback?

No network performance optimization can be faster than the local cache on the user’s machine. If your site is running over HTTPS, see the “Practical Guide to Using Service Workers”. The service worker is used for the purpose of caching static resources and storing offline resources (even offline pages). It also teaches you how to retrieve data from the user’s device, meaning that you now don’t need to request previous data over the network. Also, check out Jake’s Offline Cookbook and Udacity free course “Offline Web Applications.” Browser support? As mentioned above, it’s widely supported (Chrome, Firefox, Safari TP, Samsung Internet, Edge 17+), but it’s the web anyway. Does it help performance? Yes, Service Workers do improve performance.

Testing and monitoring

  1. Have you tested it in proxy browsers and older browsers?

Testing in Chrome and Firefox is not enough. You should find out how your site works in proxy browsers and older browsers. For example, UC Browser and Opera Mini have a significant market share (35%) in Asia. Measure average network speeds in countries of interest to avoid “big surprises” in the future. Test network throttling and simulate a high DPI device. BrowserStack is great, but test it on a real device.

K6 lets you write performance test cases the same way you write unit tests.

  1. Is continuous monitoring enabled?

Having a private instance of WebPagetest is always good for fast and unlimited testing. However, a continuous monitoring tool with automatic alerts will give you a more detailed performance description. Set your own user timing markers to measure and monitor specific business metrics. Also, consider adding automated performance regression alerts to monitor changes over time.

Use the RUM solution to monitor performance over time. For automated unit-like load testing tools, you can use the K6 scripting API. Also, check out SpeedTracker, Lighthouse, and Calibre.

Quick scheme

This list is so comprehensive that it can take a long time to complete all the optimizations. So if you only had an hour to make a major improvement, what would you do? Let’s boil it all down to 10 low-hanging fruits. Obviously, before you start and after you finish, measure the results, including the start rendering time and the speed index at 3G and cable connections.

  1. Measure the experience of the actual environment and set appropriate goals. A good goal is: first meaningful drawing < 1 s, speed index < 1250, interaction on slow 3G networks < 5s, and TTI < 2s for repeated access. Optimized render start time and interaction time.

  2. Prepare the critical CSS for your master template and include it in the of the page. (Your budget is 14 KB). For CSS/JS, the file size does not exceed 170 KB gzipped (0.8-1 MB after decompression).

  3. Lazy-load as many scripts as you can, including your own and third-party scripts — especially social media buttons, video players, and time-consuming JavaScript scripts.

  4. Add resource prompts and use DNS-LOOKUP, preconnect, prefetch, and preload to speed up transfers.

  5. Separate the Web fonts and load them asynchronously (or switch to the system fonts).

  6. Optimize the image, and consider using WebP on important pages, such as the login page.

  7. Check that the HTTP cache header and security header are set correctly.

  8. Enable Brotli or Zopfli compression on the server. (If you can’t, don’t forget to enable Gzip compression.)

  9. If HTTP/2 is available, enable HPACK compression and enable mixed content warning monitoring. If you are running LTS, you can also enable OCSP stapling.

  10. Cache as many assets as possible in the Service worker cache, such as fonts, styles, JavaScript, and images.

List download (PDF, Apple Pages)

With this list in mind, you’re ready for any kind of front-end performance project. Feel free to download a printed PDF version of the list, as well as an editable Apple page document to customize the list you need:

  • Download the Checklist PDF (PDF, 0.129MB)
  • Download the Checklist in Apple Pages (.pages, 0.236MB)

If you need other options, you can also refer to Rublic’s front-end checklist and Jon Yablonski’s “Designer’s Web Performance Checklist.”

Set off!

Some optimizations may be beyond your work or budget, or may be overly overused due to the need to deal with legacy code. No problem! Use this list as a general (and hopefully comprehensive) guide, and create your own list of questions that are appropriate for your environment. But most importantly, test and weigh your own projects to identify problems before tuning. Good luck with 2018!

Many thanks to Guy Podjarny, Yoav Weiss, Addy Osmani, Artem Denysov, Denys Mishunov, Ilya Pukhalski, Jeremy Wagner, Colin Bendell, Mark Zeman, Patrick Meenan, Leonardo Losoviz, Andy Davies, Rachel Andrew, Anselm Hannemann, Patrick Hamann, Andy Davies, Tim Kadlec, Rey Bango, Matthias Ott, Mariana Peralta, Philipp Tellis, Ryan Townsend, Proof reading of this article by Mohamed Hussain S H, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson, Aleksey Kulikov and Rodney Rehm, Thanks also to our wonderful community for sharing the techniques and experiences they have learned from their performance tuning work for everyone to use. You are truly amazing!