Webpack prefetch and preload directives

Original author: Tobias Koppers
  • Transfer
In webpack 4.6.0. support for directives prefetchand appeared preload(they look, respectively, as "magic comments" webpackPrefetchand webpackPreloadto commands import()). With their help, the browser can give tips about resources that the user may need in the near future. The browser preloads such resources in advance, which helps to improve the user's impression of working with the site. The material, the translation of which we publish today, will focus on how to use these directives to optimize website performance.

image



What is ?


The directive prefetchtells the browser that the specified resource may be needed in the future to move around the site.

Browsers usually load similar resources at a time when they are not busy with other tasks. After loading, the resulting resource is in the HTTP cache, ready to be used when processing future requests. If you need to organize the preliminary receipt of many resources, such requests are queued, and they are executed when the browser is in idle mode. Leaving this mode, the browser can interrupt the current loading of the prefetch resource (and put a partial result in the cache in order to later return to its loading using the Content-Range headers) and stop the queue for processing prefetch requests.

As a result, we can say that using the resource hint prefetchleads to the fact that the corresponding resources are loaded during browser downtime.

What is ?


The directive preloadtells the browser that the resource marked to it will be needed in this session with the site, but it will be accessed a little later. At the same time, Chrome even displays a warning when a similar resource is not used 3 seconds after loading.

Usually browsers download such resources, giving them medium priority (such loading does not block the user interface).

Hinted resources preloadare loaded like regular resources, however, their download starts a little earlier than the user accesses them.

About the benefits of the prefetch and preload directives


The directive preloadallows you to pre-load the resources that will be needed soon, and to avoid the "waterfall effect" when, everything that is needed to display the page starts to load immediately after clicking on the corresponding link. This technology allows you to break the page loading into two stages, when the HTML code is loaded first, and then everything else. However, this does not mean additional load on the network channel.

The tooltip is prefetchused during browser downtime to speed up future interactions with the site. Its use may mean the need for additional traffic costs in the event that the user does not use the loaded resources.

Code separation


Here it is assumed that this is a huge application prepared by webpack using the on-demand loading mechanism (command import()) to download only those parts of the application that the user needs at the moment.

As an example, we will consider the home page ( HomePage), on which there is a button for logging in ( LoginButton), which opens a modal window for entering credentials ( LoginModal). After the user logs in, they are shown the control panel page ( DashboardPage). There may be other buttons on this page that are needed to go to other pages, but we focus on the fact that the purpose of the user is this page.

In order to achieve the best performance, there is a command on the page with a button for entering the system import("LoginModal"), and a command on the page for entering credentials import("DashboardPage").

Now it turns out that our experimental application is divided into at least three parts: the home page, the credentials entry page, and the control panel page. At the initial download, you only need to show the user the home page. It loads quickly, which gives us every right to expect that the user will have a good experience working with this page. However, when the user clicks on the login button, he will notice some delay necessary to display the login window, because before the user sees this window, this part of the application still needs to be downloaded. The same goes for the control panel page. At this stage, we have a question about how to improve the user experience of working with the site.

Using webpack prefetch hints


Due to the fact that prefetch hints can now be used in webpack, we can improve the above scenario of working with the site. It is very easy to do. Namely, it is necessary, on the page with a button input to use, instead of the command import("LoginModal"), command import(/* webpackPrefetch: true */ "LoginModal"). Similarly, on the page for entering credentials, instead of the command, import("DashboardPage")you need to use the design import(/* webpackPrefetch: true */ "DashboardPage").

These commands will tell webpack what it should load, after loading the main page (while the browser is idle), the specified fragments of the application. In this example, after loading the home page, the loading of the login page is added to the queue. And when the login page is finished loading (real download, not preliminary, caused by a promptwebpackPrefetch), the application fragment representing the control panel page will be put in the download queue.

Based on the fact that the entry point to the application is the home page, a view link will be formed on the HTML page based on the above commands . An application fragment representing the login page is loaded on demand, so webpack will take care to embed a view tag in the page after the login page has finished loading.

