Nextjs 在生产服务器上部署后不使用图像 url 获取图像

Has*_*eeb 4 image amazon-s3 node.js next.js

对于生产部署,我们有一个由 3 台 Linux 机器组成的网络。其中两个用于部署,一个是 nginx 代理。对于开发部署,我们有一台单独的 Linux 机器。

在前端(这是一个 nextjs 框架)内部,设置了一个 http-proxy-middleware 用于解析浏览器的 cors 请求。这是http-proxy-middleware的代码:

import { API_URL } from "../../../config/";
import { createProxyMiddleware } from "http-proxy-middleware";

// Create proxy instance outside of request handler function to avoid unnecessary re-creation
const apiProxy = createProxyMiddleware({
  target: `${API_URL}`,
  changeOrigin: true,
  pathRewrite: { [`^/api/proxy`]: "" },
  secure: false,
});

export default function handler(req, res) {
  console.log(
    `Method: ${req.method} URL: ${req.url} Status Code: ${res.statusCode}`
  );
  apiProxy(req, res, (result) => {
    if (result instanceof Error) {
      throw result;
    }

    throw new Error(
      `Request '${req.url}' is not proxied! We should never reach here!`
    );
  });
}
export const config = { api: { externalResolver: true, bodyParser: false } };

Run Code Online (Sandbox Code Playgroud)

为了获取图像,我们只需在 next/image 组件的 src 属性中提供图像 url。像这样:

<Image
      src={currentImage.imageurl}
      alt={currentImage.imageurl} 
      layout="fill"
      className={styles.imageSize}  />
Run Code Online (Sandbox Code Playgroud)

这是 next.config.js 文件:

module.exports = {
  reactStrictMode: true,
  images: {
    domains: ["exam105.s3.amazonaws.com"],
  },
  async headers() {
    return [
      {
        source: "/(.*)",
        headers,
      },
    ];
  },
};

Run Code Online (Sandbox Code Playgroud)

正如您在上面的 next.config.js 文件中看到的,我也添加了图像的域。我还取消了 dockerfile 中这一行的注释,以上传 next.config.js 文件中的更改: COPY --from=builder /app/next.config.js ./ 这就是为什么当前端部署在开发服务器上时,图像将被获取并显示在浏览器上。但是,当前端部署在生产环境中时,不会显示图像,而是弹出错误:在浏览器上,它给出500 Internal Server Error. 这是 nginx 日志中出现的错误:

"GET /_next/image?url=https%3A%2F%2Fexam105.s3.amazonaws.com%2Fimage.jpg&w=128&q=75 HTTP/1.1" 500 32 "https://exam105.com/search/6176cdfe27612732e98a25d9/6176cdfe27612732e98a25d6" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62"
Run Code Online (Sandbox Code Playgroud)

前端日志打印此错误:

FetchError: request to https://exam105.s3.amazonaws.com/image.JPG failed, reason: getaddrinfo EAI_AGAIN exam105.s3.amazonaws.com
     at ClientRequest.<anonymous> (/app/node_modules/node-fetch/lib/index.js:1461:11)
     at ClientRequest.emit (node:events:390:28)
     at TLSSocket.socketErrorListener (node:_http_client:447:9)
     at TLSSocket.emit (node:events:390:28)
     at emitErrorNT (node:internal/streams/destroy:157:8)
     at emitErrorCloseNT (node:internal/streams/destroy:122:3)
     at processTicksAndRejections (node:internal/process/task_queues:83:21) {
   type: 'system',
   errno: 'EAI_AGAIN',
   code: 'EAI_AGAIN'
 }
Run Code Online (Sandbox Code Playgroud)

正如我们从 nginx 日志中的错误中看到的,图像 URL 是用某些字符进行编码的,在我看来这可能就是问题所在。当我通过单击浏览器中损坏的图像进入检查元素时,该网址也可见。前端正在发送编码的 url,但未解码,因此抛出错误。我们如何删除下一个/图像组件的编码?或者,如果无法阻止编码,我们如何在架构的上下文中对其进行解码? 因为我尝试<Image.../><img.../>标签替换,并且图像也开始显示在生产中部署的前端上。这次当我在浏览器中检查图像时,没有在 URL 中看到任何编码。因此 next/image 组件正在执行编码,但在部署到生产服务器上时它不会被解码,但是当它部署在开发服务器上时,它会被解码并且也可以使用 next/image 组件看到图像。

我希望你能理解这个问题。如果有不清楚的地方,请发表评论。谢谢。

Mar*_*orn 9

看起来 next 的加载器正在对 url 进行编码,为了克服这个问题,您可以定义自己的加载器,它只是返回 src,如下所示:

  const loaderProp =({ src }) => {
    return src;
  }
Run Code Online (Sandbox Code Playgroud)

然后在您的<Image>as 中引用它:

<Image
      src={currentImage.imageurl}
      alt={currentImage.imageurl} 
      layout="fill"
      className={styles.imageSize} 
      loader={loaderProp} />
Run Code Online (Sandbox Code Playgroud)