📜 ⬆️ ⬇️

I want sites to open instantly

Hello, my name is Alexander Zelenin and I am a web developer. I will tell you how to make your website open quickly. Very fast.



Introduction


There will be no advice to make "A" and get a super win. This does not happen. In this article I want to consider the factors that can be accelerated and due to what. There are no other factors. The next time you make your site faster, there will be an understanding of how you will win.

The article is focused on advanced developers!
')
Each of the topics considered deserves a separate post, if not one. If it is interesting, I will definitely tell you more.

Let's start with what really matters to the user:



  1. HTML starts loading ( TTFB )
  2. HTML, CSS and scripts at the top of the page are loaded. Page rendered ( TTI )
  3. Full functionality: additional content is available, control buttons work ( TTLB ) *

* it is not entirely correct to call it TTLB, since we loaded a number of separate files, but we can assume that the last required byte is loaded.

It is enough to display the main content within 1 second so that the user thinks that the site is fast. This is much simpler than it seems.

What to optimize first?


It is necessary to measure the described metrics of the site and select the largest of them - in this order and optimize. Now it is easier to do this than ever - just open, for example, in the chrome Network panel in the web developer's tools.

Before you start optimizing you need to know


  1. The geographical location of the target audience (city (s), country (s). Sometimes even a district may be important.)
  2. The parameters of the communication channels of users (What tariffs are distributed in this geographic location? And the mobile Internet?)
  3. Types of access devices (PC, phones, tablets)

All recommendations are given for modern PC machines and connections of 8 megabits per second with a ping to the capital not exceeding 50ms. In your case, you need to adjust the numbers depending on the desired conditions.

What does page opening consist of


  1. Expectation
    1. Waiting queue
    2. Proxy passing
    3. Resolve DNS
    4. Connection establishment (TCP handshakes)
    5. SSL handshake
    6. Submit request
    7. Waiting for response (time before receiving the first byte)

  2. Data loading
  3. Running scripts
  4. Rendering
  5. Drawing

Expectation


Waiting is all that happens until the moment the first byte is received.

Waiting queue


Impact : every request, if the limit is exceeded
Factors : the number of simultaneously requested files from one domain
Good value : 0 for meaningful content
Note if for meaningful content the value is greater than zero.

Browsers have a limit on the simultaneous number of connections (simultaneous downloads) with the same domain. On average, from 4 to 8, but may vary depending on the device, browser and its version. However, this limitation applies simultaneously to all tabs.

If the browser needs to load more resources than the limit, it will start downloading the first and put the rest in the queue.

Necessary steps:

  1. Move the loading of meaningful content to the top of the queue
  2. If meaningful content still creates a queue, combine the relevant resources *. CSS files in one, JS files in one, combine icons into sprites or place them directly into CSS (the cost usually does not exceed 10-20% and is worth it).
  3. Move loading optional content to end of queue
  4. Combine optional resources into groups. It is not necessary to combine everything, everything - it is best to combine scripts, styles and graphics in blocks, because they are sometimes independent and can be displayed asynchronously.

* And you can do it like this
Optimization errors
Combine everything into 1 file (i.e., put everything straight into an HTML file, including graphics via inline image)
This will give some acceleration due to the fact that there will be no expectations, but:
  1. Drawing will be only when everything is loaded. HTML + CSS would be enough.
  2. Now the cache is useless. If the site opens a second, then the second time will be a second (instead of a quarter, as described below).

Ideally, both the communication channel and processor resources should be loaded simultaneously, and not sequentially. I did it on yac2013 , not having time to properly separate these processes and having lost more than 100ms.

Well, then we put CSS right in HTML.

Yes, it will give a win on the first download. But only.

  1. The cache is useless, CSS is loaded every time.
  2. If the fonts are connected (you also connect them inline, right? And not by a separate file, otherwise just wait), we get + 200-500kb to download

Mm, okay. Let's then merge all-all js files into 1 and all-all css files into 1. Then we will fit into the limits of any browser, well, it will load quickly.

On the right track, but this is still incorrect. You do not need all-all js and css files for the initial page rendering. Even if the part is not used - they still take the channel and processor time. Well and still at any change of the smallest file the cache is invalid and the user to load everything anew.

How to organize everything right away?

Fonts and inline icons in CSS. Make the CSS necessary for drawing, and the rest of the load on 1 through the dependency manager. The required CSS is loaded from the page header, the rest via js. Js exactly the same. Post static on CDN.

Proxy passing


If the work occurs through any proxy connection, then it imposes its own limitations and increases the latency of response and final load. We cannot influence this parameter, therefore there is no sense to linger on its consideration.

Recognition of DNS records


