Autore:
    Creazione:2025-11-25Ultimo aggiornamento:2026-08-09

    Ottimizzazione delle dimensioni e delle prestazioni del bundle i18n

    Una delle sfide più comuni con le tradizionali soluzioni i18n basate su file JSON è la gestione delle dimensioni dei contenuti. Se gli sviluppatori non separano manualmente i contenuti in namespace, gli utenti finiscono spesso per scaricare le traduzioni per ogni pagina e potenzialmente per ogni lingua solo per visualizzare una singola pagina.

    Ad esempio, un'applicazione con 10 pagine tradotte in 10 lingue potrebbe far sì che un utente scarichi il contenuto di 100 pagine, anche se ne ha bisogno solo di una (la pagina attuale nella lingua attuale). Ciò porta a spreco di larghezza di banda e tempi di caricamento più lenti.

    Intlayer risolve questo problema attraverso l'ottimizzazione in fase di compilazione (build). Analizza il tuo codice per rilevare quali dizionari sono effettivamente utilizzati in ciascun componente e inietta solo il contenuto necessario nel tuo bundle.

    Indice dei Contenuti

    Analizza il tuo bundle

    Analizzare il tuo bundle è il primo passo per identificare i file JSON "pesanti" e le opportunità di suddivisione del codice (code-splitting). Questi strumenti generano una visualizzazione treemap del codice compilato della tua applicazione, permettendoti di vedere esattamente quali librerie consumano più spazio.

    Vite / Rollup

    Vite utilizza Rollup sotto il cofano. Il plugin rollup-plugin-visualizer genera un file HTML interattivo che mostra le dimensioni di ogni modulo nel tuo grafo.

    bash
    npm install -D rollup-plugin-visualizer
    vite.config.ts
    import { defineConfig } from "vite";import { visualizer } from "rollup-plugin-visualizer";export default defineConfig({ plugins: [   visualizer({     open: true, // Apre automaticamente il report nel tuo browser     filename: "stats.html",     gzipSize: true,     brotliSize: true,   }), ],});

    Come Funziona

    Intlayer utilizza un approccio per componente. A differenza dei file JSON globali, il tuo contenuto viene definito accanto o all'interno dei tuoi componenti. Durante il processo di build, Intlayer:

    1. Analizza il tuo codice per trovare le chiamate a useIntlayer.
    2. Costruisce il contenuto del dizionario corrispondente.
    3. Sostituisce la chiamata a useIntlayer con un codice ottimizzato in base alla tua configurazione.

    Ciò garantisce che:

    • Se un componente non viene importato, il suo contenuto non viene incluso nel bundle (Dead Code Elimination).
    • Se un componente viene caricato tramite lazy loading, anche il suo contenuto viene caricato in modo lazy.

    Riferimento Plugin

    L'ottimizzazione in fase di build di Intlayer è suddivisa tra diversi plugin discreti, ciascuno con una singola responsabilità. Capire cosa fa ciascuno evita confusione al momento della configurazione.

    Plugin Babel (@intlayer/babel)

    Questi sono usati direttamente nel file babel.config.js per i setup basati su Webpack (Next.js con Babel, CRA, Webpack personalizzato, ecc.).

    La tabella seguente li elenca nel loro ordine di pipeline richiesto (lo stesso ordine in cui devono comparire in babel.config.js):

    Plugin Cosa fa
    intlayerExtractBabelPlugin Scansiona i file .content.ts e scrive i dizionari compilati in .intlayer/
    intlayerPurgeBabelPlugin Scansiona tutti i file sorgente, rimuove i campi di contenuto inutilizzati dai file di dizionario JSON compilati .intlayer/**/*.json
    intlayerMinifyBabelPlugin Rinomina le chiavi dei campi di contenuto in brevi alias alfabetici (titlea) sia nei file JSON che nel codice sorgente
    intlayerOptimizeBabelPlugin Riscrive useIntlayer('key') in useDictionary(hash) e inietta la dichiarazione di import corrispondente al dizionario
    L'ordine dei plugin è importante. Nel tuo babel.config.js i plugin purge e minify devono apparire prima del plugin optimize. La fase optimize sostituisce useIntlayer('key') con una chiamata opaca a useDictionary(hash), cancellando le informazioni della chiave del dizionario di cui le fasi purge e minify hanno bisogno per identificare quali campi vengono usati.

    Ogni plugin Babel ha un relativo helper per le opzioni che legge il tuo intlayer.config.ts una volta sola al momento del caricamento della configurazione e restituisce valori pre-risolti:

    Helper opzioni Usato con
    getExtractPluginOptions() intlayerExtractBabelPlugin
    getPurgePluginOptions() intlayerPurgeBabelPlugin
    getMinifyPluginOptions() intlayerMinifyBabelPlugin
    getOptimizePluginOptions() intlayerOptimizeBabelPlugin

    Plugin Vite (vite-intlayer)

    Gli utenti di Vite non configurano mai questi direttamente. Vengono cablati automaticamente quando chiami withIntlayer() in vite.config.ts. I flag build.purge e build.minify in intlayer.config.ts attivano o disattivano il comportamento corrispondente senza alcuna registrazione extra di plugin.

    Plugin Vite interno Comportamento equivalente
    Usage analyzer Stesso comportamento della fase di analisi in intlayerPurgeBabelPlugin
    Dictionary prune Stesso comportamento della fase di scrittura JSON in intlayerPurgeBabelPlugin
    Dictionary minify Stesso comportamento della fase di scrittura JSON in intlayerMinifyBabelPlugin
    Babel transform Stesso comportamento di ridenominazione codice sorgente intlayerMinifyBabelPlugin + intlayerOptimizeBabelPlugin

    Plugin SWC (@intlayer/swc)

    Nemmeno gli utenti di Next.js configurano mai questi direttamente. Dalla v9.2.1, withIntlayer() in next.config.ts esegue l'intera pipeline — purge, minify e riscrittura degli import — basandosi solo sui flag build.purge e build.minify.

    Il lavoro è diviso in due, perché un plugin Wasm SWC trasforma un file alla volta e non ha accesso al file system:

    Passata Dove viene eseguita Cosa fa
    Analisi d'uso + purge/minify del JSON Node, dentro withIntlayer() Legge ogni file sorgente dei componenti, riscrive .intlayer/**/*.json, produce le tabelle di rinomina
    Riscrittura del sorgente (content.title.a) @intlayer/swc (Wasm) Applica le tabelle di rinomina agli accessi alle proprietà corrispondenti nel tuo codice
    Riscrittura degli import (useIntlayer → dict) @intlayer/swc (Wasm) Come intlayerOptimizeBabelPlugin

    Decidere quali campi sono inutilizzati e quale alias assegnare a ciascuno richiede stato tra file e I/O su file, quindi quella metà viene eseguita in Node; il plugin SWC riceve solo le tabelle risultanti.

    Configurazione per Piattaforma

    Next.js

    Next.js richiede il plugin @intlayer/swc, perché Next.js usa SWC per le build. Dalla v9.2.1 questo singolo pacchetto copre l'intera pipeline — ottimizzazione (riscrittura degli import), purge e minify.

    Questo plugin non è installato di default perché i plugin SWC sono ancora sperimentali in Next.js. Questo aspetto potrebbe cambiare in futuro.
    Next.js 16.1.0 è la versione minima. È la prima release costruita sull'ABI dei plugin Wasm di SWC compatibile in avanti; le release precedenti rifiutano il plugin. withIntlayer legge la tua versione di Next.js e semplicemente non registra il plugin sotto la 16.1.0 — quelle build riescono comunque, semplicemente girano senza l'ottimizzazione del bundle.
    bash
    npm install -D @intlayer/swc

    Una volta installato, Intlayer rileverà e utilizzerà automaticamente il plugin.

    Le passate di purge e minify (rimozione e rinomina dei campi) non richiedono alcun pacchetto aggiuntivo né babel.config.js. Avvolgi la tua configurazione con withIntlayer e attiva i flag in intlayer.config.ts:

    next.config.ts
    import { withIntlayer } from "next-intlayer/server";import type { NextConfig } from "next";const nextConfig: NextConfig = {/* la tua configurazione */};export default withIntlayer(nextConfig);
    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = { build: {   purge: true, // rimuove i campi di contenuto inutilizzati dal JSON incluso nel bundle   minify: true, // rinomina le chiavi dei campi con alias brevi },};export default config;

    Durante next build, withIntlayer analizza i tuoi sorgenti, riscrive i dizionari compilati e passa le tabelle di rinomina risultanti a @intlayer/swc, che aggiorna gli accessi alle proprietà corrispondenti nel tuo codice.

    Usa il withIntlayer asincrono, non withIntlayerSync. La variante sincrona non esegue la pipeline di analisi, quindi purge e minify non hanno alcun effetto con essa.
    Purge e minify vengono eseguiti solo con next build — la pipeline di ottimizzazione è disattivata durante next dev.
    Sono inoltre disabilitati quando sono configurati chiamanti degli adattatori di compatibilità (swcExtraCallers, impostati dai pacchetti di compatibilità come @intlayer/next-intl o @intlayer/react-i18next): quei punti di chiamata sono invisibili all'analizzatore d'uso, quindi il purge rimuoverebbe campi che il codice legge ancora. La riscrittura degli import resta attiva.

    Le versioni precedenti (prima della 9.2.1) richiedevano @intlayer/babel e un babel.config.js che dichiarasse intlayerPurgeBabelPlugin e intlayerMinifyBabelPlugin. Quel file non è più necessario e può essere eliminato.

    Configurazione

    Puoi controllare come Intlayer ottimizza il tuo bundle tramite la proprietà build in intlayer.config.ts.

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.ITALIAN],    defaultLocale: Locales.ENGLISH,  },  dictionary: {    importMode: "dynamic",  },  build: {    // Sostituisce le chiamate useIntlayer() con import diretti al dizionario a tempo di compilazione.    // undefined = automatico (abilitato in produzione), true = sempre, false = mai.    optimize: undefined,    // Rinomina chiavi dei campi di contenuto nei dizionari compilati con alias alfabetici corti    // (es. title → a). Riduce la dimensione del JSON; richiede optimize.    minify: true,    // Rimuove campi di contenuto mai accessibili staticamente nel codice sorgente.    // Richiede optimize.    purge: true,  },};export default config;
    Mantenere il valore predefinito (undefined) per optimize è consigliato nella maggior parte dei casi.
    Consulta il riferimento per la configurazione per tutte le opzioni: Configurazione

    Opzioni di Build

    Proprietà Tipo Default Descrizione
    optimize boolean / undefined undefined Abilita il passaggio di riscrittura degli import. undefined = attivo solo nelle build di produzione. false disabilita anche purge e minify.
    minify boolean false Rinomina chiavi dei campi di contenuto nei file JSON compilati usando brevi alias alfabetici. Riscrive anche gli accessi a tali proprietà nel codice sorgente. Non ha alcun effetto se optimize è false.
    purge boolean false Rimuove i campi di contenuto a cui non si accede mai in modo statico dal codice sorgente all'interno dei file JSON. Non ha alcun effetto se optimize è false.

    Minificazione (ridenominazione chiave dei campi)

    build.minify non si occupa di minificare il tuo bundle JavaScript — quello viene gestito dal tuo bundler. Rimpicciolisce invece i file JSON del dizionario compilato sostituendo ciascuna chiave definita dall'utente con un breve alias alfabetico:

    plaintext
    // Prima della minificazione{ "title": "Ciao", "subtitle": "Mondo" }// Dopo la minificazione{ "a": "Ciao", "b": "Mondo" }

    La medesima modifica viene apportata agli accessi di tali proprietà all'interno del codice sorgente, così che content.title diventi content.a nell'output compilato. Il comportamento in esecuzione rimane identico.

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  build: {    minify: true,  },};export default config;
    La minificazione viene saltata quando optimize è false o quando editor.enabled è true (l'editor visuale richiede il nome completo della proprietà per consentire la modifica).
    Su Next.js la minificazione viene saltata anche quando @intlayer/swc non è installato o non può essere caricato (Next.js sotto la 16.1.0). Il plugin è la metà che riscrive gli accessi nel sorgente, quindi rinominare i dizionari senza di esso lascerebbe il tuo codice a leggere nomi di campi che non esistono più.
    La minificazione viene ignorata anche per i dizionari caricati tramite importMode: 'fetch' perché i loro JSON vengono serviti tramite API remote usando le chiavi dei campi originali; rinominarle rovinerebbe il contratto tra client e server.

    Purging (rimozione dei campi non usati)

    build.purge analizza a quali campi di contenuto accedi effettivamente nel tuo codice sorgente, provvedendo a rimuovere il resto dai file JSON.

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  build: {    purge: true,  },};export default config;

    Esempio: un dizionario di cinque campi dal quale vengono adoperati solamente due:

    plaintext
    // Prima di purge{ "title": "…", "subtitle": "…", "cta": "…", "footer": "…", "badge": "…" }// Dopo aver effettuato purge (solamente accessi di title e subtitle presenti){ "title": "…", "subtitle": "…" }
    Il purge viene saltato se optimize è false o quando editor.enabled è true. Su Next.js viene inoltre saltato quando @intlayer/swc non è disponibile e quando sono configurati chiamanti degli adattatori di compatibilità.
    Il purge viene saltato per precauzione qualora un file non riesca a essere analizzato, oppure se l'oggetto useIntlayer viene riversato in altri valori usando parametri dinamici non analizzabili (come distruggere parti non strutturate, assegnazioni generiche ai props ecc.). In questi scenari viene conservato l'intero dizionario.

    Modalità di Importazione

    Per grandi applicazioni in grado di coprire parecchie pagine e localizzazioni diverse, il peso imposto dal JSON costituisce una quota vitale per il bundle complessivo. Intlayer consente un controllo specifico di come importare i dizionari grazie a importMode.

    Configurazione Globale

    Si può stabilire il valore predefinito agendo in intlayer.config.ts.

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  dictionary: {    importMode: "dynamic", // Di default preimpostato come 'static'  },};export default config;

    Definizione Per Dizionario

    Resta pur sempre valida la sovrascrittura di questo comportamento per ogni singolo file come nel caso descritto dalle estensioni .content.{{ts|tsx|js|jsx|mjs|cjs|json|jsonc|json5|md|mdx|yaml|yml}}.

    ts
    import { type Dictionary, t } from "intlayer";const appContent: Dictionary = {  key: "app",  importMode: "dynamic", // Ridefinisce in che modo caricare i contenuti in locale  content: {    // ...  },};export default appContent;
    Proprietà Tipo Valore base Descrizione
    importMode 'static', 'dynamic', 'fetch' 'static' Deprecato: Usa dictionary.importMode al suo posto. Controlla e stabilisce le dinamiche di importazione di rete.

    Il valore importMode gestisce i flussi in cui iniettare il componente. Lo definisci globalmente in intlayer.config.ts o individualmente per .content.ts.

    1. Modalità Statica (default)

    Utilizzando la modalità statica, Intlayer trasforma e sostituisce le useIntlayer in useDictionary rendendo effettivo l'inserimento integrato di ciascun dato nell'applicativo di base in JavaScript.

    • Vantaggi: Render immediato, con la completa assenza di caricamenti di rete durante la prima inizializzazione.
    • Svantaggi: Tutto l'ammontare linguistico e strutturale relativo alla mole del componente per ciascuna lingua.
    • Caso d'Uso Migliore: Architetture come SPA o pagine singole dalle scarse necessità restrittive in materia.

    Codice Esemplificativo Trasformato:

    tsx
    // Il tuo codice d'origineconst content = useIntlayer("my-key");// Trasformazione Statica (Illustrativa)const content = useDictionary({  key: "my-key",  content: {    nodeType: "translation",    translation: {      en: "My title",      it: "Il mio titolo",    },  },});

    2. Modalità Dinamica

    Impiegando lo status di modulo dinamico, subentra l'interazione rimpiazzando useIntlayer attraverso un comportamento asservito a useDictionaryAsync. È impiegata la parola chiave import() a lazy-load.

    • Vantaggi: Tree-shaking ad alte prestazioni limitate a specifici stati linguistici locali. Si eviterà uno spreco impattante di megabyte impedendo al file italiano di presentarsi ad utenti che godono di preferenze in lingua inglese.
    • Svantaggi: Raggiunge richieste asincrone idonee a innescare il ritardo derivante dal prelievo remoto durante l'hydratation.
    • Miglior utilizzo: Testi complessi o corpose quantità di termini multilingua voluminosi da mantenere compattati o da delegare in caso di necessita di download parziale o differito.

    Codice Trasformato Dinamico:

    tsx
    // Tuo codiceconst content = useIntlayer("my-key");// Rappresentazione in Dinamica di quanto in esecuzioneconst content = useDictionaryAsync({  en: () =>    import(".intlayer/dynamic_dictionary/my-key/en.json").then(      (mod) => mod.default    ),  it: () =>    import(".intlayer/dynamic_dictionary/my-key/it.json").then(      (mod) => mod.default    ),});
    Applicando l'uso in importMode: 'dynamic', non frammentare a vuoto con costanza ma procedi aggregando un insieme in pochi file .content dedicati, cosicché ad impiego congiunto si limitino e si aggreghino prelievi limitrofi ad unica natura. Intlayer fondono se aventi pari identità o parametri limitrofi per le chiavi impiegate con regolarità per medesime identità.

    3. Modalità Fetch

    Svolge iter analogo ed affine per conformità di intenti, mirando piuttosto all'ottenimento delle medesime procedure avvalendosi delle chiamate API da Intlayer Live Sync. Per far risaltare flussi tempestivi dinamici su ambienti reattivi con riciclo d'informazioni in live updates e di ripiego sulla tipologia dinamic.

    Esempio in Fetch:

    tsx
    // Il tuo codiceconst content = useIntlayer("my-key");// Ottimizzato secondo l'uso di base fetchconst content = useDictionaryAsync({  en: () =>    fetch("https://intlayer.my-domain.com/dictionary/my-key/en").then((res) =>      res.json()    ),  it: () =>    fetch("https://intlayer.my-domain.com/dictionary/my-key/it").then((res) =>      res.json()    ),});
    Ulteriori verifiche presso il riferimento ai supporti per la documentazione CMS: CMS
    Nella struttura fetch le ottimizzazioni relative a minify o purge passano sempre inosservate al fine di favorire la corrispondenza lato server in nome delle relative comunicazioni.

    Sommario: Statica vs Dinamica

    Parametro Modalità Statica Modalità Dinamica
    Peso Bundle JS Cospicuo (racchiude l'ammontare totale comp) Minimizzato a favore delle sole logiche del base
    Inizializzazione Veloce Sostanzialmente subitanea Intervallato (Necessita download preventivo)
    Chiamate Rete 0 di contorno prelevanti 1 in base all'identità prescritta o richiesta
    Uso Tree-Shaking Esteso alla natura dei componenti Ad uso interamente localizzato a scopo
    Campi Preferenziali Dettagli di UI, Modelli basici Masse contenutistiche, Voluminose presenze testi