Skip to content

🚀 Performance Guide

📖 Introduction

Nuxt I18n Micro is designed with performance in mind, offering a significant improvement over traditional internationalization (i18n) modules like nuxt-i18n. This guide provides an in-depth look at the performance benefits of using Nuxt I18n Micro, and how it compares to other solutions.

🤔 Why Focus on Performance?

In large-scale projects and high-traffic environments, performance bottlenecks can lead to slow build times, increased memory usage, and poor server response times. These issues become more pronounced with complex i18n setups involving large translation files. Nuxt I18n Micro was built to address these challenges head-on by optimizing for speed, memory efficiency, and minimal impact on your application's bundle size.

📊 Performance Comparison

We conducted a series of tests to demonstrate the performance improvements that Nuxt I18n Micro brings to the table. Below is a detailed comparison between Nuxt I18n Micro and the traditional nuxt-i18n module, based on identical conditions with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n v10
  • Code Bundle: 19.24 MB
  • Translations: 38.05 MB (compiled into JS)
  • Max CPU Usage: 419%
  • Max Memory Usage: 9,117 MB
  • Elapsed Time: 82.26s

Nuxt I18n Micro

  • Code Bundle: 1.48 MB — 92% smaller than i18n v10
  • Translations: 55.76 MB (lazy-loaded JSON)
  • Max CPU Usage: 243% — 42% lower than i18n v10
  • Max Memory Usage: 1,175 MB — 87% less memory than i18n v10
  • Elapsed Time: 14.95s — 82% faster than i18n v10

See the full benchmark report for charts, Autocannon results, and fixture details.

🌐 Server Performance Under Load

We also tested server performance using Artillery and Autocannon stress tests.

