Олег Карнауховweb developerОбсудить проект

Блог

Карта сайта, которая врала про даты, и как её починить

lastmod, зашитый константой в код, — это обещание роботу, что сайт не меняется. Как брать дату из файла, что считать полом и почему точность в сутки правильнее миллисекунд.

В карте сайта у всех адресов стояла одна дата, и она была написана рукой в константе. Сайт при этом менялся почти каждый день. Для робота это заявление: возвращаться незачем.

Почему так вышло

Константа появилась из здравого рассуждения: если подставить в lastmod текущее время, карта будет утверждать, что сайт изменился прямо сейчас, при каждом обходе. Это тоже ложь, и её поисковики распознают — дата, которая всегда «сегодня», перестаёт считаться сигналом.

Поэтому дату зафиксировали и оставили комментарий «обновлять при изменениях». Через две недели она устарела, потому что такие комментарии не работают: обновлять её никто не помнит, и напоминать некому.

Где правильный источник

У даты изменения страницы есть честный источник — файл, в котором лежат её слова. Панель пишет этот файл, значит время изменения файла и есть ответ. Правка в админке двигает дату сама, без участия человека.

Для страниц, которые живут в коде, а не в панели, такого файла нет. Их честная дата — момент выкладки: релиз создаёт новый каталог, и время его создания это и есть.

app/server/changed.tsts
export async function changedAt(...files: string[]): Promise<Date | undefined> {
  const times = await Promise.all(files.map(when));
  const known = times.filter((time): time is number => time !== undefined);
  return known.length ? new Date(Math.max(...known)) : undefined;
}

async function when(file: string): Promise<number | undefined> {
  try {
    return (await stat(file)).mtimeMs;
  } catch {
    // Нет файла, нет прав, это каталог — всё это значит одно:
    // сказать о дате изменения нечего.
    return undefined;
  }
}
undefined — допустимый ответ. Запись в карте сайта может вообще не иметь lastmod, и это честнее выдуманной даты.
СпособЧто сообщает роботуПроблема
Константа в кодесайт не менялся с даты Xустаревает молча
new Date() при запросеменялся прямо сейчасвсегда «сегодня», сигнал обесценивается
Время изменения файламенялся тогда, когда менялсятребует, чтобы контент лежал в файлах
Отсутствие lastmodне знаюробот решает сам
Третья строка — то, к чему стоит стремиться. Четвёртая — приемлемое отступление, первая — нет.

Точность — сутки

Первая версия починки отдавала полный ISO с миллисекундами. Формально допустимо, но выглядело как машинный шум и утверждало, что все страницы изменились в одну и ту же миллисекунду — что было правдой, потому что все они получили дату релиза, но читалось как ошибка.

Стандарт карты сайта начинает описание поля с формата ГГГГ-ММ-ДД. Точность мельче суток для расписания обхода не значит ничего.

Чего в этой схеме всё ещё не хватает

Карта сайта — пассивный сигнал: робот придёт и прочитает её, когда сам решит. Активный способ сообщить о новой странице — протокол IndexNow: один запрос уведомляет Яндекс и Bing сразу. Его в моей схеме пока нет, и это следующая доработка.