Hey, here’s a Web performance optimization map for you

Berwin is a member of the W3C Performance Working Group and a senior front end engineer for 360 Navigation. Vue. Js early user, author of Vue. Js in Its simplest form (currently being published).

github.com/berwin

We all know that performance is important for Web applications. However, the knowledge of performance optimization is vast and cluttered. It is often unclear what performance tuning entails and what the performance bottlenecks are.

Not those experienced in performance tuning

In fact, there are many aspects of Web performance that can be optimized, and the knowledge involved can be roughly divided into several categories: metrics, coding optimization, static resource optimization, delivery optimization, build optimization, and performance monitoring.

Figure 1. Performance optimization classification

This article mainly introduces what you need to do and what you need to consider for performance optimization. The goal is to create a macro map in the reader’s mind.

We will not describe how each optimization project works. PS: There will be a series of articles to introduce specific optimization operations under different optimization categories in more detail.

1. Metrics and goal setting

Before performance tuning, we need to choose the right metrics (performance metrics) and set a reasonable optimization goal for the application.

Not all metrics are equally important, depending on your application. Finally, set a realistic goal based on the metrics.

1.1 Metrics

Here are some metrics to consider:

  • First Meaningful Paint (FMP, when the main content is displayed on the page)
  • Hero Rendering Times (a new measure of user experience, when the content the user cares about most is rendered)
  • Time to Interactive (TTI for short) is when the page layout is stable, key page fonts are visible, and the main process is available to process user input, so basically the user can click on the UI and interact with it.
  • Responsiveness (time required for interfaces to respond to user Input)
  • (Perceptual Speed Index, or PSI, measures how quickly a page changes visually as it loads. The lower the score, the better.)
  • User-defined indicators are determined by business requirements and user experience.

FMP and hero render times are very similar, but they are different in that FMP doesn’t distinguish whether the content is useful or not, and whether the rendered content is of interest to the user.

1.2 Setting goals

  • Interface response time of 100 ms and 60FPS
  • The Speed Index is less than 1250ms
  • On a 3G network, the interaction time is less than 5 seconds
  • The estimated size of important files is less than 170KB

The setting of the above four indicators has evidence to follow. See RAIL performance model for details.

2. Coding optimization

Coding optimization is related to the runtime performance of your application, and this section describes several suggestions for improving the runtime performance of your application.

2.1 Data read speed

In fact, there are different types of data access speed. Here are several factors that affect data access speed:

  • Literals and local variables are the fastest to access, while array elements and object members are relatively slow
  • The longer a variable is searched from local scope to global scope, the slower it is
  • The deeper an object is nested, the slower it will be read
  • The deeper an object exists in the prototype chain, the slower it will be to find it

The recommended practice is to cache object member values. Caching object member values into local variables speeds up access

2.2 the DOM

