首先一些背景信息。我有 2 个 docker 容器正在运行用于开发:api 和前端:
由于 next/image 会自动优化服务器端的图像,因此我们为图像传递以下基本 url:
http://host.docker.internal:1337/uploads/*filenamehere.ext*
这对于 80% 的图像来说效果很好。但有时由于某种原因它不会使用NextJS图像优化,然后会尝试直接访问图像。
这里的问题是它会尝试直接从客户端访问 url
http://host.docker.internal:1337/uploads/carbon_..etc.svg
,这是不可能的...
有什么好的解决方案吗?我想继续使用 Next 的图像优化。
最简单的可能是从我的主机访问“api”容器,使用:
127.0.0.1:1337
。但就没有别的办法了吗?
我想阻止使用主机网络。
不起作用的请求是针对 SVG 的。 NextJS 不需要优化 SVG,因为它们是表示为文本的矢量格式。
这意味着默认情况下它不会对它们执行任何操作,因此“原始”图像位置的 URL 最终由 HTML
<img>
标记直接使用。该 URL 被发送到您的上游服务器,该服务器无法公开访问;因此,当浏览器尝试获取它时它不起作用。
这里的问题是人们(至少部分地)出于错误的原因而依赖 NextJS 图像优化。您的图像似乎托管在其他一些上游服务上,该服务无法在您的容器上公开访问。因此,您需要通过 NextJS 服务器反向代理这些图像。
NextJS 图像优化将顺便且仅部分满足此要求。 它仅适用于 NextJS 认为需要优化的图像。对于这些,它从源下载(通过内部网络启用,因此可以这样做)图像,优化它,缓存它,然后从 NextJS 实例上的 URL 提供该图像。
这意味着对于优化的图像,缓存的 URL 最终用于 HTML
<img>
标记,该标记可在浏览器中工作,因为它是可访问的 URL。
dangerouslyAllowSVG
变得很诱人,这将迫使它也采用与 SVG 相同的代码路径。 但是,这并不能解决心智模型/架构缺陷——这是“真正的”问题。它似乎也有安全隐患。
从上游反向代理图像的要求是其自身的业务需求,并且您不应该依靠图像优化本身来实现这一点。 NextJS 图像优化旨在提供一种优化图像的机制。在某些情况下,它充当反向代理是一个技术细节,您现在或将来不能依赖该行为来满足此业务需求。您对此反向代理有一流的要求,因此您必须定义它。
我们可以使用
rewrites来实现这一点。在next.config.js
:
module.exports = {
async rewrites() {
return [
{
source: '/raw/:path*',
destination: 'http://host.docker.internal:1337/uploads/:path*'
},
]
},
}
这意味着您的 NextJS 实例上的新 URL
/raw/<image-path>
可用,其中
image-path
是要从 http://host.docker.internal:1337/uploads
请求的图像的文件名。然后,当使用 <Image>
标签时,将传递的
src
属性将是上面 source
目的地的相对路径,并且 not包含任何完全限定的内部 docker 域。例如。
src="/raw/example-image.svg"
。对于 NextJS 不需要做任何优化的情况(例如 SVG),它将执行之前所做的操作,即直接使用 src
属性作为
src
的 <img>
HTML 属性。但现在该 URL 将是有效的,指向我们的 /raw
路径,NextJS 将通过我们的重写将其代理到上游。