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 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-request-logger

v1.2.5

Published

A robust, Morgan-like HTTP request logger plugin for Vite supporting Vite 5, 6, 7, 8+ with body logging and TypeScript support.

Readme

vite-plugin-request-logger


👨‍💻 Created by Eyal Shapiro

npm version npm downloads license TypeScript Vite

A Morgan-like HTTP request logger plugin for Vite 5, 6, 7, 8+.

Intercepts requests inside the Vite dev-server middleware chain and prints each API call — method, URL, status code, response time, request body, and headers — directly in your terminal. Zero dependencies. Zero config needed to start.

[00:12:34] POST   /api/users 201 +14.23ms
  Body: {
    "name": "Eyal",
    "password": "[REDACTED]"
  }

Features

  • 🚀 Vite 5, 6, 7, 8+ — tested across all major versions
  • 🎨 Colored terminal output — method, status, and timing, color-coded at a glance
  • 📦 Request body logging — pretty-prints JSON bodies for POST / PUT / PATCH / DELETE
  • 🛡️ Automatic redaction — sensitive keys (password, token, secret, …) replaced with [REDACTED]
  • 🧹 Prefix filtering — only log requests under a given path (e.g. /api), ignoring all Vite internals
  • 📁 File logging — optionally append plain-text logs to a file (ANSI codes stripped automatically)
  • 🔒 Fail-safe — errors inside the plugin never crash your dev server
  • 🦾 Full TypeScript — complete types and IntelliSense for all options
  • 🧩 Standalone middleware — use createRequestLoggerMiddleware in Express, Fastify, or any Node.js server
  • 🌐 Browser console — auto-injects a client-side interceptor for fetch & XHR visibility
  • 💻 Vite CLI binary — zero-config instant dev server logging (npx vprl / npx vite-plugin-request-logger)

Installation

View on npm

npm https://www.npmjs.com/package/vite-plugin-request-logger

npm install -D vite-plugin-request-logger

View on npmx

pnpm https://npmx.dev/package/vite-plugin-request-logger

pnpm add -D vite-plugin-request-logger

View on Yarn

yarn https://yarnpkg.com/package?q=vite-plugin-request-logger&name=vite-plugin-request-logger

yarn add -D vite-plugin-request-logger

View on npm

# bun
bun add -D vite-plugin-request-logger

Quick Start

// vite.config.ts
import { defineConfig } from 'vite';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig({
  plugins: [
    viteRequestLogger(), // defaults: prefix '/api', format 'dev', logBody true
  ],
});

That's it. All requests to /api/* will be logged in your terminal automatically.


💻 Vite CLI Usage

Launch Vite without editing any config files using the built-in vprl / vite-plugin-request-logger binary:

# Start Vite dev server with request logging (default port: 5173)
npx vprl dev
npx vprl serve    # alias for dev

# Start the Vite preview server with request logging (default port: 4173)
npx vprl preview

# Run a Vite build (plugin active during build transforms)
npx vprl build

# Print usage help
npx vprl --help
npx vprl help

The CLI automatically enables logBody: true and format: 'dev'. No vite.config.ts changes required.

Install globally for convenience

npm install -g vite-plugin-request-logger
# Then just:
vprl dev
vprl preview

Integrate with existing package.json scripts

{
  "scripts": {
    "dev": "vprl dev",
    "preview": "vprl preview"
  }
}

Configuration

viteRequestLogger({
  prefix: '/api', // Only log URLs that start with this path
  format: 'dev', // 'dev' | 'tiny' | 'short' | 'combined'
  logBody: true, // Log request body (POST / PUT / PATCH / DELETE)
  maxBodyLength: 1000, // Truncate body output at N characters
  logHeaders: false, // Log all request headers
  redactKeys: ['password', 'token', 'secret'], // Redact sensitive fields
  logToFile: 'logs/dev.log', // Also write logs to a file (optional)
  colors: true, // ANSI colors in terminal
  timezone: 'he-IL', // Locale for timestamps (BCP 47)
  silentOnError: true, // Never crash the dev server on plugin error
});

Options Reference

| Option | Type | Default | Description | | :-------------- | :----------------------------------------- | :------------------------------ | :-------------------------------------------------------------------------------------- | | prefix | string | '/api' | Only log requests whose URL starts with this prefix. Use '/' for all. | | filter | (req) => boolean | undefined | Custom filter function (overrides prefix when provided). | | customMsg | (req, res, responseTimeMs) => string | undefined | Callback returning a custom suffix string to append to log lines. | | logger | CustomLogger \| 'console' \| 'silent' | 'console' | Custom logger instance (e.g. Pino, Winston) or preset ('silent'). | | format | 'dev' \| 'tiny' \| 'short' \| 'combined' | 'dev' | Log line format preset. | | logBody | boolean | true | Log request body for POST / PUT / PATCH / DELETE. | | maxBodyLength | number | 1000 | Max characters of body to display before truncating. | | logHeaders | boolean | false | Include all request headers in log output. | | redactKeys | string[] | ['password','token','secret'] | Keys replaced with [REDACTED] in bodies & headers (case-insensitive). | | logToFile | string | undefined | Path to append plain-text logs (e.g. 'logs/requests.log'). | | colors | boolean | true | Enable ANSI colors in terminal output. | | timezone | string \| ((d: Date) => string) | 'he-IL' | BCP 47 locale for timestamp formatting (e.g. 'en-US') or a custom formatter function. | | ignorePaths | (string \| RegExp)[] | undefined | Paths or patterns to exclude from logging (e.g. ['/health', /^\/assets\//]). | | skipAssets | boolean | false | Skip logging of static asset requests (.js, .css, images, fonts, …). | | silentOnError | boolean | true | Silently catch internal plugin errors to prevent dev server crashes. |


Log Formats

| Format | Example output | | :--------- | :------------------------------------------------- | | dev | [12:00:00] POST /api/users 201 +12.34ms | | tiny | POST /api/users 201 - 12.34 ms | | short | POST /api/users 201 12.34 ms | | combined | POST /api/users 201 12.34 ms (alias for short) |


Examples

Zero config (log only /api)

viteRequestLogger();

Log all requests (including Vite HMR and assets)

viteRequestLogger({ prefix: '/' });

Redact additional sensitive fields

viteRequestLogger({
  redactKeys: ['password', 'token', 'secret', 'apiKey', 'authorization', 'ssn'],
});

Persist logs to a file

viteRequestLogger({
  logToFile: 'logs/dev-requests.log',
  colors: true, // colors in terminal; ANSI codes stripped automatically in the file
});

Minimal terminal output

viteRequestLogger({
  format: 'tiny',
  logBody: false,
  logHeaders: false,
});

Disable colors (CI / piped output)

viteRequestLogger({ colors: false });

Full configuration example

// vite.config.ts
import { defineConfig } from 'vite';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig({
  plugins: [
    viteRequestLogger({
      prefix: '/api',
      format: 'dev',
      logBody: true,
      maxBodyLength: 2000,
      logHeaders: true,
      redactKeys: ['password', 'token', 'secret', 'authorization'],
      logToFile: 'logs/requests.log',
      colors: true,
      timezone: 'en-US',
      silentOnError: true,
    }),
  ],
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
      },
    },
  },
});

With Vite proxy to a real backend

The plugin logs the request before it's forwarded — so you see the exact URL, body, and timing for every proxied call.

// vite.config.ts
import { defineConfig } from 'vite';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig({
  plugins: [viteRequestLogger({ prefix: '/api' })],
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:4000', // your Express / Fastify / NestJS server
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },
});

With React (Vite + @vitejs/plugin-react)

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

export default defineConfig({
  plugins: [
    react(),
    viteRequestLogger({
      prefix: '/api',
      format: 'dev',
      logBody: true,
    }),
  ],
});

With Vue (Vite + @vitejs/plugin-vue)

// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig({
  plugins: [
    vue(),
    viteRequestLogger({
      prefix: '/api',
      format: 'tiny', // minimal output for Vue projects
    }),
  ],
});

With tRPC (log /trpc prefix)

// vite.config.ts
import { defineConfig } from 'vite';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig({
  plugins: [
    viteRequestLogger({
      prefix: '/trpc', // log all tRPC procedure calls
      format: 'dev',
      logBody: true,
    }),
  ],
});

Custom filtering (multiple prefixes or regex)

You can pass a custom filter function to log requests matching multiple endpoints, regexes, or exclude specific routes:

viteRequestLogger({
  filter: (req) =>
    req.url?.startsWith('/api') ||
    req.url?.startsWith('/trpc') ||
    (req.url?.includes('/graphql') ?? false),
});

Custom message suffix (customMsg)

Annotate log lines with custom labels (e.g. tagging slow requests or environment headers):

viteRequestLogger({
  customMsg: (req, res, responseTimeMs) => (responseTimeMs > 500 ? '⚠️ SLOW' : undefined),
});

Custom Logger (Pino / Winston / Silent)

Pass any external logger instance (e.g. Pino, Winston) or the 'silent' preset directly:

With Pino

import pino from 'pino';
import viteRequestLogger from 'vite-plugin-request-logger';

const pinoLogger = pino();

export default defineConfig({
  plugins: [
    viteRequestLogger({
      logger: pinoLogger,
    }),
  ],
});

With Winston

import winston from 'winston';
import viteRequestLogger from 'vite-plugin-request-logger';

const winstonLogger = winston.createLogger({
  transports: [new winston.transports.Console()],
});

export default defineConfig({
  plugins: [
    viteRequestLogger({
      logger: winstonLogger,
    }),
  ],
});

Silent Mode (suppress all console output)

viteRequestLogger({
  logger: 'silent',
});

Multiple prefixes (alternative)

You can also instantiate the plugin twice with different prefixes:

// vite.config.ts
import { defineConfig } from 'vite';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig({
  plugins: [
    viteRequestLogger({ prefix: '/api', format: 'dev' }),
    viteRequestLogger({ prefix: '/trpc', format: 'tiny' }),
  ],
});

Environment-based configuration

Enable verbose logging only in local dev; keep it minimal in staging:

// vite.config.ts
import { defineConfig } from 'vite';
import viteRequestLogger from 'vite-plugin-request-logger';

export default defineConfig(({ mode }) => ({
  plugins: [
    viteRequestLogger({
      prefix: '/api',
      format: mode === 'development' ? 'dev' : 'tiny',
      logBody: mode === 'development',
      logHeaders: mode === 'development',
      colors: mode === 'development',
      // write logs to file only in staging
      logToFile: mode === 'staging' ? 'logs/requests.log' : undefined,
    }),
  ],
}));

Write logs to file without showing them in the terminal

viteRequestLogger({
  logToFile: 'logs/requests.log',
  colors: false,
  logger: 'silent', // suppress terminal output entirely
});

Tip: The log file is always plain text (ANSI codes stripped automatically), so it's safe to tail -f logs/requests.log or ship to any log aggregator.

Skip health-check and asset routes

viteRequestLogger({
  ignorePaths: ['/health', '/ping', /^\/metrics/],
  skipAssets: true,
});

Standalone middleware (Express / Fastify / pure Node.js)

Use createRequestLoggerMiddleware independently of Vite — perfect for production servers or any Connect-compatible framework:

import express from 'express';
import { createRequestLoggerMiddleware } from 'vite-plugin-request-logger';

const app = express();
app.use(
  createRequestLoggerMiddleware({
    prefix: '/api',
    format: 'dev',
    logBody: true,
    redactKeys: ['password', 'token'],
  }),
);

Or with a pure node:http server:

import http from 'node:http';
import { createRequestLoggerMiddleware } from 'vite-plugin-request-logger';

const logger = createRequestLoggerMiddleware({ prefix: '/api' });

const server = http.createServer((req, res) => {
  logger(req, res, () => {
    // your handler
    res.end('Hello');
  });
});
server.listen(3000);

🌐 Browser Telemetry & Privacy (@vprl/client)

@vprl/client is a lightweight, privacy-first browser telemetry client that captures user interactions (clicks, form inputs, uncaught errors) and sends them in efficient batches to your server with built-in PII redaction and resilience.

Basic Usage

import { VPRLClient } from 'vite-plugin-request-logger/client';

const client = new VPRLClient({
  endpoint: '/api/telemetry',
});

Configurable Sensitive Input Types & PII Masking

By default, @vprl/client automatically redacts sensitive input types ('password', 'email', 'tel', 'card') as [REDACTED]. You can configure custom sensitive input types (such as ssn, pin, credit-card, etc.) or supply custom sanitizers:

import { VPRLClient, DEFAULT_SENSITIVE_INPUT_TYPES } from 'vite-plugin-request-logger/client';

const client = new VPRLClient({
  endpoint: '/api/telemetry',
  batchSize: 10,
  flushInterval: 2000,

  // When false, non-sensitive inputs (like text) pass through while sensitive types are redacted
  maskInputValues: false,

  // Add extra sensitive input types on top of 'password', 'email', 'tel', 'card'
  additionalSensitiveInputTypes: ['ssn', 'pin', 'credit-card', 'search'],

  // Or completely override the sensitive types list:
  // sensitiveInputTypes: ['password', 'ssn', 'pin'],

  // Redact elements matching CSS selectors
  maskSelectors: ['.sensitive', '[data-vprl-mask]', '#bank-account'],

  // Custom sanitizer override (optional)
  customSanitizer: (element, value) => {
    if (element.hasAttribute('data-allow-plain')) return value;
    return value.replace(/\d{4}/g, '****');
  },

  // Lifecycle hooks
  beforeSend: (event) => {
    // Return modified event, or null to drop
    return event;
  },
  onFlushSuccess: (events) => {
    console.log(`Delivered ${events.length} telemetry events`);
  },
});

@vprl/client Configuration Options

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | endpoint | string | (Required) | The server endpoint URL where batched telemetry is POSTed. | | batchSize | number | 10 | Max events per batch POST. Triggers immediate flush when reached. | | flushInterval | number | 2000 | Interval in ms for periodic automatic flushes. | | maxQueueSize | number | 100 | Max in-memory queue size before dropping oldest events (FIFO). | | maskInputValues | boolean | true | When true, masks all input fields. When false, masks only sensitive types. | | sensitiveInputTypes | string[] | ['password', 'email', 'tel', 'card'] | Overrides the list of input types that are always redacted. | | additionalSensitiveInputTypes | string[] | [] | Appends extra input types to be redacted alongside defaults. | | maskSelectors | string[] | ['.sensitive', '[data-vprl-mask]'] | CSS selectors for elements whose content is always redacted. | | customSanitizer | (element, value) => string | undefined | Custom function to sanitize/redact values before queueing. | | enableClickTracking | boolean | true | Automatic click tracking with smart element bubbling. | | enableInputTracking | boolean | true | Automatic input/change tracking on form fields. | | enableErrorTracking | boolean | true | Automatic uncaught error tracking (window.onerror). | | beforeSend | (event) => VPRLEvent \| null | undefined | Hook to transform or filter events before queueing. | | onFlushSuccess | (events) => void | undefined | Hook called after a batch is successfully delivered. | | onFlushError | (error, events) => void | undefined | Hook called when a batch delivery fails. | | customHeaders | Record<string, string> \| (() => ...) | undefined | Additional HTTP headers sent with each flush. | | maxFailures | number | 5 | Failures before opening the circuit breaker. | | cooldownPeriod | number | 30000 | Circuit breaker recovery cooldown in ms. |


How It Works

The plugin registers a middleware in Vite's dev server using configureServer. It patches res.end to capture the status code and response time at the exact moment the response is sent — giving accurate timing that includes proxy round-trips.

Request filtering: Only URLs that start with prefix (default: /api) are logged. Vite's own HMR, source-file, and asset requests are always ignored without any extra configuration.

Body capture: For mutating methods (POST, PUT, PATCH, DELETE), request body chunks are collected via req.on('data', …) before res.end fires. The body is then pretty-printed (if JSON) and redacted before logging.

File logging: Logs are written to disk asynchronously (non-blocking) using fs/promises. ANSI color codes are stripped before writing so the file contains clean plain text.


Runnable Examples

Standalone examples are bundled under example/:

| Example | Port | Description | | :---------------------------------------------------- | :--- | :---------------------------------------------------------------------- | | react-query-axios | 5180 | React 19 + @tanstack/react-query + Axios Instance | | solid-ts | 5181 | SolidJS + TypeScript (solid-ts) signal logging | | client-interceptor | 5173 | Dedicated browser fetch & XHR interceptor demo | | advanced | 3001 | All plugin options · Vite 5 · mock API · file logging | | custom-features | 3002 | Custom filter, Vite logger bridge, client telemetry & PII redaction demo | | vite-node-server | 3003 | Pure Node.js API embedded in Vite — no Express | | react-example | 3000 | React + Vite + axios | | express-standalone | 4000 | Standalone Express server (no Vite) | | nextjs-ssr | 3005 | Next.js 14 App Router — SSR custom server + Edge middleware | | nginx-proxy | 8080 | Nginx Reverse Proxy — $request_id distributed tracing with Docker |

example/react-query-axios — React Query + Axios Instance

Demonstrates capturing requests sent via a custom Axios Instance (axios.create(...)) integrated with TanStack React Query (useQuery, useMutation).

cd example/react-query-axios
npm install
npm run dev
# Open http://localhost:5180

example/solid-ts — Solid-TS Example

Demonstrates fine-grained SolidJS signals and createResource fetching data logged seamlessly by vite-plugin-request-logger.

cd example/solid-ts
npm install
npm run dev
# Open http://localhost:5181

example/advanced — All options · Vite 5

Demonstrates every plugin option with an interactive browser UI. Uses Vite 5 for maximum compatibility with older projects.

cd example/advanced
npm install
npm run dev
# Open http://localhost:3001

Features demonstrated: all HTTP methods, body logging, header logging, automatic redaction, file logging, prefix filtering.

example/custom-features — Filter, Custom Message & Custom Logger

Demonstrates custom filter functions, customMsg status annotations, and external logger instances (Pino/Winston/Silent).

cd example/custom-features
npm install
npm run dev
# Open http://localhost:3002

example/vite-node-server — Pure Node.js inside Vite · No Express

Shows how to embed a complete CRUD API using only node:http primitives inside the Vite middleware chain via configureServer. Zero extra runtime dependencies.

cd example/vite-node-server
npm install
npm run dev
# Open http://localhost:3003

example/react-example — React + Vite

React 19 app using axios for HTTP calls. The plugin logs every request in the terminal and the client-side interceptor mirrors them in the browser console.

cd example/react-example
npm install
npm run dev
# Open http://localhost:3000

example/express-standalone — Express Standalone

Uses createRequestLoggerMiddleware directly in an Express server — no Vite needed. Useful for production or preview servers.

cd example/express-standalone
npm install
npm start
# Server on http://localhost:4000

Run any example from the project root:

npm run example:react-query # port 5180
npm run example:solid       # port 5181
npm run example:advanced    # port 3001
npm run example:custom      # port 3002
npm run example:vite-node   # port 3003
npm run example:react       # port 3000
npm run example:express     # port 4000

Automated Publishing & Release

Releases are published automatically to npm via GitHub Actions when a new GitHub Release is created.


Development & Contributing

# Install dependencies
npm install

# Build the library (watch mode)
npm run dev

# Run tests
npm test

# Type-check only (no emit)
npm run typecheck

# Lint
npm run lint

# Auto-fix formatting
npm run format:fix

Source code and issue tracker: github.com/EyalShapiro/vite-plugin-request-logger


License

MIT © Eyal Shapiro