The performance bottleneck of an application at runtime is that DOM manipulation is very expensive. Here are some suggestions for DOM manipulation related performance improvements:

  • DOM access in JS is very expensive. Try to minimize DOM access (it is recommended to cache DOM attributes and elements, cache the length of the DOM collection in variables, and use it in iterations. Reading variables is much faster than reading DOM.
  • Rearrangement and redrawing are very expensive. If the operation needs to be rearranged and redrawn multiple times, it is recommended that the elements be removed from the document stream and then returned to the document stream, so that the browser will only rearrange and redraw the elements twice (when they are removed and when they are returned).
  • Be adept at using event delegates

2.3 Process Control

Here is a list of process control-related details that can improve performance slightly and are used extensively in large open source projects (such as Vue) :

  • Avoid the use offor... in(It enumerates to prototypes, so it’s slow.)
  • Reverse looping in JS improves performance slightly
  • Reduce the number of iterations
  • Loop based iteration is 8 times faster than function based iteration
  • Use Map tables instead of lots ofif-elseandswitchImproves performance

3. Static resource optimization

Web applications cannot run without static resources, so the optimization of static resources is very important.

3.1 the use ofBrotliorZopfliDo plain text compression

Brotli is so slow at the highest levels of compression (but slower compression eventually leads to higher compression rates) that the time the server has to wait for dynamic resource compression cancels out the benefits of high compression, but it is good for static file compression because it decompresses quickly.

Zopfli compression can be 3% to 8% better than Zlib’s maximum compression.

3.2 Image Optimization

Use responsive images through srcset, Sizes, and elements wherever possible. You can also use WebP format images through the element.

You may not have heard of responsive images, but you certainly have heard of responsive layouts. Responsive images are similar to responsive layouts in that they work well on devices with different screen sizes and resolutions (such as auto-resizing images, auto-cropping images, etc.).

Of course, if you are not satisfied with this scale of optimization, you can optimize the image further. For example: blurring non-essential parts of an image to reduce the file size, and replacing giFs with auto-play and loc HTML5 videos, since videos are smaller than GIF files (the good news is that videos can be loaded from the IMG tag in the future).

4. Delivery optimization

Delivery optimization refers to the optimization of page loading resources and the delivery process between users and web pages.

4.1 Loading JS asynchronously without blocking

Javascript loading and execution blocks page rendering, and Script tags can be placed at the bottom of the page. But it’s better to load JS asynchronously without blocking. There are several ways to load JS without blocking: defer, Async, dynamically create script tags, and use XHR to request JS code asynchronously and inject it into the page.

However, it is more recommended to use defer or Async. If you use defer or Async, place the Script tag in the head tag so that the browser finds the resource earlier and parses it in the background thread to start loading JS.

4.2 the use ofIntersection ObserverImplementing lazy loading

Lazy loading is one of the most common performance optimizations. Here are some common practices:

  • Can be achieved byIntersection ObserverLazy loading of images, videos, AD scripts, or any other resource.
  • You can load a low-quality or blurry image first and then replace it with the full image when the image is finished loading.

Lazy loading of all bulky components, fonts, JS, videos, or iframes is a good idea

4.3 Loading key CSS first

Loading CSS resources has a significant impact on browser rendering. By default, browsers do not render pages until they have finished loading and parsing CSS in the tag. If the CSS file is too large, the user will have to wait a long time to see the render result. In this case, you can extract the CSS that must be used for the first screen rendering and embed it in , and then load the rest of the CSS asynchronously. You can do this with Critical.

4.4 Resource Hints

Resource Hints define the relationship between the Link element in HTML and DNS-PreFETCH, Preconnect, and PreFETCH and PRERender. It helps the browser decide which sources to connect to and which resources to fetch and preprocess to improve page performance.

4.4.1 DNS – prefetch

Dns-prefetch can specify an origin to fetch the resource and prompt the browser to parse it as early as possible.

<link rel="dns-prefetch" href="//example.com">

4.4.2 preconnect

Preconnect is used to initiate prelinks, which include DNS lookups, TCP handshaking, and the optional TLS protocol, allowing browsers to reduce the potential overhead of establishing a connection.

<link rel="preconnect" href="//example.com">
<link rel="preconnect" href="//cdn.example.com" crossorigin>

4.4.3 prefetch

Prefetch is used to identify resources that may be required for the next navigation. The browser retrieves the resource and can provide a faster response if the resource is requested in the future.

<link rel="prefetch" href="//example.com/next-page.html" as="html" crossorigin="use-credentials">
<link rel="prefetch" href="/library.js" as="script">

Browsers don’t preprocess, don’t automate, and don’t apply it to the current context.

Both the AS and Crossorigin options are optional.

4.4.4 prerender

Prerender identifies resources that may be required for the next navigation. The browser retrieves and executes, providing a faster response if the resource is requested in the future.

<link rel="prerender" href="//example.com/next-page.html">

The browser preloads the resources associated with the target page and executes them to preprocess the HTML response.

4.5 Preload

Declaring a resource through an existing element (for example: IMG, script, link) couples the fetch to the execution. However, the application may simply want to get the resource first and then execute the resource when certain conditions are met.

Preload provides the ability to prefetch resources, separating the act of fetching resources from resource execution. Therefore, Preload can build custom resource loading and execution.

For example, an application can use Preload to Preload CSS resources with features such as high priority and non-blocking rendering. The application then uses CSS resources at appropriate times:

<! <link rel="preload" href="/styles/other. CSS "as="style"> <! <script> var res = document.createElement("link"); res.rel = "preload"; res.as = "style"; res.href = "styles/other.css"; document.head.appendChild(res); </script>
<! - use HTTP header preload - > Link: < https://example.com/other/styles.css >; rel=preload; as=style

4.6 Responsive user interface

PSI (Perceptual Speed Index) is an important indicator of improving user experience, making users feel that the page feedback is much better than no feedback.

Try using a skeleton screen or adding some Loading transition animations to remind the user of the experience.

Input responsiveness indicators are equally or even more important. Imagine how users feel when they click on a web page and have no reaction. The single thread of JS is no longer familiar, which means that the user interface is “locked” while JS is running, so the longer JS synchronizes execution, the longer the user waits for a response.

According to the survey, JS execution more than 100 milliseconds users will obviously feel that the web page change card. Therefore, strictly limit the execution time of each JS task to no more than 100 milliseconds.

The solution is to split a large task into smaller tasks and distribute them in different MacroTasks (colloquially, to split a large JS task into smaller tasks and execute them asynchronously). Or use WebWorkers, which can perform JS code operations outside the UI thread without blocking the UI thread, so the user experience is not affected.

The more complex the application, the more important it is to proactively manage UI threads

5. Build optimization

Modern front-end applications require a construction process, and whether the project is reasonably optimized in the construction process will have a huge impact on the performance of Web applications. For example, it affects the volume of the file after construction, the efficiency of code execution, the loading time of the file, the first effective drawing index, etc.

5.1 Using Precompilation

In the case of Vue, if you develop your project using a single-file component, the component compiles the template into a rendering function at compile time. The final code can be rendered directly by executing the render function when it is executed. If you do not precompile the code using a single file component and instead introduce vue.min.js to the web page, the application will compile the template into a render function at runtime, and then execute the render function to render it. There are more steps to template compilation than precompilation, so a lot of performance is wasted.

5.2 Use tree-shaking, Scope reprocessing, and code-splitting

Tree-shaking is a technique for removing useless code during the build process. Using tree-shaking can reduce the size of files after building.

Currently, both Webpack and Rollup support Scope collieries. They can check the import chain and put as many scattered modules into a function as possible without creating code redundancy. So only modules that have been referenced once are merged. Using Scope collieries can make code smaller and reduce the memory overhead at runtime, while running faster. In the previous section 2.1, it was explained that the longer the searching process of variables from local Scope to global Scope, the slower the execution speed will be, and the Scope reactive can reduce the searching time.

Code-splitting is one of the most compelling features in Webpack. This feature enables you to separate code into different bundles and load these files on demand or in parallel. Code-splitting can be used to get smaller bundles and control resource loading priorities, which, if used properly, can have a significant impact on load time.

5.3 Server Rendering (SSR)

Single-page applications need to render the page in the front end after JS loading, which means the browser will have a blank screen during the period before JS loading and rendering starts.

The significance of Server Side Render (SSR for short) is to make up for the cost of rendering the main content in the front end, reduce the white screen time and improve the speed of rendering effectively for the first time. You can use server-side rendering to get a faster first effective rendering.

The preferred approach is to use server-side rendering of static HTML to get a faster first effective rendering, and then take over the page once the JavaScript is loaded.

5.4 the use ofimportFunction to dynamically import modules

Using the import function, you can dynamically load ES2015 modules at run time to fulfill the need to load on demand.

This optimization is particularly important in single page, at the time of switching routing dynamic import needed for the current routing module, to avoid loading redundant module (just think if the whole site when loading the page for the first time a one-time need all modules are loaded at the same time how many unnecessary JS down loads, should as far as possible to load the JS smaller, Load only the JS you need on the first screen.

Import the initial dependency module using static imports. In other cases, dynamic imports are used to load dependencies on demand

5.5 Using HTTP Cache Headers

Set Expires, cache-Control, and other HTTP cache headers properly.

Cache-control: immutable is recommended to avoid reauthentication.

6. Other

Some other optimizations worth considering:

  • HTTP2
  • Use the best CDNS (paid ones are much better than free ones)
  • To optimize the font
  • Performance optimizations for other verticals

7. Monitor performance

Finally, you may need a performance monitoring tool to continuously monitor your site’s performance.

8. To summarize

Finally, a picture is used to summarize the content of this article. Thanks to @Anjia for helping to draw this picture.



Figure 2. Summary of the article

Thank you very much to Teacher Li Songfeng and sister An Jia for helping to verify this article.

Allow me to conclude with an advertisement. At the end of last year, I was lucky enough to sign a contract with the Turing Community of Posts and Telecommunications Publishing House and started to write a book called “Simple And Simple Vue. Js” (I was told by my friend yesterday that this title is not good, so the title of the book may be changed later).

As the name implies, this book goes deep into the basic implementation principles of vue.js and explains the internal core functions and APIS of vue.js in an easy-to-understand way.

At present, this book has been written and is in the stage of editing and printing. If everything goes well, it will be available at the end of the year (thank you very much wang Junhua for providing this opportunity).

For those of you who are interested in vue.js and want to know more about its internals, please take a look. I will post a notice on my blog as soon as the book comes out.

Blog: github.com/berwin/Blog

The resources

  • Front-End Performance Checklist 2018
  • High Performance JavaScript
  • Responsive picture
  • Preload
  • Resource Hints