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

Next.js在GitHub Actions构建失败:预渲染无法访问Django API

Next.js + Django Docker项目构建时API调用失败的解决方案

问题背景

采用Next.js(App Router)前端、Django API后端的Docker项目,本地双容器通信正常,但在GitHub Actions执行构建时,因未启动Django服务,预渲染页面时axios调用API失败导致构建终止。错误表现为getaddrinfo ENOTFOUND backend,根源是服务器组件在构建阶段发起了真实API请求。


解决方案

方案3:指定页面/组件跳过预渲染(推荐)

这是最轻量化的解决方式,针对单个页面或组件关闭预渲染,无需修改CI流程或引入额外依赖。

方法1:将ImageList改为客户端组件

在ImageList.tsx顶部添加'use client'指令,将API调用移至useEffect中(客户端组件仅在浏览器端运行,构建阶段不会执行):

'use client';
import axios from 'axios';
import { useEffect, useState } from 'react';
import Thumbnail from './Thumbnail';
import './ImageList.css';

interface Image {
  source: string,
  id: number
};

export default function ImageList() {
  const [imageList, setImageList] = useState<Image[]>([]);

  useEffect(() => {
    const fetchImages = async () => {
      axios.defaults.baseURL = 'http://backend:8000';
      const response = await axios.get('/api/image/');
      setImageList(response.data);
    };
    fetchImages();
  }, []);

  return (
    <div className='image-grid-container'>
      {imageList.map((image) => 
        <Thumbnail src={image.source} id={image.id} key={image.id}/>
      )}
    </div>
  );
};

方法2:设置单个页面为动态渲染

若希望整个首页跳过预渲染,在app/page.tsx顶部添加动态配置:

// app/page.tsx
export const dynamic = "force-dynamic";

import ImageList from './ImageList';

export default function Home() {
  return <ImageList />;
}

该配置会让Next.js在每次请求时才渲染页面,构建阶段不会执行API调用。


方案1:在GitHub Actions中模拟后端API

使用Mock Service Worker(MSW)拦截构建阶段的API请求,返回模拟数据。

  1. 安装依赖:
npm install msw --save-dev
  1. 创建Mock处理器文件mocks/handlers.ts:
import { http, HttpResponse } from 'msw';

export const handlers = [
  http.get('http://backend:8000/api/image/', () => {
    return HttpResponse.json([
      { source: '/mock-image-1.jpg', id: 1 },
      { source: '/mock-image-2.jpg', id: 2 }
    ]);
  }),
];
  1. 创建Mock Provider组件app/mock-provider.tsx:
'use client';
import { useEffect } from 'react';
import { setupWorker } from 'msw/browser';
import { handlers } from '../mocks/handlers';

const worker = setupWorker(...handlers);

export function MockProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    // 仅在测试/构建环境启用Mock
    if (process.env.NODE_ENV !== 'production') {
      worker.start();
    }
  }, []);
  return children;
}
  1. 在根布局中引入Mock Provider:
// app/layout.tsx
import { MockProvider } from './mock-provider';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <MockProvider>{children}</MockProvider>
      </body>
    </html>
  );
}
  1. 在GitHub Actions构建步骤中启用Mock:
- name: Build Next.js app
  env:
    NODE_ENV: test
  run: npm run build

方案2:在GitHub Actions中启动双容器

利用Docker Compose在CI环境中启动后端服务,确保构建时API可访问。

  1. 确保项目根目录有docker-compose.yml:
version: '3.8'
services:
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    # 后端启动命令、环境变量等配置
  frontend:
    build: ./frontend
    depends_on:
      - backend
    # 前端配置
  1. 修改GitHub Actions workflow文件:
name: Build and Validate
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Start backend service
        run: docker-compose up -d backend

      - name: Wait for backend to be ready
        run: |
          # 轮询直到后端API可访问
          until curl -s --head --fail http://localhost:8000/api/image/; do
            sleep 3
          done

      - name: Install frontend dependencies
        working-directory: ./frontend
        run: npm install

      - name: Build frontend
        working-directory: ./frontend
        run: npm run build

      - name: Clean up containers
        run: docker-compose down

方案4:关闭全局预渲染(非首选)

若所有页面都无需预渲染,可在根布局中设置全局动态配置:

// app/layout.tsx
export const dynamic = "force-dynamic";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

此方案会完全失去预渲染的性能优势,仅在特殊场景下使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 19:45:18