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

Next.js 14动态上传图片:生产环境无需构建即可显示的方法

问题描述

我搭建了一个用于添加产品图片的后台管理面板,开发模式下功能正常,但部署到云服务器生产环境时出现问题:上传的新产品图片无法自动进入/_next/image目录,必须执行npm run build才能在网站上显示。尝试设置minimumCacheTTL无效。

相关代码如下:

产品创建Action代码

export const createProduct = async (state, formData) => {
  const result = productSchema.safeParse(
    Object.fromEntries(formData.entries())
  );

  console.log(result.error);

  if (result.success === false) return result.error.formErrors.fieldErrors;

  const {
    title,
    vendorCode,
    image,
    categoryId,
    characteristics,
    mainCategoryId,
    price,
  } = result.data;

  const data = result.data;
  await fs.mkdir("public/products", { recursive: true });
  const imagePath = `/products/${crypto.randomUUID()}-${data.image.name}`;
  await fs.writeFile(
    `public${imagePath}`,
    Buffer.from(await data.image.arrayBuffer())
  );

  const product = await db.product.create({
    data: {
      title,
      slug: slugify(`${title}-${vendorCode}`, {
        locale: "ru",
        lower: true,
      }),
      image: imagePath,
      categoryId,
      vendorCode,
      mainCategoryId,
      price,
    },
  });

  await db.productCharacteristic.createMany({
    data: characteristics.map((char) => ({
      title: char.title,
      variants: char.values.map(({ value }) => value),
      productId: product.id,
    })),
  });
  revalidatePath("/");
  redirect("/admin/catalog");
}

图片使用代码

<Image
  className="absolute top-0 left-0 w-full h-full object-cover"
  src={product.image}
  width={800}
  height={800}
  alt={product.title}
/>

Next.js配置文件

/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    ignoreDuringBuilds: true,
  },
  env: {
    SERVER_URL: process.env.SERVER_URL,
  },
  images: {
    minimumCacheTTL: 60,
  },
};

export default nextConfig;
解决方案

核心原因

生产环境下,Next.js会在npm run build阶段将public目录下的静态图片预处理并生成到/_next/image目录,运行时上传到public/products的新图片不会触发这个优化流程,因此无法通过/_next/image访问。minimumCacheTTL仅控制缓存时长,不影响资源生成逻辑。

方法1:自定义API路由实现实时图片优化

通过创建API路由手动处理图片优化,替代Next.js默认的静态构建时优化:

  1. 安装图片处理依赖:
npm install sharp
  1. 在app/api/image/route.js创建路由文件:
import { NextResponse } from 'next/server';
import fs from 'fs/promises';
import path from 'path';
import sharp from 'sharp';

export async function GET(request) {
  const { searchParams } = new URL(request.url);
  const src = searchParams.get('src');
  const width = parseInt(searchParams.get('width') || '800');
  const height = parseInt(searchParams.get('height') || '800');

  if (!src) return NextResponse.json({ error: '缺少src参数' }, { status: 400 });

  try {
    // 拼接本地图片路径
    const imagePath = path.join(process.cwd(), 'public', src.slice(1));
    const imageBuffer = await fs.readFile(imagePath);
    
    // 压缩并转换图片格式
    const optimizedImage = await sharp(imageBuffer)
      .resize(width, height, { fit: 'cover' })
      .toFormat('webp')
      .toBuffer();

    return new NextResponse(optimizedImage, {
      headers: {
        'Content-Type': 'image/webp',
        'Cache-Control': 'public, max-age=2592000', // 缓存30天
      },
    });
  } catch (error) {
    return NextResponse.json({ error: '图片不存在' }, { status: 404 });
  }
}
  1. 修改Image组件的src指向自定义API,并禁用默认优化:
<Image
  className="absolute top-0 left-0 w-full h-full object-cover"
  src={`/api/image?src=${product.image}&width=800&height=800`}
  width={800}
  height={800}
  alt={product.title}
  unoptimized={true}
/>

方法2:直接使用原生img标签(快速方案)

如果不需要Next.js的图片优化功能,直接改用原生img标签即可:

<img
  className="absolute top-0 left-0 w-full h-full object-cover"
  src={product.image}
  width={800}
  height={800}
  alt={product.title}
/>

方法3:上传到云存储并配置图片域名

将图片上传到云存储(如阿里云OSS、AWS S3等),让Next.js远程优化图片:

  1. 修改上传逻辑,将图片上传到云存储,把返回的URL存入数据库。
  2. 更新next.config.js配置云存储域名:
/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    ignoreDuringBuilds: true,
  },
  env: {
    SERVER_URL: process.env.SERVER_URL,
  },
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'your-cloud-storage-domain.com', // 替换为你的云存储域名
        pathname: '/products/**',
      },
    ],
  },
};

export default nextConfig;
  1. Image组件直接使用云存储返回的URL即可。

内容的提问来源于stack exchange,提问作者Павел Соляник

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:50:55