Nuxt I18n v10
  • Requests per Second (Artillery): 51 [#/sec]
  • Average Response Time: 1,363 ms
  • Max Memory Usage: 1,243 MB

Nuxt I18n Micro

  • Requests per Second (Artillery): 278 [#/sec] — 445% more requests per second than i18n v10
  • Average Response Time: 437 ms — 63% faster than i18n v10
  • Max Memory Usage: 275 MB — 75% less memory usage than i18n v10

📈 Visual Comparison

Loading chart...
Loading chart...
Metricnuxt-i18n v10i18n-microImprovement
Build Time82.26s14.95s82% faster
Memory (build)9,117 MB1,175 MB87% less
Code Bundle19.24 MB1.48 MB92% smaller
CPU Usage419%243%42% lower
Response Time1,177 ms437 ms63% faster
RPS (Artillery)51278445% more

🔍 Interpretation of Results

These tests clearly indicate that Nuxt I18n Micro offers superior performance across multiple metrics:

  • 🗜️ Smaller Code Bundle: The code bundle is only 1.48 MB (vs 19.24 MB for i18n v10) — translations are stored as lazy-loaded JSON files.
  • 🔋 Lower CPU Usage: 42% lower CPU usage during build (243% vs 419%), allowing for more efficient CI/CD pipelines.
  • 🧠 Reduced Memory Consumption: Uses 87% less memory during build (1.2 GB vs 9.1 GB), making it feasible for resource-constrained environments.
  • 🕒 Faster Build Times: 82% faster builds (14.95s vs 82.26s), beneficial for development iteration speed.
  • Better Runtime Performance: 63% faster response times (437 ms vs 1,177 ms) and 445% more requests per second under load.

⚙️ Key Optimizations

🛠️ Minimalist Design

Nuxt I18n Micro is built around a minimalist architecture with a small core and dedicated strategy packages. This reduces overhead and simplifies the internal logic, leading to improved performance.

🚦 Efficient Routing

In v3, route generation and runtime path logic are split into dedicated packages for optimal tree-shaking:

  • @i18n-micro/route-strategy — Build-time route generation: extends Nuxt pages with localized routes. Only the selected strategy (no_prefix, prefix, prefix_except_default, prefix_and_default) is included.
  • @i18n-micro/path-strategy — Runtime path resolution, redirects, and link generation. Uses pure functions and pre-computed context flags to minimize allocations on hot paths. Subpath exports (/prefix, /no-prefix, etc.) ensure only the chosen implementation is bundled.

This approach keeps the routing configuration lightweight and ensures fast route resolution regardless of the number of locales.

📂 Streamlined Translation Loading

The module supports only JSON files for translations, with a clear separation between global and page-specific files. This ensures that only the necessary translation data is loaded at any given time, further enhancing performance.

🔒 GlobalThis Singleton Cache

Starting from v3.0.0, the module uses a globalThis singleton pattern with Symbol.for to guarantee a single cache instance across the entire Node.js process. This prevents:

  • Cache duplication when the same module is bundled multiple times
  • Per-request object recreation that causes garbage collection pressure
  • Memory leaks from orphaned cache instances
typescript
// Internal implementation pattern
const CACHE_KEY = Symbol.for('__NUXT_I18N_STORAGE_CACHE__')
if (!globalThis[CACHE_KEY]) {
  globalThis[CACHE_KEY] = new Map()
}

⚡ Optimized Translation Function (tFast)

The $t() function uses a direct lookup strategy optimized for speed:

  1. Pre-computed context: Locale and route name are calculated once during navigation, not on every $t() call
  2. Single-source lookup: All translations (root + page-specific + fallback) are pre-merged at build time into a single file per page — no layered search needed
  3. Cumulative deep merge on navigation: When navigating within the same locale, new page translations are deep-merged (2-level depth) into the active dictionary, so keys from the previous page remain visible during transition animations — even when pages share overlapping nested prefixes (e.g., both pages have keys under common.*)
  4. Garbage collection via page:transition:finish: After the transition animation is fully complete, the merged dictionary is replaced with the clean translations for the new page only, freeing memory from old-page keys
  5. Direct property access: Uses obj[key] instead of Map lookups for hot paths
typescript
// Simplified lookup logic — single active dictionary
let val = cachedTranslations[key]
if (val === undefined && key.includes('.')) {
  val = getByPath(cachedTranslations, key)
}

💉 Server-Side Payload Transfer

During SSR, loaded translation chunks are stored in useState('i18n-ssr-chunks') and serialized through the Nuxt payload. On the client, 01.plugin.ts calls translationStorage.seedFromSsrChunks() before any $fetch, completely avoiding duplicate requests on first load.

NuxtI18n maintains the active merged dictionary (cachedTranslations) used by $t() and $has(). Same-locale navigations deep-merge page chunks until page:transition:finish cleans up stale keys.

This approach:

  • Eliminates waterfall requests on page load
  • Reduces Time to Interactive (TTI)
  • Works seamlessly with pre-rendering and SSG

💾 Caching and Pre-rendering

To optimize performance, Nuxt I18n Micro implements caching and supports pre-rendering of translation files:

  • 🗄️ Caching: Translations are cached after the initial load, reducing the need for subsequent requests and improving response times.
  • 🏁 Pre-rendering: During the build process, translation files for all configured locales and routes can be pre-rendered. This eliminates the need for runtime requests, ensuring that translations are served quickly and efficiently.

☁️ Serverless Payload Output

By default, pre-merged translation payloads are emitted in multiple places so SSR, static generation, and local data routes work without extra setup. Large applications with many locales and page-level payloads may want tighter control, especially on serverless platforms where every Nitro server asset increases the Worker bundle.

Use translationPayloads.mode: 'source' for compact serverless deployments:

typescript
export default defineNuxtConfig({
  i18n: {
    translationPayloads: {
      mode: 'source',
    },
  },
})

mode: 'source' keeps layer-merged source files in Nitro server assets and merges root/page/fallback translations at runtime through the built-in /_locales route. By default it disables public asset copies and prerendered payload routes, which is usually what you want on Cloudflare Workers.

Static hosting / pure SSG

With mode: 'source', publicAssets and prerenderRoutes default to false. Pure static hosting without a Nitro/edge runtime therefore cannot load translations on the client unless you enable one of these outputs, keep serverHandler available at runtime, or host payloads externally.

External CDN hosts

When apiBaseServerHost or apiBaseClientHost is set, the module fetches already merged JSON from that origin. External hosts must serve the same /{apiBaseUrl}/:page/:locale/data.json responses as the built-in route. mode: 'source' applies only to locally bundled Nitro assets, not to an external CDN unless that CDN also serves runtime-merged payloads.

Or disable individual outputs manually and host payloads externally:

typescript
export default defineNuxtConfig({
  i18n: {
    apiBaseClientHost: 'https://cdn.example.com',
    apiBaseServerHost: 'https://cdn.example.com',
    translationPayloads: {
      serverAssets: false,
      serverHandler: false,
      publicAssets: false,
      prerenderRoutes: false,
    },
  },
})

Keep serverAssets and serverHandler enabled when you rely on the built-in local /{apiBaseUrl}/:page/:locale/data.json route. Disable them when payloads are hosted externally and apiBaseServerHost points at that external origin. Disable prerenderRoutes when you do not want Nitro to materialize /{apiBaseUrl}/.../data.json files such as /_locales/index/en/data.json into public output.

During build, the module warns when generated payload output exceeds translationPayloads.warnFileCount (default 500) or translationPayloads.warnSizeBytes (default 10 MB). It also warns when all local outputs are disabled without external payload hosts configured.

📝 Tips for Maximizing Performance

Here are a few tips to ensure you get the best performance out of Nuxt I18n Micro:

  • 📉 Limit Locale Data: Only include the locales you need in your project to keep the bundle size small.
  • 🗂️ Use Page-Specific Translations: Organize your translation files by page to avoid loading unnecessary data.
  • 💾 Enable Caching: Make use of the caching features to reduce server load and improve response times.
  • 🏁 Leverage Pre-rendering: Pre-render your translations to speed up page loads and reduce runtime overhead.

For detailed results of the performance tests, please refer to the Performance Test Results.

Released under the MIT License.