@intlayer/docs 8.12.2 → 8.12.4-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/blog.cjs.map +1 -1
- package/dist/cjs/common.cjs.map +1 -1
- package/dist/cjs/doc.cjs.map +1 -1
- package/dist/cjs/frequentQuestions.cjs.map +1 -1
- package/dist/cjs/generated/blog.entry.cjs +1 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +1 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +1 -0
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +1 -0
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/dist/cjs/legal.cjs.map +1 -1
- package/dist/esm/blog.mjs.map +1 -1
- package/dist/esm/common.mjs.map +1 -1
- package/dist/esm/doc.mjs.map +1 -1
- package/dist/esm/frequentQuestions.mjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
- package/dist/esm/generated/legal.entry.mjs.map +1 -1
- package/dist/esm/legal.mjs.map +1 -1
- package/dist/types/blog.d.ts.map +1 -1
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/doc.d.ts.map +1 -1
- package/dist/types/frequentQuestions.d.ts.map +1 -1
- package/dist/types/legal.d.ts.map +1 -1
- package/docs/ar/bundle_optimization.md +250 -102
- package/docs/ar/configuration.md +10 -10
- package/docs/bn/bundle_optimization.md +252 -104
- package/docs/bn/configuration.md +10 -10
- package/docs/cs/bundle_optimization.md +253 -105
- package/docs/cs/configuration.md +10 -10
- package/docs/de/bundle_optimization.md +245 -97
- package/docs/de/configuration.md +10 -10
- package/docs/en/bundle_optimization.md +172 -49
- package/docs/en/configuration.md +10 -10
- package/docs/en-GB/bundle_optimization.md +230 -82
- package/docs/en-GB/configuration.md +10 -10
- package/docs/es/bundle_optimization.md +250 -102
- package/docs/es/configuration.md +10 -10
- package/docs/fr/bundle_optimization.md +223 -75
- package/docs/fr/configuration.md +10 -10
- package/docs/hi/bundle_optimization.md +253 -105
- package/docs/hi/configuration.md +10 -10
- package/docs/id/bundle_optimization.md +258 -110
- package/docs/id/configuration.md +10 -10
- package/docs/it/bundle_optimization.md +249 -103
- package/docs/it/configuration.md +10 -10
- package/docs/ja/bundle_optimization.md +245 -97
- package/docs/ja/configuration.md +10 -10
- package/docs/ko/bundle_optimization.md +253 -105
- package/docs/ko/configuration.md +10 -10
- package/docs/nl/bundle_optimization.md +249 -101
- package/docs/nl/configuration.md +10 -10
- package/docs/pl/bundle_optimization.md +258 -111
- package/docs/pl/configuration.md +10 -10
- package/docs/pt/bundle_optimization.md +256 -115
- package/docs/pt/configuration.md +10 -10
- package/docs/ru/bundle_optimization.md +253 -105
- package/docs/ru/configuration.md +10 -10
- package/docs/tr/bundle_optimization.md +255 -107
- package/docs/tr/configuration.md +10 -10
- package/docs/uk/bundle_optimization.md +250 -102
- package/docs/uk/configuration.md +10 -10
- package/docs/ur/bundle_optimization.md +257 -109
- package/docs/ur/configuration.md +10 -10
- package/docs/vi/bundle_optimization.md +259 -111
- package/docs/vi/configuration.md +10 -10
- package/docs/zh/bundle_optimization.md +260 -112
- package/docs/zh/configuration.md +10 -10
- package/docs/zh-TW/bundle_optimization.md +602 -0
- package/package.json +8 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-11-25
|
|
3
|
-
updatedAt: 2026-
|
|
4
|
-
title:
|
|
5
|
-
description: Reduce application bundle size by optimising internationalisation (i18n) content. Learn how to leverage tree shaking and lazy loading for dictionaries with Intlayer.
|
|
3
|
+
updatedAt: 2026-06-07
|
|
4
|
+
title: i18n Bundle Size & Performance Optimisation
|
|
5
|
+
description: Reduce your application bundle size by optimising internationalisation (i18n) content. Learn how to leverage tree shaking and lazy loading for dictionaries with Intlayer.
|
|
6
6
|
keywords:
|
|
7
7
|
- Bundle Optimisation
|
|
8
8
|
- Content Automation
|
|
@@ -16,33 +16,36 @@ slugs:
|
|
|
16
16
|
- concept
|
|
17
17
|
- bundle-optimization
|
|
18
18
|
history:
|
|
19
|
+
- version: 8.12.0
|
|
20
|
+
date: 2026-06-07
|
|
21
|
+
changes: "Added `intlayerPurgeBabelPlugin` and `intlayerMinifyBabelPlugin` for Babel/Webpack; clarified the plugin pipeline"
|
|
19
22
|
- version: 8.7.0
|
|
20
23
|
date: 2026-04-08
|
|
21
|
-
changes: "
|
|
24
|
+
changes: "Added `minify` and `purge` options to build configuration"
|
|
22
25
|
---
|
|
23
26
|
|
|
24
|
-
#
|
|
27
|
+
# i18n Bundle Size & Performance Optimisation
|
|
25
28
|
|
|
26
|
-
One of the most common challenges with traditional i18n solutions relying on JSON files is managing content size. If developers do not manually separate content into namespaces, users often end up downloading translations for every page and potentially every language just to view a single page.
|
|
29
|
+
One of the most common challenges with traditional i18n solutions relying on JSON files is managing content size. If developers do not manually separate content into namespaces, users often end up downloading the translations for every page and potentially every language just to view a single page.
|
|
27
30
|
|
|
28
|
-
For example, an application with 10 pages translated into 10 languages
|
|
31
|
+
For example, an application with 10 pages translated into 10 languages could result in a user downloading 100 pages' worth of content, even though they only need **one** (the current page in the current language). This leads to wasted bandwidth and slower load times.
|
|
29
32
|
|
|
30
|
-
**Intlayer solves this problem through build-time optimisation.** It analyses your code to detect which dictionaries are actually used per component and
|
|
33
|
+
**Intlayer solves this problem through build-time optimisation.** It analyses your code to detect exactly which dictionaries are actually used per component and re-injects only the necessary content into your bundle.
|
|
31
34
|
|
|
32
35
|
## Table of Contents
|
|
33
36
|
|
|
34
37
|
<TOC />
|
|
35
38
|
|
|
36
|
-
##
|
|
39
|
+
## Analyse your bundle
|
|
37
40
|
|
|
38
|
-
Analysing your bundle is the first step
|
|
41
|
+
Analysing your bundle is the first step to identifying "heavy" JSON files and opportunities for code-splitting. These tools generate a visual treemap of your application's compiled code, allowing you to see exactly which libraries are taking up the most space.
|
|
39
42
|
|
|
40
43
|
<Tabs>
|
|
41
44
|
<Tab value="vite">
|
|
42
45
|
|
|
43
46
|
### Vite / Rollup
|
|
44
47
|
|
|
45
|
-
Vite uses Rollup under the hood. The `rollup-plugin-visualizer` generates an interactive HTML file showing the size of
|
|
48
|
+
Vite uses Rollup under the hood. The `rollup-plugin-visualizer` generates an interactive HTML file showing the size of each module in your graph.
|
|
46
49
|
|
|
47
50
|
```bash
|
|
48
51
|
npm install -D rollup-plugin-visualizer
|
|
@@ -69,7 +72,7 @@ export default defineConfig({
|
|
|
69
72
|
|
|
70
73
|
### Next.js (Turbopack)
|
|
71
74
|
|
|
72
|
-
For projects using the App Router and Turbopack, Next.js provides a built-in experimental analyser that requires no extra dependencies.
|
|
75
|
+
For projects using the App Router and Turbopack, Next.js provides a built-in, experimental analyser that requires no extra dependencies.
|
|
73
76
|
|
|
74
77
|
```bash packageManager='npm'
|
|
75
78
|
npx next experimental-analyze
|
|
@@ -131,7 +134,7 @@ ANALYZE=true npm run build
|
|
|
131
134
|
|
|
132
135
|
### Standard Webpack
|
|
133
136
|
|
|
134
|
-
For Create React App (ejected), Angular, or custom Webpack setups, use the industry
|
|
137
|
+
For Create React App (ejected), Angular, or custom Webpack setups, use the industry standard `webpack-bundle-analyzer`.
|
|
135
138
|
|
|
136
139
|
```bash packageManager='npm'
|
|
137
140
|
npm install -D webpack-bundle-analyzer
|
|
@@ -149,7 +152,7 @@ pnpm add -D webpack-bundle-analyzer
|
|
|
149
152
|
bun add -d webpack-bundle-analyzer
|
|
150
153
|
```
|
|
151
154
|
|
|
152
|
-
```typescript fileName="webpack.config.ts
|
|
155
|
+
```typescript fileName="webpack.config.ts"
|
|
153
156
|
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
|
154
157
|
|
|
155
158
|
export default {
|
|
@@ -166,19 +169,56 @@ export default {
|
|
|
166
169
|
</Tab>
|
|
167
170
|
</Tabs>
|
|
168
171
|
|
|
169
|
-
## How
|
|
172
|
+
## How it works
|
|
170
173
|
|
|
171
|
-
Intlayer uses a **per-component approach**. Unlike global JSON files, your content is defined alongside or within your components. During the build process, Intlayer:
|
|
174
|
+
Intlayer uses a **per-component approach**. Unlike global JSON files, your content is defined alongside or within your components. During the build process, Intlayer will:
|
|
172
175
|
|
|
173
|
-
1.
|
|
174
|
-
2.
|
|
175
|
-
3.
|
|
176
|
+
1. **Analyse** your code to find `useIntlayer` calls.
|
|
177
|
+
2. **Build** the corresponding dictionary content.
|
|
178
|
+
3. **Replace** the `useIntlayer` call with optimised code based on your configuration.
|
|
176
179
|
|
|
177
180
|
This ensures that:
|
|
178
181
|
|
|
179
182
|
- If a component is not imported, its content is not included in the bundle (Dead Code Elimination).
|
|
180
183
|
- If a component is lazy-loaded, its content is also lazy-loaded.
|
|
181
184
|
|
|
185
|
+
## Plugin Reference
|
|
186
|
+
|
|
187
|
+
Intlayer's build optimisation is split into several discrete plugins, each with a single responsibility. Understanding what each one does prevents confusion when configuring them.
|
|
188
|
+
|
|
189
|
+
### Babel plugins (`@intlayer/babel`)
|
|
190
|
+
|
|
191
|
+
These are used directly in `babel.config.js` for Webpack-based setups (Next.js with Babel, CRA, custom Webpack, etc).
|
|
192
|
+
|
|
193
|
+
| Plugin | What it does |
|
|
194
|
+
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------ |
|
|
195
|
+
| `intlayerExtractBabelPlugin` | Scans `.content.ts` files and writes compiled dictionaries to `.intlayer/` |
|
|
196
|
+
| `intlayerOptimizeBabelPlugin` | Rewrites `useIntlayer('key')` → `useDictionary(hash)` and injects the matching dictionary `import` |
|
|
197
|
+
| `intlayerPurgeBabelPlugin` | Scans all source files, removes **unused content fields** from the compiled `.intlayer/**/*.json` dictionary files |
|
|
198
|
+
| `intlayerMinifyBabelPlugin` | **Renames content field keys** to short alphabetical aliases (`title` → `a`) in both JSON files and the source code |
|
|
199
|
+
|
|
200
|
+
> **Plugin order matters.** In your `babel.config.js` the purge and minify plugins must appear **before** the optimize plugin. The optimize pass replaces `useIntlayer('key')` with an opaque `useDictionary(hash)` call, wiping out the dictionary key information the purge and minify passes need to identify which fields are used.
|
|
201
|
+
|
|
202
|
+
Each Babel plugin has a corresponding options helper that reads your `intlayer.config.ts` once at config load time and returns pre-resolved values:
|
|
203
|
+
|
|
204
|
+
| Options helper | Used with |
|
|
205
|
+
| :--------------------------- | :---------------------------- |
|
|
206
|
+
| `getExtractPluginOptions()` | `intlayerExtractBabelPlugin` |
|
|
207
|
+
| `getOptimizePluginOptions()` | `intlayerOptimizeBabelPlugin` |
|
|
208
|
+
| `getPurgePluginOptions()` | `intlayerPurgeBabelPlugin` |
|
|
209
|
+
| `getMinifyPluginOptions()` | `intlayerMinifyBabelPlugin` |
|
|
210
|
+
|
|
211
|
+
### Vite plugins (`vite-intlayer`)
|
|
212
|
+
|
|
213
|
+
Vite users **never configure these directly**. They are wired up automatically when you call `withIntlayer()` in `vite.config.ts`. The `build.purge` and `build.minify` flags in `intlayer.config.ts` toggle the corresponding behaviour without any extra plugin registration.
|
|
214
|
+
|
|
215
|
+
| Internal Vite plugin | Equivalent behaviour |
|
|
216
|
+
| :------------------- | :------------------------------------------------------------------------------------- |
|
|
217
|
+
| Usage analyzer | Same as `intlayerPurgeBabelPlugin` analyse pass |
|
|
218
|
+
| Dictionary prune | Same as `intlayerPurgeBabelPlugin` JSON write pass |
|
|
219
|
+
| Dictionary minify | Same as `intlayerMinifyBabelPlugin` JSON write pass |
|
|
220
|
+
| Babel transform | Same as `intlayerMinifyBabelPlugin` source code rename + `intlayerOptimizeBabelPlugin` |
|
|
221
|
+
|
|
182
222
|
## Setup by Platform
|
|
183
223
|
|
|
184
224
|
<Tabs>
|
|
@@ -186,9 +226,9 @@ This ensures that:
|
|
|
186
226
|
|
|
187
227
|
### Next.js
|
|
188
228
|
|
|
189
|
-
Next.js requires the `@intlayer/swc` plugin
|
|
229
|
+
Next.js requires the `@intlayer/swc` plugin for the optimise (import rewrite) pass, because Next.js uses SWC for builds.
|
|
190
230
|
|
|
191
|
-
> This plugin is not installed by default
|
|
231
|
+
> This plugin is not installed by default as SWC plugins are still experimental for Next.js. This may change in the future.
|
|
192
232
|
|
|
193
233
|
```bash packageManager="npm"
|
|
194
234
|
npm install -D @intlayer/swc
|
|
@@ -206,21 +246,63 @@ pnpm add -D @intlayer/swc
|
|
|
206
246
|
bun add -d @intlayer/swc
|
|
207
247
|
```
|
|
208
248
|
|
|
209
|
-
Once
|
|
249
|
+
Once installed, Intlayer will automatically detect and use the plugin.
|
|
250
|
+
|
|
251
|
+
For the **purge and minify** passes (field removal and field rename), install `@intlayer/babel` alongside it and add the Babel plugins. Because Next.js uses SWC for transformation but still evaluates `babel.config.js` for plugin config, the Babel plugins run as a pre-pass before SWC.
|
|
252
|
+
|
|
253
|
+
```bash packageManager="npm"
|
|
254
|
+
npm install -D @intlayer/babel
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```javascript fileName="babel.config.js"
|
|
258
|
+
const {
|
|
259
|
+
intlayerPurgeBabelPlugin,
|
|
260
|
+
intlayerMinifyBabelPlugin,
|
|
261
|
+
getPurgePluginOptions,
|
|
262
|
+
getMinifyPluginOptions,
|
|
263
|
+
} = require("@intlayer/babel");
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
presets: ["next/babel"],
|
|
267
|
+
plugins: [
|
|
268
|
+
// Purge: remove unused content fields from .intlayer/**/*.json
|
|
269
|
+
[intlayerPurgeBabelPlugin, getPurgePluginOptions()],
|
|
270
|
+
// Minify: rename content field keys in JSON + source code
|
|
271
|
+
[intlayerMinifyBabelPlugin, getMinifyPluginOptions()],
|
|
272
|
+
// Note: intlayerOptimizeBabelPlugin is NOT needed here because
|
|
273
|
+
// @intlayer/swc handles the useIntlayer → useDictionary rewrite.
|
|
274
|
+
],
|
|
275
|
+
};
|
|
276
|
+
```
|
|
210
277
|
|
|
211
278
|
</Tab>
|
|
212
279
|
<Tab value="vite">
|
|
213
280
|
|
|
214
281
|
### Vite
|
|
215
282
|
|
|
216
|
-
Vite uses `@intlayer/babel` plugin which is included as dependency of `vite-intlayer`. The optimisation is enabled by default
|
|
283
|
+
Vite uses the `@intlayer/babel` plugin, which is included as a dependency of `vite-intlayer`. The full optimisation pipeline — import rewrite, purge, and minify — is enabled by default and requires no extra plugin registration.
|
|
284
|
+
|
|
285
|
+
Enable purge and minify by setting the corresponding flags in `intlayer.config.ts`:
|
|
286
|
+
|
|
287
|
+
```typescript fileName="intlayer.config.ts"
|
|
288
|
+
import type { IntlayerConfig } from "intlayer";
|
|
289
|
+
|
|
290
|
+
const config: IntlayerConfig = {
|
|
291
|
+
build: {
|
|
292
|
+
purge: true, // remove unused content fields from bundled JSON
|
|
293
|
+
minify: true, // rename content field keys to short aliases
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
export default config;
|
|
298
|
+
```
|
|
217
299
|
|
|
218
300
|
</Tab>
|
|
219
301
|
<Tab value="webpack">
|
|
220
302
|
|
|
221
|
-
### Webpack
|
|
303
|
+
### Webpack (and Next.js with Babel)
|
|
222
304
|
|
|
223
|
-
|
|
305
|
+
Install `@intlayer/babel`:
|
|
224
306
|
|
|
225
307
|
```bash packageManager="npm"
|
|
226
308
|
npm install -D @intlayer/babel
|
|
@@ -238,14 +320,37 @@ pnpm add -D @intlayer/babel
|
|
|
238
320
|
bun add -d @intlayer/babel
|
|
239
321
|
```
|
|
240
322
|
|
|
241
|
-
|
|
323
|
+
Add all four plugins to `babel.config.js` in the correct order:
|
|
324
|
+
|
|
325
|
+
```javascript fileName="babel.config.js"
|
|
242
326
|
const {
|
|
243
|
-
|
|
327
|
+
intlayerExtractBabelPlugin,
|
|
328
|
+
intlayerPurgeBabelPlugin,
|
|
329
|
+
intlayerMinifyBabelPlugin,
|
|
244
330
|
intlayerOptimizeBabelPlugin,
|
|
331
|
+
getExtractPluginOptions,
|
|
332
|
+
getPurgePluginOptions,
|
|
333
|
+
getMinifyPluginOptions,
|
|
334
|
+
getOptimizePluginOptions,
|
|
245
335
|
} = require("@intlayer/babel");
|
|
246
336
|
|
|
247
337
|
module.exports = {
|
|
248
|
-
plugins: [
|
|
338
|
+
plugins: [
|
|
339
|
+
// Extract: compile .content.ts files → .intlayer/**/*.json
|
|
340
|
+
[intlayerExtractBabelPlugin, getExtractPluginOptions()],
|
|
341
|
+
|
|
342
|
+
// Purge: remove unused fields from .intlayer/**/*.json
|
|
343
|
+
// (reads the intlayer.config.ts build.purge flag)
|
|
344
|
+
[intlayerPurgeBabelPlugin, getPurgePluginOptions()],
|
|
345
|
+
|
|
346
|
+
// Minify: rename field keys in JSON + source code
|
|
347
|
+
// (reads the intlayer.config.ts build.minify flag)
|
|
348
|
+
[intlayerMinifyBabelPlugin, getMinifyPluginOptions()],
|
|
349
|
+
|
|
350
|
+
// Optimize: rewrite useIntlayer('key') → useDictionary(hash)
|
|
351
|
+
// Must come last because it erases the dictionary key.
|
|
352
|
+
[intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],
|
|
353
|
+
],
|
|
249
354
|
};
|
|
250
355
|
```
|
|
251
356
|
|
|
@@ -268,43 +373,48 @@ const config: IntlayerConfig = {
|
|
|
268
373
|
importMode: "dynamic",
|
|
269
374
|
},
|
|
270
375
|
build: {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
* Indicates if the build should check TypeScript types
|
|
283
|
-
*/
|
|
284
|
-
checkTypes: false;
|
|
376
|
+
// Replace useIntlayer() calls with direct dictionary imports at build-time.
|
|
377
|
+
// undefined = auto (enabled in production), true = always, false = never.
|
|
378
|
+
optimize: undefined,
|
|
379
|
+
|
|
380
|
+
// Rename content field keys in compiled dictionaries to short alphabetical
|
|
381
|
+
// aliases (e.g. title → a). Reduces JSON size; requires optimize.
|
|
382
|
+
minify: true,
|
|
383
|
+
|
|
384
|
+
// Remove content fields that are never accessed in the source code.
|
|
385
|
+
// Requires optimize.
|
|
386
|
+
purge: true,
|
|
285
387
|
},
|
|
286
388
|
};
|
|
287
389
|
|
|
288
390
|
export default config;
|
|
289
391
|
```
|
|
290
392
|
|
|
291
|
-
>
|
|
393
|
+
> It is recommended to keep the default value (`undefined`) for `optimize` in most cases.
|
|
292
394
|
|
|
293
|
-
> See
|
|
395
|
+
> See the configuration reference for all options: [Configuration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/configuration.md)
|
|
294
396
|
|
|
295
397
|
### Build Options
|
|
296
398
|
|
|
297
|
-
|
|
399
|
+
| Property | Type | Default | Description |
|
|
400
|
+
| :------------- | :--------------------- | :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
401
|
+
| **`optimize`** | `boolean \| undefined` | `undefined` | Enables the import rewrite pass. `undefined` = active in production builds only. `false` disables purge and minify as well. |
|
|
402
|
+
| **`minify`** | `boolean` | `false` | Renames content field keys in compiled JSON files to short alphabetical aliases. Rewrites matching property accesses in the source code as well. Has no effect when `optimize` is `false`. |
|
|
403
|
+
| **`purge`** | `boolean` | `false` | Removes content fields that are never statically accessed in the source code from the compiled JSON files. Has no effect when `optimize` is `false`. |
|
|
298
404
|
|
|
299
|
-
|
|
300
|
-
| :------------- | :-------- | :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
301
|
-
| **`optimize`** | `boolean` | `undefined` | Controls whether build optimisation is enabled. If `true`, Intlayer replaces dictionary calls with optimised injects. If `false`, optimisation is disabled. Ideally set to `true` in production. |
|
|
302
|
-
| **`minify`** | `boolean` | `false` | Whether to minify the dictionaries to reduce the bundle size. |
|
|
303
|
-
| **`purge`** | `boolean" | `false` | Whether to purge the unused keys in dictionaries. |
|
|
405
|
+
### Minification (field key rename)
|
|
304
406
|
|
|
305
|
-
|
|
407
|
+
`build.minify` does **not** minify your JavaScript bundle — your bundler handles that. Instead, it shrinks the compiled dictionary JSON files by replacing every user-defined content field key with a short alphabetical alias:
|
|
306
408
|
|
|
307
|
-
|
|
409
|
+
```
|
|
410
|
+
// Before minification
|
|
411
|
+
{ "title": "Hello", "subtitle": "World" }
|
|
412
|
+
|
|
413
|
+
// After minification
|
|
414
|
+
{ "a": "Hello", "b": "World" }
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
The same rename is applied to all property accesses in your source code, so `content.title` becomes `content.a` in the compiled output. The runtime behaviour is identical.
|
|
308
418
|
|
|
309
419
|
```typescript fileName="intlayer.config.ts"
|
|
310
420
|
import type { IntlayerConfig } from "intlayer";
|
|
@@ -318,11 +428,13 @@ const config: IntlayerConfig = {
|
|
|
318
428
|
export default config;
|
|
319
429
|
```
|
|
320
430
|
|
|
321
|
-
>
|
|
431
|
+
> Minification is skipped when `optimize` is `false` or when `editor.enabled` is `true` (the visual editor requires the original field names to allow editing).
|
|
432
|
+
|
|
433
|
+
> Minification is also skipped for dictionaries loaded via `importMode: 'fetch'` because their JSON is served from a remote API using the original field names — renaming the client-side keys would break the server/client contract.
|
|
322
434
|
|
|
323
|
-
### Purging
|
|
435
|
+
### Purging (unused field removal)
|
|
324
436
|
|
|
325
|
-
|
|
437
|
+
`build.purge` analyses which content fields are actually accessed in your source code and removes all others from the compiled JSON files.
|
|
326
438
|
|
|
327
439
|
```typescript fileName="intlayer.config.ts"
|
|
328
440
|
import type { IntlayerConfig } from "intlayer";
|
|
@@ -336,27 +448,43 @@ const config: IntlayerConfig = {
|
|
|
336
448
|
export default config;
|
|
337
449
|
```
|
|
338
450
|
|
|
339
|
-
|
|
451
|
+
**Example:** a dictionary with five fields where only two are used:
|
|
452
|
+
|
|
453
|
+
```
|
|
454
|
+
// Before purge
|
|
455
|
+
{ "title": "…", "subtitle": "…", "cta": "…", "footer": "…", "badge": "…" }
|
|
456
|
+
|
|
457
|
+
// After purge (only title + subtitle accessed in source)
|
|
458
|
+
{ "title": "…", "subtitle": "…" }
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
> Purge is skipped when `optimize` is `false` or when `editor.enabled` is `true`.
|
|
462
|
+
|
|
463
|
+
> Purge is also conservatively skipped when a source file cannot be parsed, or when the result of `useIntlayer` is assigned to a variable and passed around in ways the static analyser cannot track (e.g. spread into an object, passed as a prop without destructuring). In those cases, the full dictionary is preserved.
|
|
340
464
|
|
|
341
465
|
### Import Mode
|
|
342
466
|
|
|
343
|
-
For large applications, including several pages and locales, your JSON can represent
|
|
467
|
+
For large applications, including several pages and locales, your JSON can represent an important part of your bundle size. Intlayer allows you to control how dictionaries are loaded using the `importMode` option.
|
|
468
|
+
|
|
469
|
+
### Global definition
|
|
344
470
|
|
|
345
|
-
The import mode can be defined
|
|
471
|
+
The import mode can be defined globally in your `intlayer.config.ts` file.
|
|
346
472
|
|
|
347
473
|
```typescript fileName="intlayer.config.ts"
|
|
348
474
|
import type { IntlayerConfig } from "intlayer";
|
|
349
475
|
|
|
350
476
|
const config: IntlayerConfig = {
|
|
351
|
-
|
|
352
|
-
|
|
477
|
+
dictionary: {
|
|
478
|
+
importMode: "dynamic", // Default is 'static'
|
|
353
479
|
},
|
|
354
480
|
};
|
|
355
481
|
|
|
356
482
|
export default config;
|
|
357
483
|
```
|
|
358
484
|
|
|
359
|
-
|
|
485
|
+
### Per-dictionary definition
|
|
486
|
+
|
|
487
|
+
You can override the import mode for individual dictionaries in their `.content.{{ts|tsx|js|jsx|mjs|cjs|json|jsonc|json5|md|mdx|yaml|yml}}` files.
|
|
360
488
|
|
|
361
489
|
```ts
|
|
362
490
|
import { type Dictionary, t } from "intlayer";
|
|
@@ -372,28 +500,28 @@ const appContent: Dictionary = {
|
|
|
372
500
|
export default appContent;
|
|
373
501
|
```
|
|
374
502
|
|
|
375
|
-
| Property | Type | Default | Description
|
|
376
|
-
| :--------------- | :--------------------------------- | :--------- |
|
|
377
|
-
| **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` | **Deprecated**: Use `dictionary.importMode` instead. Determines how dictionaries are loaded (see
|
|
503
|
+
| Property | Type | Default | Description |
|
|
504
|
+
| :--------------- | :--------------------------------- | :--------- | :------------------------------------------------------------------------------------------------------- |
|
|
505
|
+
| **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` | **Deprecated**: Use `dictionary.importMode` instead. Determines how dictionaries are loaded (see below). |
|
|
378
506
|
|
|
379
|
-
The `importMode` setting
|
|
380
|
-
You can define it globally in the `intlayer.config.ts` file under the `dictionary` object, or you can overwrite it for a specific dictionary in its `.content.ts` file.
|
|
507
|
+
The `importMode` setting determines how the dictionary's content is injected into your component. You can define it globally in `intlayer.config.ts` under the `dictionary` object, or override it on a per-dictionary basis in its `.content.ts` file.
|
|
381
508
|
|
|
382
509
|
### 1. Static Mode (`default`)
|
|
383
510
|
|
|
384
511
|
In static mode, Intlayer replaces `useIntlayer` with `useDictionary` and injects the dictionary directly into the JavaScript bundle.
|
|
385
512
|
|
|
386
|
-
- **Pros:** Instant rendering (synchronous), zero
|
|
513
|
+
- **Pros:** Instant rendering (synchronous), zero additional network requests during hydration.
|
|
387
514
|
- **Cons:** The bundle includes translations for **all** available languages for that specific component.
|
|
388
515
|
- **Best for:** Single Page Applications (SPA).
|
|
389
516
|
|
|
390
|
-
**Transformed
|
|
517
|
+
**Transformed code example:**
|
|
391
518
|
|
|
392
519
|
```tsx
|
|
393
520
|
// Your code
|
|
394
521
|
const content = useIntlayer("my-key");
|
|
395
522
|
|
|
396
|
-
// Optimised code (Static)
|
|
523
|
+
// Optimised code illustration after transformation (Static)
|
|
524
|
+
// This is for illustration only, the actual code will differ for optimisation reasons
|
|
397
525
|
const content = useDictionary({
|
|
398
526
|
key: "my-key",
|
|
399
527
|
content: {
|
|
@@ -408,19 +536,20 @@ const content = useDictionary({
|
|
|
408
536
|
|
|
409
537
|
### 2. Dynamic Mode
|
|
410
538
|
|
|
411
|
-
In dynamic mode, Intlayer replaces `useIntlayer` with `useDictionaryAsync`. This uses `import()` (Suspense-like mechanism) to lazy-load specifically the JSON for the current locale.
|
|
539
|
+
In dynamic mode, Intlayer replaces the `useIntlayer` with `useDictionaryAsync`. This uses `import()` (a Suspense-like mechanism) to lazy-load specifically the JSON for the current locale.
|
|
412
540
|
|
|
413
|
-
- **Pros:** **Locale-level tree shaking.** A user viewing the English version will _only_
|
|
541
|
+
- **Pros:** **Locale-level tree shaking.** A user viewing the English version will download _only_ the English dictionary. The French dictionary is never loaded.
|
|
414
542
|
- **Cons:** Triggers a network request (asset fetch) per component during hydration.
|
|
415
543
|
- **Best for:** Large text blocks, articles, or applications supporting many languages where bundle size is critical.
|
|
416
544
|
|
|
417
|
-
**Transformed
|
|
545
|
+
**Transformed code example:**
|
|
418
546
|
|
|
419
547
|
```tsx
|
|
420
548
|
// Your code
|
|
421
549
|
const content = useIntlayer("my-key");
|
|
422
550
|
|
|
423
|
-
// Optimised code (Dynamic)
|
|
551
|
+
// Optimised code illustration after transformation (Dynamic)
|
|
552
|
+
// This is for illustration only, the actual code will differ for optimisation reasons
|
|
424
553
|
const content = useDictionaryAsync({
|
|
425
554
|
en: () =>
|
|
426
555
|
import(".intlayer/dynamic_dictionary/my-key/en.json").then(
|
|
@@ -433,22 +562,41 @@ const content = useDictionaryAsync({
|
|
|
433
562
|
});
|
|
434
563
|
```
|
|
435
564
|
|
|
436
|
-
> When using `importMode: 'dynamic'`, if you have 100 components using `useIntlayer` on a single page, the browser will attempt 100 separate fetches. To avoid this "waterfall" of requests, group content into fewer `.content` files (e.g
|
|
565
|
+
> When using `importMode: 'dynamic'`, if you have 100 components using `useIntlayer` on a single page, the browser will attempt 100 separate fetches. To avoid this "waterfall" of requests, group content into fewer `.content` files (e.g. one dictionary per page section) instead of one per atom component. You can also use multiple `.content` files that use the same key. Intlayer will merge them into a single dictionary.
|
|
437
566
|
|
|
438
567
|
### 3. Fetch Mode
|
|
439
568
|
|
|
440
569
|
Behaves similarly to Dynamic mode but attempts to fetch dictionaries from the Intlayer Live Sync API first. If the API call fails or the content is not marked for live updates, it falls back to the dynamic import.
|
|
441
570
|
|
|
571
|
+
**Transformed code example:**
|
|
572
|
+
|
|
573
|
+
```tsx
|
|
574
|
+
// Your code
|
|
575
|
+
const content = useIntlayer("my-key");
|
|
576
|
+
|
|
577
|
+
// Optimised code illustration (Fetch)
|
|
578
|
+
const content = useDictionaryAsync({
|
|
579
|
+
en: () =>
|
|
580
|
+
fetch("https://intlayer.my-domain.com/dictionary/my-key/en").then((res) =>
|
|
581
|
+
res.json()
|
|
582
|
+
),
|
|
583
|
+
fr: () =>
|
|
584
|
+
fetch("https://intlayer.my-domain.com/dictionary/my-key/fr").then((res) =>
|
|
585
|
+
res.json()
|
|
586
|
+
),
|
|
587
|
+
});
|
|
588
|
+
```
|
|
589
|
+
|
|
442
590
|
> See CMS documentation for more details: [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/intlayer_CMS.md)
|
|
443
591
|
|
|
444
|
-
> In fetch mode, purge and minification
|
|
592
|
+
> In fetch mode, purge and minification are not applied because the JSON is served from a remote API using the original field names.
|
|
445
593
|
|
|
446
594
|
## Summary: Static vs Dynamic
|
|
447
595
|
|
|
448
|
-
| Feature | Static Mode
|
|
449
|
-
| :------------------- |
|
|
450
|
-
| **JS Bundle Size** | Larger (includes all
|
|
451
|
-
| **Initial Load** | Instant (Content is in bundle)
|
|
452
|
-
| **Network Requests** | 0 extra requests
|
|
453
|
-
| **Tree Shaking** | Component-level
|
|
454
|
-
| **Best Use Case** | UI Components, Small Apps
|
|
596
|
+
| Feature | Static Mode | Dynamic Mode |
|
|
597
|
+
| :------------------- | :------------------------------------------------ | :------------------------------- |
|
|
598
|
+
| **JS Bundle Size** | Larger (includes all languages for the component) | Smallest (code only, no content) |
|
|
599
|
+
| **Initial Load** | Instant (Content is in bundle) | Slight delay (Fetches JSON) |
|
|
600
|
+
| **Network Requests** | 0 extra requests | 1 request per dictionary key |
|
|
601
|
+
| **Tree Shaking** | Component-level | Component-level + Locale-level |
|
|
602
|
+
| **Best Use Case** | UI Components, Small Apps | Text-heavy pages, Many Languages |
|
|
@@ -681,16 +681,16 @@ routing: {
|
|
|
681
681
|
|
|
682
682
|
When using cookie storage, you can configure additional cookie attributes:
|
|
683
683
|
|
|
684
|
-
| Field | Description
|
|
685
|
-
| ---------- |
|
|
686
|
-
| `name` | Cookie name. Default: `'INTLAYER_LOCALE'`
|
|
687
|
-
| `domain` | Cookie domain. Default: `undefined`
|
|
688
|
-
| `path` | Cookie path. Default: `undefined`
|
|
689
|
-
| `secure` | Require HTTPS. Default: `undefined`
|
|
690
|
-
| `httpOnly` | HTTP-only flag. Default: `undefined`
|
|
691
|
-
| `sameSite` | SameSite policy.
|
|
692
|
-
| `expires` |
|
|
693
|
-
| `maxAge` | Lifetime in seconds from creation. Takes precedence over `expires`. Default: `undefined`
|
|
684
|
+
| Field | Description | Type |
|
|
685
|
+
| ---------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
|
686
|
+
| `name` | Cookie name. Default: `'INTLAYER_LOCALE'` | `string` |
|
|
687
|
+
| `domain` | Cookie domain. Default: `undefined` | `string` |
|
|
688
|
+
| `path` | Cookie path. Default: `undefined` | `string` |
|
|
689
|
+
| `secure` | Require HTTPS. Default: `undefined` | `boolean` |
|
|
690
|
+
| `httpOnly` | HTTP-only flag. Default: `undefined` | `boolean` |
|
|
691
|
+
| `sameSite` | SameSite policy. | `'strict'` | <br/> `'lax'` | <br/> `'none'` |
|
|
692
|
+
| `expires` | A `number` is days from creation; a `Date` (or ISO date string) is an absolute expiry. Default: `undefined` | `Date` | <br/> `number` | <br/> `string` |
|
|
693
|
+
| `maxAge` | Lifetime in seconds from creation. Takes precedence over `expires`. Default: `undefined` | `number` |
|
|
694
694
|
|
|
695
695
|
#### Locale Storage Attributes
|
|
696
696
|
|