This will have a beneficial effect on the user's experience with the site. Namely, the following improvements can be noted here:

  • When the user gets to the home page, it loads, according to his feelings, as fast as before. After the loading of the home page is completed, the browser goes into an idle state and starts background loading of the login page. The user does not notice this. We assume that the user needs some time to find the button for entering the system, which means that the background loading of the login page will complete before he clicks on the button.
  • When the user finally clicks on the login button, the login page is already loaded into the HTTP cache, the request to load it is served from the cache, the page output takes as little time as possible. As a result, the user will immediately see the login page. After loading this page, the browser adds the control panel page to the background download queue, as a result, after the system is logged in, the output of this page will also be executed instantly.

Please note that above we described the ideal scenario.

The user will not always see the pages that are supposed to load in the background instantly. There are many factors that can affect this. Among them are slow Internet connections, users who click on the corresponding buttons very quickly, disabled processing of prefetch hints on devices that are aimed at saving traffic, lack of support for this feature in browsers, very slow processing of loaded pages on a site, and so on.

Using webpack preload hints


Above, we talked about the design import(/* webpackPrefetch: true */ "...")for describing the resources that are supposed to be loaded during browser downtime. There is a similar command import(/* webpackPreload: true */ "..."),, for describing preload resources. If you compare these two approaches, you can identify many differences:

  • The preload resource starts loading in parallel with the parent resource. A prefetch resource is loaded only after the parent resource has finished loading.
  • A preload resource has medium priority, it loads immediately. The prefetch resource is loaded during browser downtime.
  • The preload resource must be requested very quickly by the parent page. A prefetch resource can be used in the future at any time.
  • Browsers support these mechanisms in different ways.

As a result, prefetch hints are rarely used. For example, they may be needed if the module immediately imports something with a command import(). This may make sense if, for example, a certain component depends on a large library, which must be present in a separate fragment of the application. For example, a component for displaying diagrams,, ChartComponentuses a large library for working with diagrams - ChartingLibrary. The component, at boot time, displays a download indicator ( LoadingIndicator) and immediately executes the command import(/* webpackPreload: true */ "ChartingLibrary"). As a result, when requested to load a page that uses ChartComponent, it is requested using the construct, and loading a fragment of the application with the library. Based on the assumption that the page with the component is smaller than the fragment of the application with the library, and its loading will complete faster, this page will display with a loading indicator that will be displayed until the fragment of the application with the library is finished loading. This will slightly reduce the download time of everything necessary, since the system performs the downloads in parallel, without dividing this process into two separate actions. This will be especially noticeable where network connections are characterized by high latency.

I must say that improper use of the design webpackPreloadcan degrade performance, so you need to use it carefully.

If you are thinking about what kind of mechanism you need - preloadorprefetchYou will probably be better off taking advantage prefetch. Moreover, the above is true for the import()webpack team . Ordinary HTML pages are probably more suitable for you preload.

Loading multiple prefetch resources


If necessary, you can use as many commands import()with the directive on the page webpackPrefetch. However, it should be borne in mind that all resources loaded in this way will fight for bandwidth.

Corresponding requests are queued, which can lead to a situation where the fragment necessary to service the user’s request is not loaded at the right time.

This cannot be called a big problem if all the prefetch resources may be needed with the same probability. However, if some resources are more important than others, then most likely you should think about the possibility of controlling the order of loading resources.

Fortunately, this is possible, although it goes beyond the basic use cases prefetchand preload.

So, instead of applying the construction webpackPrefetch: true, you can use a number instead of a logical value. As a result, webpack will load fragments in the given order. For example, resource c webpackPrefetch: 42will be loaded before resource c webpackPrefetch: 1, which, in turn, will be loaded earlier webpackPrefetch: truethan resource c, and this resource will be loaded before resource c webpackPrefetch: -99999(this resembles z-order). Actually, truehere it is the same as 0. It is

