---
title: "Vite Plugin"
description: "Build-time optimizations for any Vite-based framework. Auto-init, debug stripping, source location injection, and optional auto-imports."
canonical_url: "https://www.evlog.dev/reference/vite-plugin"
---
# Vite Plugin

> Build-time optimizations for any Vite-based framework. Auto-init, debug stripping, source location injection, and optional auto-imports.

The `evlog/vite` plugin adds build-time DX features to any Vite-based project. It works with SvelteKit, Hono, Express, Fastify, Elysia, and any framework using Vite as its build tool.

<callout color="info" icon="i-lucide-info">

**Nuxt users**: These features are already integrated into the `evlog/nuxt` module via `strip` and `sourceLocation` options. You don't need to install the Vite plugin separately.

</callout>

## Quick Start

### 1. Install

<code-group>

```bash [pnpm]
pnpm add evlog
```

```bash [bun]
bun add evlog
```

```bash [yarn]
yarn add evlog
```

```bash [npm]
npm install evlog
```

</code-group>

### 2. Add to `vite.config.ts`

```typescript [vite.config.ts]
import { defineConfig } from 'vite'
import evlog from 'evlog/vite'

export default defineConfig({
  plugins: [
    evlog({
      service: 'my-api',
      environment: 'production',
    }),
  ],
})
```

That's it. The plugin automatically:

- Initializes the logger at compile time (no `initLogger()` call needed)
- Strips `log.debug()` calls from production builds

## Features

<vite-strip-build>



</vite-strip-build>

The plugin transforms your source at build time: `log.debug()` calls are deleted from the output, `__source: 'file:line'` is injected into object-form log calls, and `initLogger()` is wired in via Vite's `define` hook so you never have to call it yourself.

### Auto-initialization

The plugin injects logger configuration at compile time via Vite's `define` hook. The `service`, `environment`, `pretty`, `silent`, `enabled`, and `sampling` options are serialized and injected at build time, so `log`, `createLogger()`, and `createRequestLogger()` work immediately without an `initLogger()` call. When an `evlog.config.ts` exists, these settings can come from the file too, see the `evlog.config.ts` section below.

### Debug stripping

By default, all `log.debug()` calls are removed from production builds. This is a compile-time transformation, the calls are completely eliminated from the output, not just silenced.

```typescript [vite.config.ts]
evlog({
  service: 'my-api',
  // Default: strip debug logs in production builds
  // strip: ['debug'],

  // Strip debug and info in production:
  // strip: ['debug', 'info'],

  // Disable stripping:
  // strip: [],
})
```

Stripping only activates during `vite build` (not `vite dev`).

### Source location injection

When enabled, the plugin injects `__source: 'file:line'` into object-form log calls so you know exactly which file and line produced each log entry.

```typescript [vite.config.ts]
evlog({
  service: 'my-api',
  sourceLocation: true,      // Always inject
  // sourceLocation: 'dev',  // Only in development
})
```

### Auto-imports (opt-in)

Automatically detect and import evlog symbols (`log`, `createEvlogError`, `parseError`, etc.) without manual import statements. Disabled by default.

```typescript [vite.config.ts]
evlog({
  service: 'my-api',
  autoImports: true,
})
```

When enabled, the plugin:

1. Scans your code for evlog symbols
2. Adds the correct `import` statements automatically
3. Generates a `.d.ts` file for TypeScript support

<callout color="amber" icon="i-lucide-triangle-alert">

The auto-imported error constructor is `createEvlogError`, not `createError`. This avoids conflicts with framework-native `createError` (Nuxt, Nitro, h3). The standalone `createError` from `evlog` is still available via explicit import.

</callout>

### Client-side injection

When the `client` option is provided, the plugin injects a `<script>` tag into HTML pages that initializes the client-side logger. This enables `log.info()`, `log.error()`, etc. in browser code.

```typescript [vite.config.ts]
evlog({
  service: 'my-api',
  client: {
    console: false,
    transport: {
      enabled: true,
      endpoint: '/api/_evlog/ingest',
    },
  },
})
```

## evlog.config.ts

The plugin reads `evlog.config.ts` from the Vite root, the same file the CLI, Nuxt and Nitro read. It looks for `evlog.config.ts`, `.mts`, `.js` and `.mjs`, in the Vite root first, then in each parent directory up to the workspace root. The nearest file wins.

```typescript [evlog.config.ts]
import { defineEvlog } from 'evlog'

export default defineEvlog({
  service: 'my-api',
  pretty: false,
  sampling: { rates: { info: 10 }, keep: [{ status: 400 }] },
})
```

The file is the base and the plugin options override it, key by key. Plugin options win on `service`, `environment`, `enabled`, `pretty`, `silent`, `minLevel`, `stringify`, and on the keys of `sampling`. The `sampling.keep` rules from both sides are kept. Any other file key is left alone.

```typescript [vite.config.ts]
evlog({
  environment: 'production', // the file keeps its service and pretty settings
})
```

Only these settings are read from the file: `service`, `environment`, `enabled`, `pretty`, `silent`, `sampling`, `minLevel` and `stringify`. The functions in the file (`drain`, `enrich`, `keep` and `plugins`) are not injected by the plugin, so they do not run in the build. A file with a syntax or import error fails the build with its path in the message. Without a file, the plugin behaves as it did before.

## Configuration

<table>
<thead>
  <tr>
    <th>
      Option
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        service
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'app'
      </code>
    </td>
    
    <td>
      Service name in logs
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        environment
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Auto-detected
    </td>
    
    <td>
      Environment name
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pretty
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
      
       in dev
    </td>
    
    <td>
      Pretty print logs
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        silent
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Suppress console output
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        enabled
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Enable/disable all logging
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        strip
      </code>
    </td>
    
    <td>
      <code>
        LogLevel[]
      </code>
    </td>
    
    <td>
      <code>
        ['debug']
      </code>
    </td>
    
    <td>
      Log levels to remove from production builds. <code>
        trace
      </code>
      
       is not stripped by default; add it to the list if you opt into it
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sourceLocation
      </code>
    </td>
    
    <td>
      <code>
        boolean | 'dev'
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Inject source file:line into log calls
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        autoImports
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Auto-import evlog symbols
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        client
      </code>
    </td>
    
    <td>
      <code>
        object
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      Client-side injection config (<code>
        console
      </code>
      
      , <code>
        transport
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sampling
      </code>
    </td>
    
    <td>
      <code>
        object
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      Head/tail sampling rates
    </td>
  </tr>
</tbody>
</table>

## Nuxt Integration

The Nuxt module exposes `strip` and `sourceLocation` directly in `nuxt.config.ts`:

```typescript [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['evlog/nuxt'],
  evlog: {
    env: { service: 'my-app' },
    strip: ['debug'],           // Default
    sourceLocation: 'dev',      // Inject in dev only
  },
})
```

## Vite Compatibility

The plugin supports **Vite 7+** and is optimized for **Vite 8** (Rolldown). On Vite 8, transform hooks use Rolldown-native `filter` and `moduleType` for maximum performance, non-matching files are skipped entirely on the Rust side without crossing the JS bridge.

---

- [Source Code](https://github.com/evloghq/evlog/tree/main/packages/evlog/src/vite)


## Sitemap

See the full [sitemap](https://www.evlog.dev/sitemap.md) for all pages.
