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

寻求适用于Next.js的同构日志方案,支持日志推送至服务器

Next.js 跨端通用日志方案实现

一、封装统一日志工具类

直接写一个通用日志工具,内部自动识别运行环境,让你不用手动区分服务端还是客户端,调用同一个API就能打日志。

1. 基础日志工具代码

在项目里新建utils/logger.js(TS项目用.ts),代码如下:

class Logger {
  constructor() {
    this.isServer = typeof window === 'undefined';
    // 这里填你的后端日志接收接口地址
    this.logEndpoint = '/api/logs';
  }

  // 通用日志方法,支持debug/info/warn/error四种级别
  log(level, message, meta = {}) {
    const logData = {
      level,
      message,
      meta: {
        ...meta,
        timestamp: new Date().toISOString(),
        env: process.env.NODE_ENV,
        isServer: this.isServer
      }
    };

    // 服务端直接打控制台,也可以顺便推送到远程
    if (this.isServer) {
      console[level](logData);
      this.sendToRemote(logData);
      return;
    }

    // 客户端先打控制台,生产环境再推送到远程
    console[level](logData);
    if (process.env.NODE_ENV === 'production') {
      this.sendToRemote(logData);
    }
  }

  // 封装快捷方法,调用更方便
  debug(message, meta) { this.log('debug', message, meta); }
  info(message, meta) { this.log('info', message, meta); }
  warn(message, meta) { this.log('warn', message, meta); }
  error(message, meta) { this.log('error', message, meta); }

  // 远程上报逻辑,用keepalive保证页面卸载时也能发出去
  async sendToRemote(logData) {
    try {
      await fetch(this.logEndpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(logData),
        keepalive: true
      });
    } catch (err) {
      // 上报失败别影响主业务,悄悄打个错就行
      console.error('日志上报失败:', err);
    }
  }
}

// 单例模式,全局只用一个实例
const logger = new Logger();
export default logger;

二、服务端接收日志的API

需要写个后端接口接收客户端发过来的日志,这里用Next.js的API路由举例:
如果是Pages Router,新建pages/api/logs.js:

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const logData = req.body;
    // 这里可以把日志存数据库、写文件,或者转发到ELK、Datadog这类专业日志服务
    console.log('收到客户端日志:', logData);
    res.status(200).json({ success: true });
  } else {
    res.status(405).json({ error: 'Method Not Allowed' });
  }
}

如果是App Router,新建app/api/logs/route.js:

export async function POST(request) {
  const logData = await request.json();
  console.log('收到客户端日志:', logData);
  return new Response(JSON.stringify({ success: true }), {
    headers: { 'Content-Type': 'application/json' },
  });
}

三、全局使用日志工具

不管是服务端组件、客户端组件还是API路由,直接导入就能用,完全不用管环境:

// 客户端组件示例
import logger from '@/utils/logger';

export default function ClientComponent() {
  const handleBtnClick = () => {
    logger.info('用户点击了提交按钮', { buttonId: 'submit-btn', userId: 'xxx' });
  };

  return <button onClick={handleBtnClick}>提交</button>;
}
// 服务端组件示例
import logger from '@/utils/logger';

export default async function ServerComponent() {
  logger.debug('服务端组件开始渲染', { componentName: 'ServerComponent' });
  // 业务逻辑...
  return <div>服务端渲染内容</div>;
}
// API路由示例
import logger from '@/utils/logger';

export async function GET() {
  logger.warn('请求参数缺失', { apiPath: '/api/user', ip: req.headers['x-forwarded-for'] });
  return new Response('参数错误', { status: 400 });
}

四、进阶优化点

  • 日志级别控制:用环境变量设置生产环境只上报warn和error,避免日志爆炸
  • 敏感信息过滤:在上报前自动过滤掉密码、token这类敏感数据
  • 批量上报:客户端把日志缓存起来,攒够10条或者隔30秒再批量发,减少请求次数
  • 专业日志库集成:服务端可以用winston、pino这类库,把日志写入文件或者转发到专业日志平台

内容的提问来源于stack exchange,提问作者Fixing It

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:55:05