opral / inlang-paraglide-js

Tree-shakable i18n library build on the inlang ecosystem.
https://inlang.com/m/gerre34r/library-inlang-paraglideJs
42 stars 0 forks source link

ParaglideJS Per-Language Splitting #22

Closed LorisSigrist closed 6 months ago

LorisSigrist commented 6 months ago

Problem

Paraglide's most unique feature is the tree-shakeable messages. That way only messages that are used on any given page are actually shipped to the page.

The tradeoff so-far has been that messages are sent in all languages. We did some benchmarks & concluded that unless you have more than 10 languages that tradeoff is usually worth it, since you save so much on runtime-size and tree-shaking.

However, per-language splitting has always been a long-term goal for paraglide. If we were to manage it, not only would paraglide be the smallest i18n library, it would actually have a 30% lower amortization cost than any other library, meaning that the gap widens as you add more messages.

The problem so far has been that any form of lazy-loading necessarily breaks tree-shaking.

Proposal

I finally found a good way to do per-language splitting and keep the tree-shaking.

Loom: https://www.loom.com/share/6fd59b087a2745e4ab12d7ed15dd9fac

The idea: Define a $messages("message_id") identifier that survives minification. Then, once the build is done, we can scan through all the output files & find all the instances of the $messages identifier. This tells us which messages are used in that file.

We then generate a corresponding <filename>.messages.js file that includes a runtime to lazy-load exactly those messages.

We then replace all instances of $messages in the original file with the import from the <filename>.messages.js file.

This can be made to work from just a CLI, so we aren't limited by the availability of build-tools.

linear[bot] commented 6 months ago

PARJS-25 ParaglideJS Per-Language Splitting