Skip to content

Commit

Permalink
Merge pull request #2442 from opral/add-how-to-write-adapter-guide
Browse files Browse the repository at this point in the history
Add Waterfall Graphic to Lazy-Loading guide
  • Loading branch information
LorisSigrist authored Mar 21, 2024
2 parents 3904afc + d7d27a2 commit 6f8b764
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
29 changes: 22 additions & 7 deletions inlang/guides/dont-lazy-load/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,22 @@ init({

This is well-intentioned. You shouldn't send what you don't use. Unfortunately it's also very bad for your web-vitals, specifically Time-to-Interactive.

In order to lazy-load you need to execute the JS for your i18n runtime. This means that your app's entire module-graph needs to be fully downloaded, parsed and executed before you even start _loading_. This is worse than a regular waterfall, since you usually don't need to execute before loading. This can easily add 300ms+ to your app's time-to-interactive, regardless of how few/many messages you are loading.
In order to lazy-load you need to execute the JS for your i18n runtime. This means that your app's entire module-graph needs to be fully downloaded, parsed and executed before you even start _loading_.

![Illustration of a loading-waterfall showing how lazy-loading takes longer over all](https://cdn.jsdelivr.net/gh/opral/monorepo@latest/inlang/guides/dont-lazy-load/assets/waterfall.png)

This is worse than a regular waterfall, since you usually don't need to execute JS before the waterfall starts. This can easily add 300ms+ to your app's time-to-interactive, regardless of how few/many messages you are loading.

In SPA apps it's even worse since your first render is blocked until the translations are loaded.

## What should I do instead?
You need to find a way to statically link translations in the correct language on your pages. Either through imports, or by eagerly loading the needed translations in load functions.

If you have a content-focused site this may be as simple as having separate components for each language. In them you can only import the translations that you need.
You need to find a way to statically link translations in the correct language on your pages.
This can be done one a few ways:
- Through `import` statements that only load the messages in the correct language
- By passing the necessary messages from the server to the client as part of the initial data payload

On content-focused sites static linking can be as simple as having separate page-components for each language. In them, only import the translations that you need.

```txt
app/
Expand All @@ -31,14 +41,19 @@ app/
```ts
// de/page.tsx
import * as m from "@/paraglide/messages/de.js" // <-- Import only german messages
//en/page.tsx
import * as m from "@/paraglide/messages/en.js" // <-- Import only english messages
```
This works great as long as you don't need to load data. If you do, having separate components for each language would require duplicating your load-logic. We don't want that.
This works as long as you don't need to load data on the server. If you do, separate components for each language would require duplicating loading-logic. We don't want that.
In that case you are reliant on your framework being able to build your pages separately for each language. Lit, Angular and Qwik do just that.
In that case you are reliant on your framework being able to build your pages separately for each language. Lit, Angular and Qwik do just that. If your stack can't, you may want to consider the nuclear option.
If your framework can't do that you will want to consider the nuclear option. Eagerly loading _all_ languages is almost always better than lazy-loading a single language. Yes, it's wasteful to your user's badwidth, but not _that_ wasteful. Text is very small; Entire novels fit into 350kB. The latency-savings from not lazy-loading offset the increase in bandwidth.
It's usually better to send over _all_ languages egaerly than to lazy load a single language. This is wasteful of your user's badwidth, but it's not _that_ wasteful. Text is very small; Entire novels fit into 350kB. The latency-savings from not lazy-loading more than offset the increase in bandwidth.
This is most noticeable if you have fewer messages & fewer languages, but it persists even for large sites.
An example of the nuclear option in action is [galaxus.ch](https://www.galaxus.ch/). It's a very well-made NextJS site that loads very quickly. Not despite loading all languages, but because of it.
An example of the nuclear option in action is [galaxus.ch](https://www.galaxus.ch/). It's a very well-made NextJS site that loads very quickly, not despite loading all languages, but because of it.
This is why we chose _not_ to ship lazy-loading in our i18n library [ParaglideJS](https://inlang.com/m/gerre34r/library-inlang-paraglideJs). Instead, we're pursuing ways of statically linking translations in the correct language. If that's not possible we fall back to loading all languages eagerly.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6f8b764

Please sign in to comment.