similarly possible to work with webpackPreload, but you are unlikely to need it.

FAQ


  • What if several teams import()request to download the same resource, and they will use hints prefetchand hints preload?

The directive preloadtakes precedence over prefetch, and is prefetchused if webpack does not have any more instructions about a specific resource. If several commands are used to preload the same resource, the one that is assigned a higher priority is triggered.

  • What if the mechanisms prefetchand preloadare not supported in the browser?

In such a situation, the browser ignores these prompts, and webpack does not attempt to use any backup mechanism. In fact, prefetchand preloadnot by chance are called "tips", so even if the browser supports it, it can, for whatever reason, to ignore them.

  • Directives prefetchand preloadon a certain page, which is the entry point to the site, do not work. What can be wrong?

The webpack runtime accepts hints prefetchand preloadonly for resources loaded on demand. When prefetchor preloadare used in commands import()in site fragments that are input points, the HTML generation system is responsible for adding tags to the resulting code.

Relevant reference data is available at entrypoints[].childAssets.

  • Why not use the Directive prefetch, and preloadin each team import()?

This will lead to irrational use of the bandwidth of the Internet channel. In addition, more benefit can be gained from the selective application of these directives for commands import()related to resources that the user will need with a high degree of probability. It’s not worth wasting Internet channels, because for some users they are far from unlimited. Therefore, use these directives only when they are really needed.

  • I do not need this opportunity. What are the disadvantages of not using it?

The corresponding code in the runtime webpack accrue only if the directive prefetchand preloadused for materials that are loaded on demand. As a result, if you do not use this opportunity, no additional load on the system is created.

  • I already have a “magical comment” on the team import(). Is it possible to add several such comments to it?

Yes it is possible. Comments must either be separated by a comma, or just use a few separate comments:

import(
  /* webpackChunkName: "test", webpackPrefetch: true */
  "LoginModal"
)
// или
import(
  /* webpackChunkName: "test" */
  /* webpackPrefetch: true */
  "LoginModal"
)
// переводы строк необязательны

  • I created a library using rollup, and I also use commands import(). Can users of my library working with webpack take advantage of use prefetch?

Yes, you can add “magic comments” to webpack commands import()and rollup will save them. If the finished project is built using webpack, it will take advantage of these comments. If webpack is not used, they will simply be removed by the minifier.

  • I’m not sure that adding a hint prefetchto some team import()will improve performance. Should I add this tooltip?

The best thing is to measure performance using the A / B testing methodology. As applied to such a situation, one cannot give unambiguous universal advice. It depends on the likelihood that the user will need to visit a certain part of the application.

  • I already have a service worker who, upon loading, caches everything the application needs. Does it make sense in this situation to use prefetch?

It depends on the application. In general, such service workers download all application resources without worrying about the order in which the download is made. At the same time, directives prefetchallow you to specify the loading order of resources; they depend on the place in the application in which the user is located. In addition, the prefetch mechanism is more economical in terms of bandwidth and only downloads data when the browser is idle.

Measure the time required to fully download the application using a low-speed communication channel, compare this with when the user needs to perform the first transition in the application. If the application is very large, it makes sense to consider using the mechanism prefetchrather than caching the entire application in one go.

  • I would like to divide the resources loaded on the first page load into vital and secondary resources, and load them according to their significance level. Will the mechanism come in handy in such a situation preload?

Yes, vital resources can be placed at the entry point to the application, and secondary resources can be downloaded import()with webpackPreload: true. And do not forget to add for the resources necessary for the correct operation of the entry point to the application (before the tags for the children).

Summary


In this article, we talked about the innovation of webpack, which allows the use of directives prefetchand preload. Their correct application helps to improve the user's experience with the site, and improper use can lead to unnecessary traffic costs, which is especially true for cases when working with a web resource is carried out on a device whose capabilities are limited. We hope the new features of webpack come in handy for creating fast and convenient web projects.

Dear readers! Do you see practical situations in which the prefetch and preload directives may come in handy?


Also popular now: