You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/docs/src/routes/(blog)/blog/(articles)/qwik-1-14-preloader/index.mdx
+31-27Lines changed: 31 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,42 +20,46 @@ import serviceWorkerRegistrationPenalty from './service-worker-registration-pena
20
20
21
21
<ArticleBlock>
22
22
23
-
We’re super excited to announce the release of Qwik 1.14.0, our most fundamental update to Qwik since the release of 1.0.0!
23
+
We're super excited to announce the release of Qwik 1.14.0, our most fundamental update to Qwik since the release of 1.0.0!
24
24
25
25
You can try it out on a new Qwik project with `npm create qwik@latest` or update your existing project with `npm i @builder.io/qwik@latest @builder.io/qwik-city@latest eslint-plugin-qwik@latest`.
26
26
27
27
## A Qwik recap
28
28
29
-
One of the core features that makes Qwik so... well... quick... is what we call “**Javascript Streaming**” – the unique ability to execute a part of the code as soon as it is ready, before all the code has been downloaded – speeding up your website’s [TTI (Time To Interactive)](https://developer.mozilla.org/en-US/docs/Glossary/Time_to_interactive) similarly to how [video streaming](https://www.cloudflare.com/learning/video/what-is-buffering/) is significantly faster than downloading an entire video and then playing it thanks to buffering and on demand delivery.
29
+
One of the core features that makes Qwik so... well... quick... is what we call "**Javascript Streaming**" - the unique ability to execute a part of the code as soon as it is ready, before all the code has been downloaded - speeding up your website's [TTI (Time To Interactive)](https://developer.mozilla.org/en-US/docs/Glossary/Time_to_interactive) similarly to how [video streaming](https://www.cloudflare.com/learning/video/what-is-buffering/) is significantly faster than downloading an entire video and then playing it thanks to buffering and on demand delivery.
30
30
31
-
This mechanism is first enabled at build-time thanks to the [Qwik optimizer](https://qwik.dev/docs/advanced/optimizer/#optimizer), which looks for $ signs and splits your application code into smaller pieces (called “segments”). Then the bundler ([Rollup](https://rollupjs.org/)) groups these segments into small javascript files (called “bundles”) that hold related segments together.
31
+
This mechanism is first enabled at build-time thanks to the [Qwik optimizer](https://qwik.dev/docs/advanced/optimizer/#optimizer), which looks for $ signs and splits your application code into smaller pieces (called "segments"). Then the bundler ([Rollup](https://rollupjs.org/)) groups these segments into small javascript files (called "bundles") that hold related segments together.
32
32
33
33
The goal is to have bundles neither too big nor small, where each corresponds to an interactive part of the UI.
34
34
35
-
Then at runtime, the framework can leverage a service-worker to prefetch and cache all the bundles available on the page so that when a user interacts with a certain component, the code for it is already buffered and can be “lazy-executed”**right away** (unlike “lazy loaded” on demand).
35
+
Then at runtime, the framework can leverage a service-worker to prefetch and cache all the bundles available on the page so that when a user interacts with a certain component, the code for it is already buffered and can be "lazy-executed"**right away** (unlike "lazy loaded" on demand).
36
36
37
-
If the user interacts but the network is really slow and therefore prefetching is still going on, Qwik will prioritize downloading those bundles and will execute them as soon as they’re available.
37
+
If the user interacts but the network is really slow and therefore prefetching is still going on, Qwik will prioritize downloading those bundles and will execute them as soon as they're available.
38
38
39
-
In comparison, the other frameworks need to execute at least all of the visible UI code to attach the event listeners, and therefore they must download all of that code before executing it in a process called “hydration”.
39
+
In comparison, the other frameworks need to execute at least all of the visible UI code to attach the event listeners, and therefore they must download all of that code before executing it in a process called "hydration".
40
40
41
-
In effect, this means that TTI on Qwik apps can often be as fast as ~5s on a slow 3G network connection, even for very complex applications. With hydration on the other hand, TTI often reaches ~20s on slow 3G on simple websites and 60s or more on more complex applications as it increases proportionally to the amount of components that need to hydrate.
41
+
For hydration based apps on a slow 3G network, TTI often reaches ~20s, and even 60s plus for more complex applications as it increases proportionally to the amount of components that need to hydrate.
42
42
43
-
### A long standing “buffering” issue
43
+
On the other hand with Qwik on a slow 3G network, TTI can often be as fast as ~5s (and even faster) no matter how complex the application becomes.
44
44
45
-
In Qwik 1.11.0 and 1.13.0, we fixed some long lasting bugs that were leading to “under-prefetching” and “over-prefetching under certain conditions. With those fixes, we made sure that all and only the bundles required for the user interactions available on a page are prefetched, therefore preventing any sort of network delays.
45
+
JavaScript Streaming enables **loading time performance that scales seamlessly**, from simple marketing websites to enterprise level applications.
46
+
47
+
### A long standing "buffering" issue
48
+
49
+
In Qwik 1.11.0 and 1.13.0, we fixed some long lasting bugs that were leading to "under-prefetching" and "over-prefetching" under certain conditions. With those fixes, we made sure that all and only the bundles required for the user interactions available on a page are prefetched, therefore preventing any sort of network delays.
46
50
47
51
But there were still 2 somewhat hidden issues we only uncovered recently through manual testing on a used up low-end smartphone. It turns out there is a small cost to serving bundles from the cache through the service worker:
48
52
49
-
-On old/low-end devices with poor CPUs, the first interactions on Qwik components would lead to small delays, even with a good network connection.
50
-
-There was a small startup penalty to register the service worker, preventing any reprioritization of the bundles before the registration.
53
+
-**For old/low-end devices with poor CPUs** the first interactions on Qwik components would lead to small delays, even with a good network connection.
54
+
-**A small startup penalty** to register the service worker, preventing any reprioritization of the bundles before the registration.
51
55
52
-
Thankfully, using a service worker isn’t the only way we can prefetch and cache javascript bundles on the client, and we have found an even better alternative to it.
56
+
Thankfully, using a service worker isn't the only way we can prefetch and cache javascript bundles on the client, and we have found an even better alternative to it.
53
57
54
-
## What’s new: a better way to “buffer” javascript bundles
58
+
## What's new: a better way to "buffer" javascript bundles
55
59
56
60
In Qwik 1.14, we've transitioned away from using a service worker in favor of a solution leveraging [`<link rel="modulepreload">`](<https://devdocs.io/html/attributes/rel/modulepreload>) as the new default.
57
61
58
-
The solution consists of a small script called the “Qwik Preloader”. Once it is downloaded on the client, it adds the `<link rel="modulepreload" href=”my-bundle.js#segment123456”>` to the html `<head>`, which tells the browser to preload and buffer the corresponding JavaScript bundles.
62
+
The solution consists of a small script called the "Qwik Preloader". Once it is downloaded on the client, it adds the `<link rel="modulepreload" href="my-bundle.js#segment123456">` to the html `<head>`, which tells the browser to preload and buffer the corresponding JavaScript bundles.
59
63
60
64
By doing so, we not only get rid of any startup penalty, but also make any interaction on Qwik components absolutely instant once the bundles for it have been preloaded, even on devices with poor CPUs 🚀
61
65
@@ -81,7 +85,7 @@ The reason why there is such a delay with the service worker on devices where th
81
85
82
86
In contrast, modulepreloaded bundles are downloaded and compiled by the browser. They live in memory and are ready to be executed instantly on request. So if all the bundles required for an interaction have been preloaded, the interaction will be instant. There is no network request, no service worker interception, no retrieving of bundles from the CacheStorage.
83
87
84
-
Here’s a small Excalidraw to illustrate the difference:
88
+
Here's a small Excalidraw to illustrate the difference:
85
89
86
90
<Imagesrc={serviceWorkerVsModulepreloadIllustration}alt="Service Worker vs modulepreload illustration" />
87
91
@@ -94,36 +98,36 @@ With modulepreload, we can now start preloading bundles as soon as the html is r
94
98
95
99
### Even better prioritization based on heuristics
96
100
97
-
A powerful feature that already existed in the Qwik service worker that is also implemented in the Qwik Preloader is the ability to “**reprioritize**” bundles on user interaction. If some bundles are at the bottom of the preload queue, we can tell the browser to start preloading them right away. This means that no matter what, TTI remains constant as it doesn't increase proportionally to the number and size of bundles that need to be loaded.
101
+
A powerful feature that already existed in the Qwik service worker that is also implemented in the Qwik Preloader is the ability to "**reprioritize**" bundles on user interaction. If some bundles are at the bottom of the preload queue, we can tell the browser to start preloading them right away. This means that no matter what, TTI remains constant as it doesn't increase proportionally to the number and size of bundles that need to be loaded.
98
102
99
-
But it’s even better if the framework can already know ahead of time what to “buffer” in which order. Qwik can now out of the box guess which bundles are more likely to be requested by the user based on what is most likely to be interacted with first.
103
+
But it's even better if the framework can already know ahead of time what to "buffer" in which order. Qwik can now out of the box guess which bundles are more likely to be requested by the user based on what is most likely to be interacted with first.
100
104
101
-
It is not perfect (for that we have [Qwik Insights]( which requires a database)), but it’s quite a bit better than before! Qwik now gives “better scores” to more important things like “user events” or “above the fold” components over things it assumes are less important.
105
+
It is not perfect (for that we have [Qwik Insights](https://maiieul-blog-co-writers.qwik-8nx.pages.dev/docs/labs/insights)), but it's quite a bit better than before! Qwik now gives "better scores" to more important things like "user events" or "above the fold" components over things it assumes are less important.
102
106
103
-
For example, Qwik assumes that the search input on the navbar above the fold is more likely to be used sooner than a Button on a footer far down below the fold, but if the user scrolls and clicks the button on the footer, Qwik will re-prioritize its bundles before the search input.
107
+
For example, Qwik assumes that the search input on the navbar above the fold is more likely to be used sooner than a Button on a footer far down below the fold, but if the user scrolls and clicks the button on the footer, Qwik will **re-prioritize** its bundles before the search input.
104
108
105
109
### Faster CI times
106
110
107
111
Thanks to the performance improvements above, our full CI tests on [qwik.dev](<http://qwik.dev>) now run in about ~10 minutes instead of ~15, and most of it can be attributed to the E2E tests which do many renders in a browser and were therefore bootstrapping a lot of service workers.
108
-
## **How do I get all of this Goodness?** (**Migration steps)**
112
+
## **How do I get all of this goodness?** (**Migration steps)**
109
113
110
114
Migrating to Qwik 1.14.0 with the Qwik Preloader as the new default should not require much effort on your end, but there are a few changes you should know about.
111
115
112
-
Currently 93% of browsers support “modulepreload”, which wasn't the case when we started using the service worker for “buffering”. For non-supported devices, the preloader will fallback to `<link rel=preload>`, which doesn't compile the code in advance but still works and brings the support to 100%. In effect, you can rest assured all your users will experience lightning speed regardless of their device.
116
+
Currently 93% of browsers support "modulepreload", which wasn't the case when we started using the service worker for "buffering". For non-supported devices, the preloader will fallback to `<link rel=preload>`, which doesn't compile the code in advance but still works and brings the support to 100%. In effect, you can rest assured all your users will experience lightning speed regardless of their device.
113
117
114
118
Here are the Steps you need to follow:
115
119
116
120
### 1. Unregister the service worker
117
121
118
-
The service worker is no longer used, but to make sure it is being uninstalled from your user’s browser (to prevent it making your app slower) we recommend waiting a few weeks/months before removing the `<ServiceWorkerRegister />` from your root component.
122
+
The service worker is no longer used, but to make sure it is being uninstalled from your user's browser (to prevent it making your app slower) we recommend waiting a few weeks/months before removing the `<ServiceWorkerRegister />` from your root component.
119
123
120
124
Both the qwik-city service worker and the experimental Qwik prefetch service worker have been updated to do this automatically for you.
121
125
122
126
So do not remove the service worker registration (in `root.tsx`) from your app just yet. Wait until your users have loaded your site at least once, or long enough for their browser to have cleared the site data.
123
127
124
-
### 2. IMPORTANT: Configure Your Cache-Control headers
128
+
### 2. IMPORTANT: Configure your Cache-Control headers
125
129
126
-
With the service worker no longer forcibly caching bundles, it’s important that you configure appropriate HTTP caching headers using your cloud provider's recommended way of setting them up, for example using vercel.json for Vercel or netlify.toml for Netlify.
130
+
With the service worker no longer forcibly caching bundles, it's important that you configure appropriate HTTP caching headers using your cloud provider's recommended way of setting them up, for example using vercel.json for Vercel or netlify.toml for Netlify.
127
131
128
132
The bundles and assets are normally served at `/build` and `/assets`, respectively. Their filenames contain a content-based hash, making them immutable. If they change, their name changes as well. You can therefore set long-lived caching headers for these.
129
133
@@ -141,11 +145,11 @@ If your app uses [`compiled-i18n`](https://github.com/wmertens/compiled-i18n) or
141
145
142
146
Note that this was also a problem with the service worker, and now you have the ability to configure the cache headers for these files, so it's a positive change.
143
147
144
-
### 4. Enjoy!
148
+
### 4. Enjoy a much faster experience!
145
149
146
-
We’ve worked countless hours for the past few months, manually testing fixes on simulated and real (old phones) environments in order to pin-point all the issues and make sure Qwik holds true to its promise of delivering the best user experience..
150
+
We've worked countless hours for the past few months, manually testing fixes on simulated and real (old phones) environments in order to pin-point all the issues and make sure Qwik holds true to its promise of delivering the best user experience..
147
151
148
-
Now that this is fixed, we are shifting our focus back to the upcoming release of Qwik V2.
152
+
Now that this is fixed, we are shifting our focus back to the upcoming release of Qwik V2.
0 commit comments