npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vite-plugin-formatjs

v1.1.3

Published

A Vite plugin that integrates FormatJS for message extraction, compilation, and build-time code transformation with hot reload support

Readme

vite-plugin-formatjs

A powerful Vite plugin that integrates FormatJS for automatic message extraction, compilation, and build-time optimization with hot reload support.

npm version License: MIT

✨ Features

  • 🔄 Automatic Message Extraction - Extract i18n messages from source code automatically
  • Hot Reload Support - Real-time message updates during development
  • 🎯 Multi-Framework Support - Works with React, Vue, TypeScript, JavaScript, and more
  • 🚀 Performance Optimized - Debounced processing and intelligent caching
  • 📦 Build Integration - Seamless integration with Vite build process
  • 🛠️ Flexible Configuration - Extensive customization options
  • 📊 Rich Logging - Detailed debug information and performance metrics
  • 🔧 TypeScript Support - Full TypeScript support with detailed type definitions

🚀 Quick Start

Installation

# npm
npm install -D vite-plugin-formatjs

# yarn
yarn add -D vite-plugin-formatjs

# pnpm
pnpm add -D vite-plugin-formatjs

Basic Setup

1. Configure the Plugin

Add the plugin to your vite.config.ts:

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { formatjs } from 'vite-plugin-formatjs';

export default defineConfig({
  plugins: [
    // Configure React with babel-plugin-formatjs for runtime optimization
    react({
      babel: {
        plugins: [
          [
            'formatjs',
            {
              idInterpolationPattern: '[sha512:contenthash:base64:6]',
              ast: true,
              removeDefaultMessage: process.env.NODE_ENV === 'production',
            },
          ],
        ],
      },
    }),

    // Configure vite-plugin-formatjs for build-time processing
    formatjs({
      extract: {
        include: ['src/**/*.{ts,tsx,js,jsx}'],
        outFile: 'src/i18n/lang/en.json',
        idInterpolationPattern: '[sha512:contenthash:base64:6]',
      },
      compile: {
        inputDir: 'src/i18n/lang',
        outputDir: 'src/i18n/compiled-lang',
      },
      debug: process.env.NODE_ENV === 'development',
    }),
  ],
});

2. Create Your i18n Setup

// src/i18n/index.ts
export const supportedLocales = ['en', 'zh', 'fr'] as const;
export type SupportedLocale = (typeof supportedLocales)[number];

export async function loadMessages(locale: string) {
  const normalizedLocale = supportedLocales.includes(locale as SupportedLocale)
    ? locale
    : 'en';

  try {
    const messages = await import(`./compiled-lang/${normalizedLocale}.json`);
    return messages.default || messages;
  } catch (error) {
    console.warn(`Failed to load messages for ${normalizedLocale}`, error);
    return {};
  }
}

3. Use in Your Components

// src/components/Welcome.tsx
import { FormattedMessage } from 'react-intl';

export function Welcome() {
  return (
    <div>
      <h1>
        <FormattedMessage
          id="welcome.title"
          defaultMessage="Welcome to our app!"
        />
      </h1>
      <p>
        <FormattedMessage
          id="welcome.description"
          defaultMessage="This message will be automatically extracted and compiled."
        />
      </p>
    </div>
  );
}

🔧 Configuration

Complete Configuration Example

import { formatjs } from 'vite-plugin-formatjs';

formatjs({
  // Message extraction configuration
  extract: {
    // Files to scan for messages
    include: [
      'src/**/*.{ts,tsx,js,jsx}',
      'components/**/*.vue',
      'pages/**/*.html',
    ],

    // Files to ignore
    ignore: ['node_modules/**', '**/*.test.*', '**/*.spec.*', 'dist/**'],

    // Output file for extracted messages
    outFile: 'src/i18n/lang/en.json',

    // Message ID generation pattern
    idInterpolationPattern: '[sha512:contenthash:base64:6]',

    // FormatJS extraction options
    additionalComponentNames: ['CustomFormattedMessage'],
    preserveWhitespace: true,
  },

  // Message compilation configuration
  compile: {
    inputDir: 'src/i18n/lang', // Source translation files
    outputDir: 'src/i18n/compiled-lang', // Compiled output directory
  },

  // Development options
  debug: process.env.NODE_ENV === 'development',
  autoExtract: true,
  debounceTime: 300,
  extractOnBuild: true,
});

