You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让NextJS输出访问日志?是否有对应开启配置?

如何让Next.js输出Apache风格的访问日志?

默认情况下,Next.js 使用 yarn start 启动服务时不会输出访问日志,仅会提示服务就绪:

yarn run v1.22.19
$ next start
ready - started server on 0.0.0.0:3000, url: http://localhost:3000

Next.js 没有直接的配置项可以一键开启访问日志,但可以通过以下两种方式实现类似Apache的access.log风格日志输出:

方法一:自定义服务器 + Morgan日志中间件

这是最简便的方案,借助Express和Morgan(专门生成HTTP日志的工具)快速生成Apache格式的日志。

  1. 安装依赖:
yarn add express morgan
# 或 npm install express morgan
  1. 在项目根目录创建server.js文件:
const express = require('express');
const next = require('next');
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

// 创建日志写入流(可选,若只需控制台输出可跳过)
const accessLogStream = fs.createWriteStream(
  path.join(__dirname, 'access.log'),
  { flags: 'a' } // 追加模式写入
);

app.prepare().then(() => {
  const server = express();

  // 配置Morgan输出Apache Combined格式日志
  // 若只需控制台输出,去掉{ stream: accessLogStream }参数即可
  server.use(morgan('combined', { stream: accessLogStream }));

  // 接管所有Next.js请求
  server.all('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(3000, (err) => {
    if (err) throw err;
    console.log('> Ready on http://localhost:3000');
  });
});
  1. 修改package.json的启动脚本:
"scripts": {
  "dev": "node server.js",
  "build": "next build",
  "start": "NODE_ENV=production node server.js"
}

启动服务后,控制台或access.log文件中就会生成类似Apache的日志:

192.168.2.20 - - [28/Jul/2006:10:27:10 -0300] "GET /cgi-bin/try/ HTTP/1.0" 200 3395
127.0.0.1 - - [28/Jul/2006:10:22:04 -0300] "GET / HTTP/1.0" 200 2216

方法二:使用Next.js中间件手动记录日志

如果不想搭建自定义服务器,可以通过Next.js的内置中间件手动构造日志内容。

在项目根目录创建middleware.js(或middleware.ts)文件:

import { NextResponse } from 'next/server';
import fs from 'fs/promises';
import path from 'path';

export async function middleware(request) {
  // 构造Apache风格的日志字段
  const clientIp = request.ip || request.headers.get('x-forwarded-for') || 'unknown';
  const dateStr = new Date().toLocaleString('en-US', {
    day: '2-digit',
    month: 'short',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    timeZoneName: 'short'
  }).replace(', ', ':').replace(' ', '/');
  const method = request.method;
  const url = request.nextUrl.pathname;
  const protocol = request.nextUrl.protocol.replace(':', '');
  const status = 200; // 若需获取实际响应状态,需额外处理响应对象
  const contentLength = '-'; // 实际内容长度需通过响应拦截获取

  const logLine = `${clientIp} - - [${dateStr}] "${method} ${url} HTTP/${protocol}" ${status} ${contentLength}\n`;

  // 输出到控制台
  console.log(logLine.trim());
  // 写入日志文件(可选)
  await fs.appendFile(path.join(process.cwd(), 'access.log'), logLine);

  return NextResponse.next();
}

// 指定中间件生效的路径(这里匹配所有路径)
export const config = {
  matcher: ['/:path*'],
};

这种方案无需额外安装依赖,但要获取准确的响应状态码和内容长度,需要对响应进行拦截包装,相对复杂一些,适合轻量日志需求场景。


内容的提问来源于stack exchange,提问作者Diogo Melo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 05:55:16