在我们公司的项目中,我们停止提供优化后的图像,因为 Google 无法正确识别路径名为
/_next/image
的 URL。由于 Google 使它成为一个问题,因为现在存在不可索引的页面,我们希望通过将旧 URL(优化版本)重定向到新 URL(原始 URL)来尽快删除它们。例如,/_next/image?url=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Fv1677122002%2Fnextjs%2Fshowcase%2Ftemplate-next-boilerplate.jpg&w=1920&q=75
现在是 https://assets.vercel.com/image/upload/v1677122002/nextjs/showcase/template-next-boilerplate.jpg
最初,我尝试通过使用正则表达式捕获源中的搜索参数并在目标中使用它来在
next.config.mjs
内重定向,但无论如何都无法识别/_next/image
:
{
// does not work
source: '/_next/image',
destination: 'https://something.com',
statusCode: 301,
},
{
// works
source: '/next/image',
destination: 'https://something.com',
statusCode: 301,
},
然后我尝试使用类似这样的东西在中间件中进行重定向:;
export default async function middleware(request) {
const url = request.nextUrl;
console.log(url);
// Check if the path is _next/image and handle redirect logic
if (url.pathname === '/_next/image' && url.searchParams.has('url')) {
const originalUrl = decodeURIComponent(url.searchParams.get('url'));
return NextResponse.redirect(originalUrl, 301);
}
// For other paths, apply the localization middleware
return intlMiddleware(request);
}
export const config = {
matcher: [
'/',
'/_next/image',
'/(de|en)/:path*',
'/((?!api|_vercel|.*\\..*).*)',
]
};
/_next/something
运行中间件,但 /_next/image
严格不运行并返回 404。是否有最终的实现方法 - 如何将下一个图像重定向到其原始 URL?
听起来您正尝试将请求从优化的 Next.js 图像 URL (/_next/image) 重定向到原始 URL (原始 URL),因为 Google 索引问题。这有点棘手,因为正如您所注意到的,Next.js 对 /next/image 使用内部路由,这可能会阻止某些重定向按预期工作。
您可以尝试以下一种改进的方法:
解决方案 1:将自定义服务器与 Next.js 结合使用 处理此问题的一种方法是在 Next.js 中使用自定义服务器,例如 Express,您可以在其中完全控制路由。使用自定义服务器,您可以拦截对 /next/image 的请求并将其重定向到原始 URL。
这是一个使用 Express 的简单示例:
安装 Express:
bash
Copy code
npm install express
更新您的 server.js(如果您还没有此文件,请在项目的根目录中创建此文件):
const express = require('express'); const next = require('下一个'); const { 解析 } = require('url');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
// Redirect _next/image to the original URL
server.get('/_next/image', (req, res) => {
const originalUrl = decodeURIComponent(req.query.url);
if (originalUrl) {
return res.redirect(301, originalUrl);
}
res.status(404).send('Not found');
});
server.all('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
更新您的 package.json 以启动自定义服务器:
json 复制代码
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
}
通过此设置,带有 url 查询参数的对 /next/image 的请求将重定向到原始 URL。
解决方案 2:不使用 /next/image 提供图像 如果您想完全避免使用 /next/image,您可以通过使用外部域设置 next.config.js 来配置 Next.js 以在不优化的情况下提供图像。
javascript 复制代码
// next.config.js
module.exports = {
images: {
domains: ['assets.vercel.com'], // Add your external domains here
unoptimized: true, // This serves images without optimization
},
};
设置 unoptimized: true 将使 Next.js 使用原始图像 URL,而不经过 /next/image,这应该可以解决 Google 索引问题。
解决方案3:自定义中间件重写(实验性) 如果您不想使用自定义服务器,您可以尝试这种中间件方法(不过,正如您所指出的,中间件在处理某些内部 Next.js 路由方面受到限制):
编写中间件来重定向 /next/image 请求:
javascript 复制代码
import { NextResponse } from 'next/server';
export function middleware(request) {
const url = request.nextUrl;
if (url.pathname === '/_next/image' && url.searchParams.has('url')) {
const originalUrl = decodeURIComponent(url.searchParams.get('url'));
return NextResponse.redirect(originalUrl, 301);
}
return NextResponse.next();
}
export const config = {
matcher: '/_next/image',
};
虽然这种中间件方法在某些情况下可能有效,但由于 Next.js 处理其内部路由的方式,它不能保证按预期拦截所有 /next/image 请求。如果解决方案 2 不能满足您的需求,则自定义服务器方法(解决方案 1)更可靠。