Configuration Options

Extract Options

| Option | Type | Default | Description | | --------- | ---------- | --------------------------------------------------- | ---------------------------------- | | include | string[] | ['src/**/*.{ts,tsx,js,jsx,vue,hbs,gjs,gts}'] | File patterns to scan for messages | | ignore | string[] | ['node_modules/**', '**/*.test.*', '**/*.spec.*'] | File patterns to ignore | | outFile | string | 'src/i18n/lang/en.json' | Output file for extracted messages |

All options from @formatjs/cli-lib are also supported.

Compile Options

| Option | Type | Default | Description | | ----------- | -------- | -------------------------- | -------------------------------------- | | inputDir | string | 'src/i18n/lang' | Directory containing translation files | | outputDir | string | 'src/i18n/compiled-lang' | Output directory for compiled files |

All options from @formatjs/cli-lib are also supported.

Plugin Options

| Option | Type | Default | Description | | ---------------- | --------- | ------- | ------------------------------------------------------ | | debug | boolean | false | Enable detailed debug logging | | autoExtract | boolean | true | Automatically extract messages on file changes | | debounceTime | number | 300 | Debounce time in milliseconds for file change handling | | extractOnBuild | boolean | false | Extract messages at build start |

🔥 Hot Reload

The plugin provides seamless hot reload functionality during development:

  1. Source File Changes: When you modify source files containing messages, the plugin automatically:

    • Extracts new/modified messages
    • Updates the message files
    • Recompiles affected translations
    • Triggers Vite's HMR
  2. Translation File Changes: When you update translation files, the plugin:

    • Recompiles the specific file
    • Updates the compiled output
    • Triggers HMR for immediate preview
  3. Smart Debouncing: Multiple file changes are batched together to avoid excessive processing.

🏗️ Build Process

Development Mode (vite dev)

  1. Initial Setup: Extract and compile all messages on startup
  2. File Watching: Monitor source files for message changes
  3. Hot Updates: Real-time message extraction and compilation
  4. Debug Logging: Detailed information about processing (when debug: true)

Production Build (vite build)

  1. Final Extraction: Ensure all messages are extracted (if extractOnBuild: true)
  2. Compilation: Compile all translation files for optimal runtime performance
  3. Optimization: Remove debug information and optimize output

🧩 Framework Integration

React + React-Intl

// Complete setup with React
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { formatjs } from 'vite-plugin-formatjs';

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          [
            'formatjs',
            {
              idInterpolationPattern: '[sha512:contenthash:base64:6]',
              ast: true,
              removeDefaultMessage: process.env.NODE_ENV === 'production',
            },
          ],
        ],
      },
    }),
    formatjs({
      extract: {
        include: ['src/**/*.{ts,tsx}'],
        outFile: 'src/locales/en.json',
        idInterpolationPattern: '[sha512:contenthash:base64:6]',
      },
      compile: {
        inputDir: 'src/locales',
        outputDir: 'src/compiled-locales',
      },
    }),
  ],
});

Vue + Vue-i18n

import { formatjs } from 'vite-plugin-formatjs';

export default defineConfig({
  plugins: [
    vue(),
    formatjs({
      extract: {
        include: ['src/**/*.{vue,ts,js}'],
        outFile: 'src/locales/messages.json',
      },
      compile: {
        inputDir: 'src/locales',
        outputDir: 'src/compiled-locales',
      },
    }),
  ],
});