Impact : once per TTL
Factors : number of used domains, location of registrar name servers
Good value : 20-50ms
Pay attention if your value exceeds 80ms for the target audience

Each domain used (including the first document) on the page requires a full domain recognition cycle, which usually takes from 10 to 120ms. Many DNS servers have mirrors around the world.

Necessary steps:

  1. Determine the geographical location of your target audience and choose a registrar with a good location of name servers for you.
  2. If you do not plan to migrate servers, you can increase the domain TTL to large values ​​- a day, or even a week.
  3. If you are planning to request subdomains or other domains from scripts or other deferred sources, you must specify
    <link rel="dns-prefetch" href="//example.com"> 
    in the main document.

Connection setup


Impact : every request after idle
Factors : distance to server with data
Good value : 50-80ms
Note if the value is 150ms or more.

Before you start sending and receiving data, the browser establishes a connection to the server. It consists of three packet transmissions and passes for 1.5 RTT (ping to server x 1.5). A connection is established each time, as it is necessary to download data if there are no connections available. As we remember, the browser does not open more than a certain number of connections. If the data enters the queue for loading and there are active connections, then they will be used as soon as they become free, i.e. no additional delay. If all relevant information is immediately contained in the first html document, we get a delay of 1.5 pings, and if at least something else is loaded, we get a delay of 3 pings. If the ping is 100ms, we get a total loss of 300ms already.

Steps:

  1. Return meaningful information in the first request (immediately reduces the impact of this factor by half).
  2. Determine the geographical location of the target audience, place the server (s) as close as possible.

SSL


Influence, overclocking options, factors : the same as when setting up a connection
Good value : 100-150ms
Note if the value is 250ms or higher.

Using SSL increases the connection setup time several times .

The number of transmitted packets to establish a connection is increased by 3 to 12 and 3 RTT . This means that at a delay of 100ms, if the data is not contained in the original document, we will receive at least 600ms of delay. Server time can be neglected, because in this case it will be small.

Steps:

  1. Understand that SSL is really needed and refuse where it is not needed
  2. Steps to speed up the connection also speed up the SSL download.

Submit request


Usually takes less than 1ms . Honestly, from practice, I do not remember a single situation when there was more.

