Next.js robots.txt не найден: Полное руководство по решению
Исправьте ошибки 404 robots.txt в Next.js с помощью нашего подробного руководства. Узнайте, почему /robots.txt перенаправляет на страницу 'Не найдено', а /robots работает, и реализуйте надежные решения с помощью промежуточного ПО, статической генерации или настройки маршрутов.
Почему мой файл robots.txt в Next.js перенаправляет на страницу “Not Found” при доступе по адресу http://localhost:3000/robots.txt, но при этом http://localhost:3000/robots работает корректно? Я пытаюсь динамически генерировать файл robots.txt с помощью API-маршрута в моем приложении Next.js.
Вот мой файл robots.ts в папке API:
import type { NextApiRequest, NextApiResponse } from 'next';
import { GraphQLRobotsService } from '@sitecore-jss/sitecore-jss-nextjs';
import { siteResolver } from 'lib/site-resolver';
import clientFactory from 'lib/graphql-client-factory';
const robotsApi = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => {
res.setHeader('Content-Type', 'text/plain');
// Resolve site based on hostname
const hostName = req.headers['host']?.split(':')[0] || 'localhost';
const site = siteResolver.getByHost(hostName);
// create robots graphql service
const robotsService = new GraphQLRobotsService({
clientFactory,
siteName: site.name,
});
const robotsResult = await robotsService.fetchRobots();
return res.status(200).send(robotsResult);
};
export default robotsApi;
А вот мой файл next.config.js с конфигурацией перезаписей:
const jssConfig = require('./src/temp/config');
const plugins = require('./src/temp/next-config-plugins') || {};
const path = require('path');
const publicUrl = jssConfig.publicUrl;
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
// Set assetPrefix to our public URL
assetPrefix: publicUrl,
// Allow specifying a distinct distDir when concurrently running app in a container
distDir: process.env.NEXTJS_DIST_DIR || '.next',
// Make the same PUBLIC_URL available as an environment variable on the client bundle
env: {
PUBLIC_URL: publicUrl,
},
i18n: {
// These are all the locales you want to support in your application.
// These should generally match (or at least be a subset of) those in Sitecore.
locales: ['ms', 'en', 'ms-MY'],
// This is the locale that will be used when visiting a non-locale
// prefixed path e.g. `/styleguide`.
defaultLocale: jssConfig.defaultLanguage,
localeDetection: false,
},
// Enable React Strict Mode
reactStrictMode: true,
// Disable the X-Powered-By header. Follows security best practices.
poweredByHeader: false,
// use this configuration to ensure that only images from the whitelisted domains
// can be served from the Next.js Image Optimization API
// see https://nextjs.org/docs/app/api-reference/components/image#remotepatterns
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'edge*.**',
port: '',
},
{
protocol: 'https',
hostname: 'xmc-*.**',
port: '',
},
{
protocol: 'https',
hostname: 'feaas*.blob.core.windows.net',
port: '',
},
]
},
async rewrites() {
// When in connected mode we want to proxy Sitecore paths off to Sitecore
return [
{
// When I change /robots.txt to /robots, http://localhost:3000/robots starts to work.
source: '/robots.txt',
destination: '/api/robots',
},
// ... other rewrites
];
},
// ... other configurations
};
module.exports = () => {
// Run the base config through any configured plugins
return Object.values(plugins).reduce((acc, plugin) => plugin(acc), nextConfig);
};
Я также пробовал создать плагин для обработки перезаписи robots.txt, но это все еще не работает. Вот мой файл src/lib/next-config/plugins/robots.js:
/**
* @param {import('next').NextConfig} nextConfig
*/
const robotsPlugin = (nextConfig = {}) => {
return Object.assign({}, nextConfig, {
async rewrites() {
const baseRewrites = (await nextConfig.rewrites?.()) || {
beforeFiles: [],
afterFiles: [],
fallback: [],
};
baseRewrites.beforeFiles.push({
source: '/robots.txt',
destination: '/api/robots',
});
return baseRewrites;
},
});
};
module.exports = robotsPlugin;
Как правильно настроить Next.js для обслуживания файла robots.txt из моего API-маршрута по адресу http://localhost:3000/robots.txt?
Проблема, с которой вы сталкиваетесь с перенаправлением robots.txt в Next.js на страницу “Not Found”, является распространенным конфликтом маршрутизации, который возникает, когда встроенная обработка robots.txt в Next.js мешает вашей перезаписи API-маршрута. На основе результатов исследования это происходит потому, что App Router в Next.js имеет специальную обработку файлов robots.txt, которая может переопределить вашу конфигурацию перезаписи.
Основная причина, как выяснилось, представляет собой конфликт маршрутизации между встроенной обработкой robots.txt в Next.js и вашей перезаписью API-маршрута. При доступе к /robots.txt App Router в Next.js сначала ищет статический файл robots.txt, и только если его не находит, рассматривает перезаписи. Это объясняет, почему /robots работает (это стандартный API-маршрут), а /robots.txt возвращает 404.
Содержание
- Понимание конфликта маршрутизации
- Решение 1: Использование промежуточного ПО для обработки robots.txt
- Решение 2: Статический robots.txt с динамическим содержимым
- Решение 3: Группы маршрутов и структура файлов
- Решение 4: Отключение встроенной обработки robots.txt в Next.js
- Лучшие практики для robots.txt в Next.js
- Шаги по устранению неполадок
Понимание конфликта маршрутизации
Как упоминается в GitHub issue #47198, проблема вызвана конфликтами маршрутов. App Router в Next.js имеет встроенную обработку файлов robots.txt и sitemap.xml, которая имеет приоритет над перезаписями в определенных сценариях.
Официальная документация показывает, что Next.js ожидает найти файлы robots.txt в определенных местах, и когда он не может найти их в ожидаемых местах, он может не правильно вернуться к вашим правилам перезаписи.
Ключевое из исследования заключается в том, что переписывания для robots.txt в App Router работают ненадежно из-за этой встроенной обработки. Разработчики сообщали об этой проблеме в различных версиях Next.js.
Решение 1: Использование промежуточного ПО для обработки robots.txt
Наиболее надежное решение - использовать промежуточное ПО (middleware) в Next.js для перехвата запросов /robots.txt и перенаправления их на ваш API-маршрут:
Создайте файл middleware.ts в корне вашего проекта:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname === '/robots.txt') {
// Переписываем запросы robots.txt на ваш API-маршрут
return NextResponse.rewrite(new URL('/api/robots', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
// Соответствовать всем путям запросов, кроме начинающихся с:
// - api (API-маршруты)
// - _next/static (статические файлы)
// - _next/image (файлы оптимизации изображений)
// - favicon.ico (файл favicon)
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
Этот подход работает, потому что промежуточное ПО выполняется до любой логики маршрутизации, обеспечивая приоритет вашей перезаписи над встроенной обработкой Next.js.
Решение 2: Статический robots.txt с динамическим содержимым
Другой подход - создать статический файл robots.txt, но сделать его содержимое динамическим. Вы можете создать скрипт, который генерирует содержимое robots.txt и записывает его в общедоступный каталог во время сборки:
// scripts/generate-robots.js
const fs = require('fs');
const path = require('path');
// Импортируйте ваш сервис robots
const { GraphQLRobotsService } = require('@sitecore-jss/sitecore-jss-nextjs');
const { siteResolver } = require('lib/site-resolver');
const clientFactory = require('lib/graphql-client-factory');
async function generateRobots() {
const hostName = 'localhost'; // Возможно, вы захотите сделать это настраиваемым
const site = siteResolver.getByHost(hostName);
const robotsService = new GraphQLRobotsService({
clientFactory,
siteName: site.name,
});
const robotsResult = await robotsService.fetchRobots();
// Запись в общедоступный каталог
const robotsPath = path.join(process.cwd(), 'public', 'robots.txt');
fs.writeFileSync(robotsPath, robotsResult);
console.log('robots.txt успешно сгенерирован');
}
generateRobots().catch(console.error);
Добавьте этот скрипт в ваш package.json:
{
"scripts": {
"generate-robots": "node scripts/generate-robots.js"
}
}
Затем запустите его перед сборкой:
npm run generate-robots npm run build
Этот подход гарантирует наличие статического файла robots.txt, который поисковые системы могут найти надежно.
Решение 3: Группы маршрутов и структура файлов
Согласно результатам исследования из блога Дариуса МакФарланда, группы маршрутов могут влиять на маршрутизацию robots.txt.
Попробуйте организовать ваши файлы следующим образом:
app/
├── api/
│ └── robots/
│ └── route.ts # Ваш обработчик API
├── robots.txt.ts # Файл метаданных для robots.txt
└── layout.tsx
В robots.txt.ts:
import type { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
// Это будет автоматически обслуживаться по адресу /robots.txt
return {
rules: [
{
userAgent: '*',
allow: '/',
},
],
sitemap: 'https://your-site.com/sitemap.xml',
};
}
И измените ваш API-маршрут для обработки фактической генерации динамического содержимого.
Решение 4: Отключение встроенной обработки robots.txt в Next.js
Если вы хотите полностью контролировать robots.txt через ваш API-маршрут, вы можете попробовать отключить встроенную обработку Next.js. Это более сложный подход и может не быть рекомендованным, но это вариант:
// next.config.js
const nextConfig = {
// ... другая конфигурация
async rewrites() {
return [
{
source: '/robots.txt',
destination: '/api/robots',
},
];
},
// Добавьте экспериментальную конфигурацию
experimental: {
// Это может помочь с конфликтами маршрутизации
serverComponentsExternalPackages: ['@sitecore-jss/sitecore-jss-nextjs'],
},
};
Однако, как отмечено в GitHub issues, этот подход может работать ненадежно из-за лежащих в основе конфликтов маршрутизации.
Лучшие практики для robots.txt в Next.js
На основе результатов исследования, вот некоторые лучшие практики:
-
Используйте промежуточное ПО для динамического robots.txt: Это наиболее надежный подход для проектов с App Router.
-
Рассмотрите статическую генерацию для производства: Если содержимое вашего robots.txt меняется нечасто, генерируйте его во время сборки.
-
Тщательно тестируйте: Как упоминается в обсуждении на Reddit, разные среды (localhost против production) могут вести себя по-разному.
-
Проверяйте на конфликты маршрутизации: Убедитесь, что у вас нет конфликтующих обработчиков маршрутов или промежуточного ПО, которые могут мешать.
-
Следите за обновлениями версий Next.js: Проблема была зарегистрирована в различных версиях Next.js, и исправления могут быть доступны в более новых выпусках.
Шаги по устранению неполадок
Если ни одно из вышеперечисленных решений не работает, попробуйте следующие шаги по устранению неполадок:
-
Проверьте на наличие конфликтующих файлов: Ищите любые существующие файлы
robots.txtв вашем каталогеpublicили в других местах вашего проекта. -
Очистите кэш Next.js: Иногда очистка каталога
.nextможет решить проблемы с маршрутизацией. -
Протестируйте с минимальной конфигурацией: Создайте минимальный проект Next.js только с перезаписью robots.txt, чтобы изолировать проблему.
-
Проверьте порядок промежуточного ПО: Если у вас несколько файлов промежуточного ПО, убедитесь, что они не мешают друг другу.
-
Проверьте заголовки запросов: Убедитесь, что ваш API-маршрут правильно обрабатывает заголовок
Content-Typeкакtext/plain. -
Тестируйте в разных средах: Проблема может быть специфичной для среды, поэтому тестируйте как в разработке, так и в производстве.
Ключевой вывод из исследования заключается в том, что переписывания для robots.txt в App Router Next.js могут быть ненадежными из-за встроенной обработки, и решения на основе промежуточного ПО или статической генерации часто являются более надежными подходами.