📊 Performance & Optimization

  • Debounced Processing: Batches multiple file changes to reduce unnecessary work
  • Incremental Updates: Only processes changed files during development
  • Parallel Compilation: Compiles multiple translation files concurrently
  • Smart Caching: Avoids reprocessing unchanged content
  • Memory Efficient: Optimized for large codebases

📁 Project Structure

src/
├── components/
│   └── *.tsx                    # Components with messages
├── i18n/
│   ├── index.ts                 # i18n setup and utilities
│   ├── lang/                    # Source translation files
│   │   ├── en.json             # Extracted messages (auto-generated)
│   │   ├── zh.json             # Chinese translations
│   │   └── fr.json             # French translations
│   └── compiled-lang/           # Compiled translation files (auto-generated)
│       ├── en.json
│       ├── zh.json
│       └── fr.json
└── ...

🔧 API Reference

formatjs(options?: UserFormatJSConfig)

Creates the Vite plugin with the specified configuration.

Parameters

  • options (optional): Configuration object of type UserFormatJSConfig

Returns

A Vite plugin object.

Configuration Types

UserFormatJSConfig

type UserFormatJSConfig = Partial<
  VitePluginFormatJSOptions & Partial<ExtractOptions> & Partial<CompileOptions>
>;

The main configuration type that users provide when using the plugin. All fields are optional, and the plugin will use sensible defaults for missing options.

VitePluginFormatJSOptions

interface VitePluginFormatJSOptions {
  extract: ExtractOptions; // Message extraction configuration
  compile: CompileOptions; // Message compilation configuration
  debug: boolean; // Enable debug logging (default: false)
  autoExtract: boolean; // Auto-extract on file changes (default: true)
  debounceTime: number; // Debounce time in ms (default: 300)
  extractOnBuild: boolean; // Extract on build start (default: false)
}

ExtractOptions

Extends ExtractCLIOptions from @formatjs/cli-lib with additional file matching configuration.

interface ExtractOptions extends ExtractCLIOptions {
  include: string[]; // File patterns to scan (required)
}

Key Properties:

  • include: Array of file matching patterns using minimatch syntax
  • outFile: Output file for extracted messages
  • idInterpolationPattern: Pattern for generating message IDs
  • All other options from @formatjs/cli-lib

CompileOptions

Extends CompileOpts from @formatjs/cli-lib with directory configuration.

interface CompileOptions extends CompileOpts {
  inputDir: string; // Input directory for translation files
  outputDir: string; // Output directory for compiled files
}

🤝 Integration with Babel Plugin

This plugin works seamlessly with babel-plugin-formatjs:

  • vite-plugin-formatjs: Handles build-time extraction and compilation
  • babel-plugin-formatjs: Handles runtime code optimization and transformation

Both plugins can use the same idInterpolationPattern to ensure consistency.

🐛 Debugging

Enable debug mode to get detailed information about the plugin's operation:

formatjs({
  debug: true, // or process.env.NODE_ENV === 'development'
  // ... other options
});

Debug output includes:

  • File processing information and timing
  • Message extraction results and statistics
  • Compilation status and performance metrics
  • Error details and stack traces

🔧 Advanced Configuration

Custom Message ID Generation

formatjs({
  extract: {
    // Generate short, stable IDs based on content
    idInterpolationPattern: '[sha512:contenthash:base64:6]',

    // Or use custom patterns
    idInterpolationPattern: '[contenthash:5]',
  },
});

Environment-Based Configuration

const isProduction = process.env.NODE_ENV === 'production';

formatjs({
  debug: !isProduction,
  extractOnBuild: isProduction,
  debounceTime: isProduction ? 100 : 300,
  extract: {
    // Production builds might want more aggressive extraction
    include: isProduction
      ? ['src/**/*.{ts,tsx,js,jsx,vue}']
      : ['src/**/*.{ts,tsx,js,jsx}'],
  },
});

📝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

📄 License

MIT © asfamilybank

🔗 Links