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.
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.
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.