question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Parcel 2: Asset Preloading and Prefetching

See original GitHub issue

Modern browsers support Resource Hints, which allow declaratively specifying resources that a web page will need in the future. This is done by inserting <link> tags in the document head, which allows browsers to discover these resources before they normally would and prioritize downloading and caching them, thus speeding up page loads and subsequent navigations. For example, resources like web fonts and background images referenced in a CSS file could be preloaded rather than waiting for the CSS file to be loaded and parsed to start downloading them. Code split bundles could also be prefetched at a lower priority so that subsequent user actions that would depend on asynchronously loaded code could be ready and potentially even parsed in the background ahead of when they are needed.

Parcel has a graph of all of the resources in an application at build time, so it is the perfect tool to automatically insert these <link> tags.

Preloading

<link rel="preload"> can be used to speed up page loads by hoisting downloads of resources that would normally be discovered after loading something else. For example, the browser normally needs to download and parse CSS in order to discover background images and fonts. By hoisting these into the HTML, the browser can download those resources in parallel instead. This could be done automatically by Parcel at build time.

In the HTML packager, Parcel already inserts <script> and <link rel="stylesheet"> tags for each of the directly referenced bundles. We should also insert <link rel="preload"> tags for each resource that is referenced by these bundles that would be immediately loaded, e.g. fonts, images, etc.

In the JS runtime, we should do the same thing. We already load CSS in parallel with JS when loading a code split bundle, but we should also load images and other resources referenced in that CSS/JS. This can be done by dynamically inserting <link rel="preload"> tags into the HTML at runtime.

This will require some bundling changes. Currently, those resources are marked as “async” so are placed in their own bundle group. Ideally, they would be placed in the same bundle group as the bundle that referenced them. This way, the JS runtime and HTML packager can pick up those resources and preload them the same way they already handle JS and CSS.

We could also handle responsive preloading by automatically adding the media attribute to the <link> tag based on the @media rule a resource was nested inside of in CSS. This would avoid preloading media that would not be used on the user’s device.

One concern is how to detect whether resources are used immediately or not. For example, a CSS class with a background image may not be applied immediately. Chrome logs warnings in the console when a preloaded resource isn’t used within a few seconds of page load. It could be argued that loading CSS that isn’t used right away is also bad, but either way, there’s no way to know at build time whether a resource will be used immediately. Perhaps these should be prefetches rather than preloads? Or maybe we need a syntax in CSS/JS to specify which resources should be preloaded and which should be prefetched? Feedback and ideas wanted here.

Prefetching

<link rel="prefetch"> can be used to speed up subsequent navigations within an application by prefetching resources in the background while the browser is idle. This means that those downloads won’t block higher priority resources such as those for the current page, but hopefully by the time the user navigates to a subsequent part of the app many resources are already loaded. These <link> tags can be embedded into the HTML, or added by JavaScript on demand.

Parcel should allow users and frameworks to trigger prefetching of the resources that would be loaded for a code split bundle. Dynamic import() normally downloads and immediately executes a bundle and it’s dependencies, but prefetching would only download and cache the resource without immediately executing it.

One way to do this is to support a runtime API to trigger prefetching. Parcel has all of the metadata about what bundles to load already, so we just need to expose this information. For example, on mouse over on a button, prefetching could be triggered so that the browser has a head start when the user decides to click it.

import prefetch from '@parcel/prefetch';

async function onMouseOver() {
  prefetch('./other');
}

async function onClick() {
  await import('./other');
}

This could be statically analyzed at build time to generate the necessary prefetching code.

Feedback

Please leave feedback in the comments below. It would be really useful to hear your usecases and ideas for this.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:11
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

5reactions
wojtekmajcommented, Dec 27, 2019

I think it would be nice to have magic comments like in Webpack, for the sake of simplicity of migration from one solution to another.

import(/* parcelPrefetch: true */ 'LoginModal');
Read more comments on GitHub >

github_iconTop Results From Across the Web

How To Use Preload and Prefetch in HTML to Load Assets
A quick overview on how to take advantage of the preload and prefetch HTML attributes in order to optimize the loading of assets....
Read more >
Parcel 2 alpha 1 is here!
At the same time, our asset graph can be invalidated super granularly, which means that cached builds have almost exactly the same ...
Read more >
PK ‍ on Twitter: "This project looks great but as I was saying they ...
Without support for prefetch/preload, its going to be hard to adopt parcel 2 IMO. github.com. Parcel 2: Asset Preloading and Prefetching · Issue...
Read more >
Front-End Performance 2021: Build Optimizations
Parcel has module support in Parcel 2. ... Or use preload-webpack-plugin to generate preload / prefetch for all JavaScript chunks.
Read more >
The ultimate guide to modern web application performance
Prefetch also work only for static assets as the preload. The main difference here is that it prefetches the resources needed for a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found