Quite an important point that I would like to point out - absolutely with each request a series of headers is sent. Cookies are also headers. If you put a lot of data in a cookie, it will be sent to the server every time. If you really need to use a lot of heavy cookies (I don’t know why, but let's say), specify the correct paths with them, so that they would be sent only to the right place.

waiting for an answer


Impact : each request
Factors : server uptime
Good value : 10-50ms
Note if the value is more than 100ms

Usually this step gives the greatest speed increase. The server cache is worth a separate article, and, perhaps, I will ripen to write it somehow. The main influence on waiting for a response is played by the execution time of scripts on the server - processing the request, database requests, generating a response, etc. The main secret of the speed of this stage is to have a ready answer to what they want to request. Simply put - cache.

Steps:

  1. Determine what data to cache and how.
  2. Return all cached data

Data loading


Impact : each request
Factors : data size, (user channel)
Good value: depending on the providers in geography, up to a second, taking into account the previous steps
Note if more than 2 seconds

Finally, the server began to return data. The main criterion for loading them is their size.
We will not consider the high speed of a small amount of data, since An ordinary site, nevertheless, takes from 500kb.

Important : with increasing bandwidth user channel decreases the influence of this factor. If the main target audience is in the capital and has 100mb / s (vs. 8ms / s taken as the standard), then 1 megabyte will load an order of magnitude faster and from the longest factor it can become one of insignificant.

It is also worth mentioning about "TCP slow start", but this is a topic for a separate post (it was somewhere in Habré, I did not find it).

Steps:

  1. Enable data compression on the server. But, it is necessary to take into account that unarchiving data also takes time (depends on the end device), and, in some situations, sending uncompressed data is justified.
  2. Remove unused data from the download. It often happens that a number of libraries are connected, and, after a while, some become irrelevant, but they are forgotten to be removed.
  3. Separate data into necessary and secondary, and load in that order. Sometimes you can get an order of magnitude gain.

Running scripts


Influence : always
Factors : volume of scripts, algorithms used
Good value : 0-50ms to display meaningful content, no further significant
Pay attention if after downloading the data more than 200ms go "nowhere"

After downloading the scripts, the browser takes some time to parse and execute them.

Rendering


Influence : always
Factors : the volume and quality of styles and nesting of site blocks
Good value : up to 50ms
Pay attention if rendering takes more than 200ms

After loading all the styles, the browser starts the calculations where to place which block, where to transfer lines, etc.
Once I saw a 20% effect on the speed of the site operation of extremely large HTML nesting. Seriously - the optimization of just HTML nesting gave a 20% more responsive site.

Steps:

  1. Reduce the number of styles
  2. Get rid of the reassigning styles whenever possible (when there is a bunch of overlapping rules for one property and only one is executed. Look towards OOCSS

Drawing


Influence : always
Factors : the number of "heavy" items with post-processing, such as, for example, shadows. Number of graphics.
Good value : up to 50ms
Pay attention if drawing takes more than 200ms

The main influence on the rendering time is played by changing parts on the page. Tritely one gif'ka will give growth more than anything else.

Steps:
  1. Reduce the number of graphics and dynamic elements on the page

CDN


Proper use of CDN will allow you to solve many problems and significantly speed up the loading of your site.
Starting with the fact that the delay in creating a connection will be within 20ms, so, sometimes, the CDN provides the download speed faster than the user’s tariff rate, due to the location on the provider's servers (as Google does, for example).

Browser Cache


When a user opens a site for the first time - the cache will not help us in any way (except for using public CDN with libraries, but this is a topic for a separate article and a security control issue). But with repeated visits, the cache provides tremendous benefits. All unchangeable content should be placed in the browser cache. Graphics, styles, scripts. Also in the cache, you can add responses to the API, but very carefully. With proper management of the cache, we will have:

  1. 75ms to establish a connection (without additional connections, data from the cache)
  2. 25ms server timeout
  3. 50ms to render
  4. 10ms to draw
  5. 100ms of data load (instead of 650)

Those. full site loading within a quarter of a second!

Sockets


First of all, to work with sockets it is necessary that any scripts be loaded and executed. Subsequently, of course, we get rid of the costs of creating a connection and queue restrictions, but we get problems with managing the cache (we will have to manage it manually).

Verdict : Sockets must be used for dynamic, non-cached, non-bulk content.

I have a SPA , how to be?


All tips apply more to the SPA. Usually, a SPA has at least 1 step more until the content is rendered, i.e. Received HTML -> Received scripts -> Download content from API. From here we receive at least one more RTT, and after loading of scripts.

Actions:

  1. Return HTML immediately with data. Modern template engines (such as handlebars) are not tied to the language, and they are easy to generate both on the server and on the client. At least for unauthorized users. The authorized already have a cache and the cost will be minimal.
  2. Download in the first place only the necessary controllers, models, views and what else do you have there? It's easier than it seems, if you prescribe dependencies or use AMD

Optimization errors
But what if you move the data requests directly to the HTML file, so that they would be added to the cache, and when the scripts are loaded everything was already there?

First try to understand what you can win. With this approach, we can only win 1 RTT (due to parallelism, although we will block one channel with this) and the server timeout.

If your server responds for a long time and for some reason you do not want to optimize it, so that this expectation would be ~ 20ms, then yes, this approach will give a gain (compared to 3 steps). But if you did everything right, then we get RTT + 20ms. Those. maximum 50-70 milliseconds. It is so not serious gain in comparison with potential problems from this action that it is not worth it that much.

Possible problems:

  1. The script was loaded before the data was received and has already sent a new request.


Subjective optimizations


It happens that you can do so that it would seem that it works faster when, in fact, the same way. Good to use. As an example, I can give the translation of listening to events in the SPA with a click on mousedown (in addition to the click!). A small hack that allows you to "try":

 document.onmousedown = function(e) { e.target.click(); } 

The trick is that the whole click of the user takes up to 50ms, and the onmousedown event takes place in the middle. Thus, starting processing earlier, we can give the result earlier. If our processing does not exceed the speed of a user’s click, then the latter will have the feeling that he hasn’t even clicked yet, but everything has already seemed - wow! Similar tricks should be done for each project individually.

In general, of course, this is a special case - if you can calculate everything in advance, you can immediately show it.

You can also cache in mouseover more than 0.1s, for example.

Total


User: without proxy, with a channel width of 8 megabits per second and RTT 50ms to our server has:

  1. 50ms DNS resolution
  2. 75ms to establish a connection (without SSL) (+ 75ms second and subsequent parallel connections)
  3. 25ms server timeout
  4. 0ms to run scripts
  5. 50ms to render
  6. 10ms to draw

285ms cost

It remains 700ms to download content, which under our conditions is approximately equal to 700kb of data. Given the compression, this may be around 3.5MB of data, which is enough for most sites.

Total: 1 second

When reopened, the delay goes to the DNS and some of the data is loaded from the cache.

Total: ~ 0.4 seconds with cache

Make quick sites and everyone will be happy. If with all this you still show information to the user when the connection is disconnected , then it will generally be gorgeous.

Bonus you can read High Performance Browser Networking

Ask questions - I will answer, I will add article.

looking for a job.

Source: https://habr.com/ru/post/274129/


All Articles