Developer Server Access Log Option
Description
As a developer it can be very useful to see the "hits", access requests in the vite console.
Suggested solution
When running vite --access-logs vite should log each hit as is typical with web servers (like apache/nginx) or web frameworks (like flask):
Alternative
No response
Additional context
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
You can do it like this. https://x.com/kiliman/status/1719488313692766582
You can do it like this. https://x.com/kiliman/status/1719488313692766582
Bad link. Does any know what the workaround is and can post it here?
You can add in plugin
{
name: 'requestLogger',
configureServer(server) {
server.middlewares.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
},
},
Added requestLogger Plugin: A custom plugin named requestLogger is added to the plugins array. This plugin uses the configureServer method to add a middleware that logs the request method and URL.
Console Log for Requests: Logs requests to the terminal in the format: "[timestamp] METHOD URL".
Result: When you run the Vite dev server, it will now log all incoming HTTP requests to the console. This helps in debugging and monitoring access during development.
@YogSottot thanks! Worth noting that for preview mode one also needs to add configurePreviewServer.
My config:
export default defineConfig({
plugins: [
{
name: 'requestLogger',
configurePreviewServer: logRequests, // log in preview mode
configureServer: logRequests, // log in development mode
},
],
...
});
function logRequests(server : PreviewServer | ViteDevServer) {
server.middlewares.use((req, _, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
}
here is sample access-log middle-ware plugin which logs like vite event-logs, useful in dev environment(filter garbage logs with regex):
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { URL } from 'url';
const filters: RegExp[] = [
/\/src(\/|$)/,
/\/node_modules(\/|$)/,
/\/@vite(\/|$)/,
/\/@react-refresh(\/|$)/,
];
function matchesAny(target: string | undefined, regexList: RegExp[]) {
if (!target) return false;
for (const r of regexList) if (r.test(target)) return true;
return false;
}
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
cyan: '\x1b[36m',
dim: '\x1b[2m',
bold: '\x1b[1m',
blue: '\x1b[38;5;38m',
gray: '\x1b[90m',
};
function colorForStatus(code: number) {
if (code >= 200 && code < 300) return colors.green;
if (code >= 300 && code < 400) return colors.yellow;
if (code >= 400) return colors.red;
return colors.cyan;
}
function log(msg: string) {
const ts = `${colors.gray}${timeString()}${colors.reset}`;
const tag = `${colors.bold}${colors.blue}[vite]${colors.reset}`;
// produce: 10:07:20 AM [vite] server restarted.
console.log(`${ts} ${tag} ${msg}`);
}
function timeString() {
const d = new Date();
return d.toLocaleTimeString(undefined, { hour12: true });
}
const logPlugin = () => ({
name: 'vite:dev-logger',
configureServer(server: any) {
server.middlewares.use((req: any, res: any, next: any) => {
const start = process.hrtime.bigint();
res.on('finish', () => {
// normalize to pathname so query strings don't break filter matching
let pathname = req.url;
try {
// req.url may be a path only; URL requires base
pathname = new URL(req.url, 'http://localhost').pathname;
} catch {
/* keep req.url as-is */
}
if (matchesAny(pathname, filters)) return;
const end = process.hrtime.bigint();
const ms = Number(end - start) / 1_000_000;
const status = res.statusCode ?? 0;
const col = colorForStatus(status);
log(
`${req.method} ${col}${req.url}${colors.reset} => ${col}${status}${colors.reset} - ${ms.toFixed(2)}ms`
);
});
next();
});
},
});
export default defineConfig({
plugins: [react(), logPlugin()],
});