Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI
История версий
- "Обновление использования API useIntlayer в Solid для прямого доступа к свойствам"v8.9.004.05.2026
- "Добавить команду init"v7.5.930.12.2025
- "Инициализация истории"v5.5.1029.06.2025
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Перевод вашего сайта на Vite и React с помощью Intlayer | Интернационализация (i18n)
Содержание
Почему Intlayer лучше альтернатив?
По сравнению с основными решениями, такими как «react-i18next» или «i18next», Intlayer — это решение, которое включает в себя встроенные оптимизации, такие как:
Intlayer оптимизирован для идеальной работы с Vite и React, предлагая охват контента на уровне компонентов, отложенные переводы и все функции, необходимые для масштабирования интернационализации (i18n).
Вместо загрузки огромных файлов JSON на свои страницы загружайте только необходимый контент. Intlayer помогает уменьшить размер бандла и страниц до 50 %.
Определение области содержимого вашего приложения облегчает обслуживание крупномасштабных приложений. Вы можете дублировать или удалить отдельную папку функций, не утруждав себя мысленным бременем проверки всей кодовой базы контента. Кроме того, Intlayer полностью типизирован, что обеспечивает точность вашего контента.
Совместное размещение контента уменьшает контекст, необходимый для моделей большого языка (LLM). Intlayer также поставляется с набором инструментов, таких как CLI для проверки отсутствия переводов,LSP, MCP, и навыки агента, чтобы сделать работу разработчика (DX) еще более удобной для агентов ИИ.
Используйте автоматизацию для перевода в своем конвейере CI/CD, используя LLM по вашему выбору за счет вашего поставщика ИИ. Intlayer также предлагает компилятор для автоматизации извлечения контента, а также веб-платформу, которая помогает переводить в фоновом режиме.
Подключение больших файлов JSON к компонентам может привести к проблемам с производительностью и реактивностью. Intlayer оптимизирует загрузку контента во время сборки (build time).
Intlayer — это больше, чем просто решение i18n. Он предоставляет автономный визуальный редактор и полный CMS, чтобы помочь вам управлять многоязычным контентом в реальном времени, упрощая сотрудничество с переводчиками, копирайтерами и другими членами команды. Контент может храниться локально и/или удаленно.
Пошаговое руководство по настройке Intlayer в приложении на Vite и React
Смотрите Application Template на GitHub.
Установка зависимостей
Установите необходимые пакеты с помощью npm:
bashКопировать кодКопировать код в буфер обмена
npm install intlayer react-intlayernpm install vite-intlayer --save-devnpx intlayer initintlayer Основной пакет, предоставляющий инструменты интернационализации для управления конфигурацией, перевода, объявления контента, транспиляции и CLI-команд.
react-intlayer Пакет, который интегрирует Intlayer с приложением на React. Он предоставляет провайдеры контекста и хуки для интернационализации в React.
vite-intlayer Включает плагин Vite для интеграции Intlayer с сборщиком Vite, а также middleware для определения предпочтительной локали пользователя, управления куки и обработки перенаправления URL.
Конфигурация вашего проекта
Создайте файл конфигурации для настройки языков вашего приложения:
intlayer.config.tsКопировать кодКопировать код в буфер обмена
import { Locales, type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // Ваши другие локали ], defaultLocale: Locales.ENGLISH, }, }; export default config;Через этот файл конфигурации вы можете настроить локализованные URL-адреса, перенаправление в middleware, имена cookie, расположение и расширение ваших деклараций контента, отключить логи Intlayer в консоли и многое другое. Для полного списка доступных параметров обратитесь к документации по конфигурации.
Интеграция Intlayer в вашу конфигурацию Vite
Добавьте плагин intlayer в вашу конфигурацию.
vite.config.tsКопировать кодКопировать код в буфер обмена
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import { intlayer } from "vite-intlayer"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react(), intlayer()], });Плагин Vite
intlayer()используется для интеграции Intlayer с Vite. Он обеспечивает создание файлов деклараций контента и отслеживает их в режиме разработки. Он определяет переменные окружения Intlayer внутри приложения Vite. Кроме того, он предоставляет алиасы для оптимизации производительности.Объявите Ваш Контент
Создайте и управляйте декларациями контента для хранения переводов:
src/app.content.tsxКопировать кодКопировать код в буфер обмена
import { t, type Dictionary } from "intlayer"; import type { ReactNode } from "react"; const appContent = { key: "app", content: { viteLogo: t({ en: "Vite logo", fr: "Logo Vite", es: "Logo Vite", }), reactLogo: t({ en: "React logo", fr: "Logo React", es: "Logo React", }), title: "Vite + React", count: t({ en: "count is ", fr: "le compte est ", es: "el recuento es ", }), edit: t<ReactNode>({ en: ( <> Редактируйте <code>src/App.tsx</code> и сохраните, чтобы проверить HMR </> ), fr: ( <> Éditez <code>src/App.tsx</code> et enregistrez pour tester HMR </> ), es: ( <> Edita <code>src/App.tsx</code> y guarda para probar HMR </> ), }), readTheDocs: t({ en: "Нажмите на логотипы Vite и React, чтобы узнать больше", fr: "Cliquez sur les logos Vite et React pour en savoir plus", es: "Haga clic en los logotipos de Vite y React para obtener más información", }), }, } соответствует Dictionary; export default appContent;Ваши объявления контента могут быть определены в любом месте вашего приложения, как только они включены в каталог
contentDir(по умолчанию,./src). И соответствуют расширению файла объявления контента (по умолчанию,.content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}).Для получения дополнительной информации обратитесь к документации по объявлению контента.
Если ваш файл контента включает код TSX, рекомендуется импортировать
import React from "react";в вашем файле контента.Использование Intlayer в вашем коде
Получайте доступ к вашим словарям контента по всему приложению:
src/App.tsxКопировать кодКопировать код в буфер обмена
import { useState, type FC } from "react"; import reactLogo from "./assets/react.svg"; import viteLogo from "/vite.svg"; import "./App.css"; import { IntlayerProvider, useIntlayer } from "react-intlayer"; const AppContent: FC = () => { const [count, setCount] = useState(0); const content = useIntlayer("app"); return ( <> <div> <a href="https://vitejs.dev" target="_blank"> <img src={viteLogo} className="logo" alt={content.viteLogo.value} /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt={content.reactLogo.value} /> </a> </div> <h1>{content.title}</h1> <div className="card"> <button onClick={() => setCount((count) => count + 1)}> {content.count} {count} </button> <p>{content.edit}</p> </div> <p className="read-the-docs">{content.readTheDocs}</p> </> ); }; const App: FC = () => ( <IntlayerProvider> <AppContent /> </IntlayerProvider> ); export default App;Если вы хотите использовать ваш контент в атрибуте типа
string, таком какalt,title,href,aria-labelи т.д., вы должны вызвать значение функции, например:htmlКопировать кодКопировать код в буфер обмена
<img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />Чтобы узнать больше о хуке
useIntlayer, обратитесь к документации.Если ваше приложение уже существует, вы можете использовать Intlayer Compiler в сочетании с командой extract, чтобы преобразовать тысячи компонентов за одну секунду.
Изменение языка вашего контента
НеобязательноЧтобы изменить язык вашего контента, вы можете использовать функцию
setLocale, предоставляемую хукомuseLocale. Эта функция позволяет установить локаль приложения и обновить контент соответственно.src/components/LocaleSwitcher.tsxКопировать кодКопировать код в буфер обмена
import type { FC } from "react"; import { Locales } from "intlayer"; import { useLocale } from "react-intlayer"; const LocaleSwitcher: FC = () => { const { setLocale } = useLocale(); return ( <button onClick={() => setLocale(Locales.English)}> Change Language to English </button> ); };Чтобы узнать больше о хуке
useLocale, обратитесь к документации.Добавьте локализованную маршрутизацию в ваше приложение
НеобязательноЦель этого шага, создать уникальные маршруты для каждого языка. Это полезно для SEO и SEO-дружественных URL. Пример:
plaintextКопировать кодКопировать код в буфер обмена
- https://example.com/about- https://example.com/es/about- https://example.com/fr/aboutПо умолчанию маршруты не имеют префикса для локали по умолчанию. Если вы хотите добавить префикс для локали по умолчанию, вы можете установить опцию
middleware.prefixDefaultв значениеtrueв вашей конфигурации. Подробнее смотрите в документации по конфигурации.Чтобы добавить локализованную маршрутизацию в ваше приложение, вы можете создать компонент
LocaleRouter, который оборачивает маршруты вашего приложения и обрабатывает маршрутизацию на основе локали. Вот пример с использованием React Router:src/components/LocaleRouter.tsxКопировать кодКопировать код в буфер обмена
import { localeMap } from "intlayer"; // Утилиты и типы из 'intlayer' import type { FC, PropsWithChildren } from "react"; // Типы React для функциональных компонентов и пропсов import { IntlayerProvider } from "react-intlayer"; // Провайдер для контекста интернационализации import { BrowserRouter, Route, Routes } from "react-router-dom"; // Компоненты роутера для управления навигацией /** * Компонент маршрутизатора, который настраивает маршруты для конкретных локалей. * Использует React Router для управления навигацией и рендеринга локализованных компонентов. */ export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => ( <BrowserRouter> <Routes> {localeMap(({ locale, urlPrefix }) => ( <Route // Шаблон маршрута для захвата локали (например, /en/, /fr/) и соответствия всем последующим путям path={`${urlPrefix}/*`} key={locale} element={ <IntlayerProvider locale={locale}>{children}</IntlayerProvider> } // Оборачивает дочерние элементы с управлением локалью /> ))} </Routes> </BrowserRouter> );Примечание: если вы используете
routing.mode: 'no-prefix' | 'search-params', скорее всего, вам не нужно использовать функциюlocaleMap.Затем вы можете использовать компонент
LocaleRouterв вашем приложении:src/App.tsxКопировать кодКопировать код в буфер обмена
import { LocaleRouter } from "./components/LocaleRouter"; import type { FC } from "react"; // ... Ваш компонент AppContent const App: FC = () => ( <LocaleRouter> <AppContent /> </LocaleRouter> );Параллельно вы также можете использовать
intlayerProxyдля добавления маршрутизации на стороне сервера в ваше приложение. Этот плагин автоматически определит текущую локаль на основе URL и установит соответствующее cookie с локалью. Если локаль не указана, плагин определит наиболее подходящую локаль на основе языковых предпочтений браузера пользователя. Если локаль не будет обнаружена, произойдет перенаправление на локаль по умолчанию.Обратите внимание, что для использования
intlayerProxyв продакшене необходимо переместить пакетvite-intlayerизdevDependenciesвdependencies.vite.config.tsКопировать кодКопировать код в буфер обмена
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import { intlayer, intlayerProxy } from "vite-intlayer"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ intlayerProxy(), // should be placed first react(), intlayer(), ], });Изменение URL при смене локали
НеобязательноЧтобы изменить URL при смене локали, вы можете использовать проп
onLocaleChange, предоставляемый хукомuseLocale. Параллельно можно использовать хукиuseLocationиuseNavigateизreact-router-domдля обновления пути URL.src/components/LocaleSwitcher.tsxКопировать кодКопировать код в буфер обмена
import { useLocation, useNavigate } from "react-router-dom"; import { Locales, getHTMLTextDir, getLocaleName, getLocalizedUrl, } from "intlayer"; import { useLocale } from "react-intlayer"; import { type FC } from "react"; const LocaleSwitcher: FC = () => { const { pathname, search } = useLocation(); // Получаем текущий путь URL. Пример: /fr/about?foo=bar const navigate = useNavigate(); const { locale, availableLocales, setLocale } = useLocale({ onLocaleChange: (locale) => { // Формируем URL с обновлённой локалью // Пример: /es/about?foo=bar const pathWithLocale = getLocalizedUrl(`${pathname}${search}`, locale); // Обновляем путь URL navigate(pathWithLocale); }, }); return ( <div> <button popoverTarget="localePopover">{getLocaleName(locale)}</button> <div id="localePopover" popover="auto"> {availableLocales.map((localeItem) => ( <a href={getLocalizedUrl(location.pathname, localeItem)} hrefLang={localeItem} aria-current={locale === localeItem ? "page" : undefined} onClick={(e) => { e.preventDefault(); setLocale(localeItem); }} key={localeItem} > <span> {/* Локаль - например, FR */} {localeItem} </span> <span> {/* Язык на его собственной локали - например, Français */} {getLocaleName(localeItem, locale)} </span> <span dir={getHTMLTextDir(localeItem)} lang={localeItem}> {/* Язык на текущей локали - например, Francés при текущей локали Locales.SPANISH */} {getLocaleName(localeItem)} </span> <span dir="ltr" lang={Locales.ENGLISH}> {/* Язык на английском - например, French */} {getLocaleName(localeItem, Locales.ENGLISH)} </span> </a> ))} </div> </div> ); };Ссылки на документацию:
Ниже приведён обновлённый Шаг 9 с дополнительными объяснениями и уточнёнными примерами кода:
Переключение атрибутов языка и направления в теге HTML
НеобязательноКогда ваше приложение поддерживает несколько языков, крайне важно обновлять атрибуты
langиdirтега<html>, чтобы они соответствовали текущей локали. Это обеспечивает:- Доступность: программы чтения с экрана и вспомогательные технологии полагаются на правильный атрибут
langдля точного произношения и интерпретации контента. - Отображение текста: атрибут
dir(направление) гарантирует, что текст отображается в правильном порядке (например, слева направо для английского, справа налево для арабского или иврита), что важно для удобочитаемости. - SEO: поисковые системы используют атрибут
langдля определения языка вашей страницы, помогая показывать правильный локализованный контент в результатах поиска.
Обновляя эти атрибуты динамически при изменении локали, вы гарантируете последовательный и доступный опыт для пользователей на всех поддерживаемых языках.
Реализация хука
Создайте пользовательский хук для управления атрибутами HTML. Хук отслеживает изменения локали и обновляет атрибуты соответствующим образом:
src/hooks/useI18nHTMLAttributes.tsxКопировать кодКопировать код в буфер обмена
import { useEffect } from "react"; import { useLocale } from "react-intlayer"; import { getHTMLTextDir } from "intlayer"; /** * Обновляет атрибуты `lang` и `dir` элемента <html> в зависимости от текущей локали. * - `lang`: сообщает браузерам и поисковым системам язык страницы. * - `dir`: обеспечивает правильный порядок чтения (например, 'ltr' для английского, 'rtl' для арабского). * * Это динамическое обновление необходимо для правильного отображения текста, доступности и SEO. */ export const useI18nHTMLAttributes = () => { const { locale } = useLocale(); useEffect(() => { // Обновляет атрибут языка на текущую локаль. document.documentElement.lang = locale; // Устанавливает направление текста в зависимости от текущей локали. document.documentElement.dir = getHTMLTextDir(locale); }, [locale]); };Использование хука в вашем приложении
Интегрируйте хук в ваш главный компонент, чтобы атрибуты HTML обновлялись при каждом изменении локали:
src/App.tsxКопировать кодКопировать код в буфер обмена
import type { FC } from "react"; import { IntlayerProvider, useIntlayer } from "react-intlayer"; import { useI18nHTMLAttributes } from "./hooks/useI18nHTMLAttributes"; import "./App.css"; const AppContent: FC = () => { // Применяем хук для обновления атрибутов lang и dir тега <html> в зависимости от локали. useI18nHTMLAttributes(); // ... Остальная часть вашего компонента }; const App: FC = () => ( <IntlayerProvider> <AppContent /> </IntlayerProvider> ); export default App;Применяя эти изменения, ваше приложение будет:
- Обеспечивать корректное отражение текущей локали в атрибуте language (
lang), что важно для SEO и поведения браузера. - Настраивать направление текста (
dir) в соответствии с локалью, улучшая читаемость и удобство использования для языков с разным порядком чтения. - Обеспечивать более доступный опыт, так как вспомогательные технологии зависят от этих атрибутов для оптимальной работы.
- Доступность: программы чтения с экрана и вспомогательные технологии полагаются на правильный атрибут
Создание локализованного компонента Link
НеобязательноЧтобы обеспечить навигацию вашего приложения с учётом текущей локали, вы можете создать пользовательский компонент
Link. Этот компонент автоматически добавляет префикс текущего языка к внутренним URL, например, когда франкоязычный пользователь нажимает на ссылку на страницу "О нас", его перенаправляет на/fr/aboutвместо/about.Такое поведение полезно по нескольким причинам:
- SEO и удобство для пользователя: Локализованные URL помогают поисковым системам правильно индексировать страницы на конкретном языке и предоставлять пользователям контент на предпочитаемом языке.
- Последовательность: Используя локализованную ссылку по всему приложению, вы гарантируете, что навигация остаётся в рамках текущей локали, предотвращая неожиданные переключения языка.
- Поддерживаемость: Централизация логики локализации в одном компоненте упрощает управление URL-адресами, делая ваш код более удобным для поддержки и расширения по мере роста приложения.
Ниже приведена реализация локализованного компонента
Linkна TypeScript:src/components/Link.tsxКопировать кодКопировать код в буфер обмена
import { getLocalizedUrl } from "intlayer"; import { forwardRef, type DetailedHTMLProps, type AnchorHTMLAttributes, } from "react"; import { useLocale } from "react-intlayer"; export interface LinkProps extends DetailedHTMLProps< AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement > {} /** * Вспомогательная функция для проверки, является ли данный URL внешним. * Если URL начинается с http:// или https://, он считается внешним. */ export const checkIsExternalLink = (href?: string): boolean => /^https?:\/\//.test(href ?? ""); /** * Пользовательский компонент Link, который адаптирует атрибут href в зависимости от текущей локали. * Для внутренних ссылок используется `getLocalizedUrl`, чтобы добавить префикс локали к URL (например, /fr/about). * Это гарантирует, что навигация останется в контексте той же локали. */ export const Link = forwardRef<HTMLAnchorElement, LinkProps>( ({ href, children, ...props }, ref) => { const { locale } = useLocale(); const isExternalLink = checkIsExternalLink(href); // Если ссылка внутренняя и href валиден, получить локализованный URL. const hrefI18n = href && !isExternalLink ? getLocalizedUrl(href, locale) : href; return ( <a href={hrefI18n} ref={ref} {...props}> {children} </a> ); } ); Link.displayName = "Link";Как это работает
Определение внешних ссылок:
Вспомогательная функцияcheckIsExternalLinkопределяет, является ли URL внешним. Внешние ссылки остаются без изменений, так как им не требуется локализация.Получение текущей локали:
ХукuseLocaleпредоставляет текущую локаль (например,frдля французского).Локализация URL:
Для внутренних ссылок (то есть не внешних) используетсяgetLocalizedUrl, который автоматически добавляет префикс локали к URL. Это означает, что если пользователь использует французский язык, передача/aboutв качествеhrefпреобразуется в/fr/about.Возврат ссылки:
Компонент возвращает элемент<a>с локализованным URL, обеспечивая согласованную навигацию в соответствии с выбранной локалью.
Интегрируя этот компонент
Linkпо всему вашему приложению, вы поддерживаете последовательный и ориентированный на язык пользовательский опыт, а также получаете преимущества улучшенного SEO и удобства использования.Извлечение содержимого ваших компонентов
НеобязательноЕсли у вас есть существующая кодовая база, преобразование тысяч файлов может занять много времени.
Чтобы упростить этот процесс, Intlayer предлагает компилятор / экстрактор для преобразования ваших компонентов и извлечения содержимого.
Чтобы настроить его, вы можете добавить раздел
compilerв ваш файлintlayer.config.ts:intlayer.config.tsКопировать кодКопировать код в буфер обмена
import { type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { // ... Остальная часть вашей конфигурации compiler: { /** * Указывает, должен ли быть включен компилятор. */ enabled: true, /** * Определяет путь к выходным файлам */ output: ({ fileName, extension }) => `./${fileName}${extension}`, /** * Указывает, должны ли компоненты сохраняться после преобразования. Таким образом, компилятор можно запустить только один раз для преобразования приложения, а затем удалить. */ saveComponents: false, /** * Префикс ключа словаря */ dictionaryKeyPrefix: "", }, }; export default config;Запустите экстрактор для преобразования компонентов и извлечения содержимого
bashКопировать кодКопировать код в буфер обмена
npx intlayer extract
Настройка TypeScript
Intlayer использует расширение модулей (module augmentation), чтобы использовать преимущества TypeScript и сделать вашу кодовую базу более надежной.


Убедитесь, что ваша конфигурация TypeScript включает автоматически сгенерированные типы.
Копировать код в буфер обмена
{ // ... Ваши существующие настройки TypeScript "include": [ // ... Ваши существующие конфигурации TypeScript ".intlayer/**/*.ts", // Включить автоматически сгенерированные типы ],}Конфигурация Git
Рекомендуется игнорировать файлы, сгенерированные Intlayer. Это позволит избежать их коммита в ваш репозиторий Git.
Для этого вы можете добавить следующие инструкции в ваш файл .gitignore:
Копировать код в буфер обмена
.intlayerРасширение VS Code
Для улучшения вашего опыта разработки с Intlayer вы можете установить официальное расширение Intlayer для VS Code.
Установить из магазина расширений VS Code
Это расширение предоставляет:
- Автодополнение для ключей переводов.
- Обнаружение ошибок в реальном времени для отсутствующих переводов.
- Встроенный просмотр переведенного контента.
- Быстрые действия для удобного создания и обновления переводов.
Для получения дополнительной информации о том, как использовать расширение, обратитесь к документации расширения Intlayer для VS Code.
(Опционально) Sitemap и robots.txt (генерация на сборке)
Intlayer предоставляет generateSitemap и getMultilingualUrls - утилиты, которые формируют многоязычные sitemap.xml и robots.txt для краулеров и позволяют автоматически записать их в public/. Обычно запускают небольшой Node-скрипт до Vite (например, npm-хуки predev / prebuild).
Sitemap
Генератор sitemap учитывает локали и добавляет нужные метаданные.
Поддерживается пространство имёнxhtml:link(hreflang). Вместо плоского списка URL Intlayer связывает все языковые версии страницы в обе стороны (например/about,/fr/aboutили/about?lang=frв зависимости от режима маршрутизации).
Robots.txt
Используйте getMultilingualUrls, чтобы правила Disallow покрывали все локализованные варианты путей.
1. Файл generate-seo.mjs в корне проекта
Копировать код в буфер обмена
import fs from "fs";import path from "path";import { fileURLToPath } from "url";import { generateSitemap, getMultilingualUrls } from "intlayer";const __dirname = path.dirname(fileURLToPath(import.meta.url));const SITE_URL = (process.env.SITE_URL || "http://localhost:5173").replace( /\/$/, "");const pathList = [ { path: "/", changefreq: "daily", priority: 1.0 }, { path: "/about", changefreq: "monthly", priority: 0.7 },];const sitemapXml = generateSitemap(pathList, { siteUrl: SITE_URL });fs.writeFileSync(path.join(__dirname, "public", "sitemap.xml"), sitemapXml);const getAllMultilingualUrls = (urls) => urls.flatMap((url) => Object.values(getMultilingualUrls(url)));const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);const robotsTxt = [ "User-agent: *", "Allow: /", ...disallowedPaths.map((path) => `Disallow: ${path}`), "", `Sitemap: ${SITE_URL}/sitemap.xml`,].join("\n");fs.writeFileSync(path.join(__dirname, "public", "robots.txt"), robotsTxt);console.log("SEO files generated successfully.");Пакет intlayer должен быть установлен. Для продакшена задайте SITE_URL в окружении (например в CI).
Для Node ESM предпочтительноgenerate-seo.mjs. Дляgenerate-seo.jsукажите"type": "module"вpackage.jsonили включите ESM иначе.
2. Запуск скрипта до Vite
Копировать код в буфер обмена
{ "scripts": { "dev": "vite", "prebuild": "node generate-seo.mjs", "build": "vite build", "preview": "vite preview" }}Подстройте команды для pnpm или yarn. Скрипт можно вызывать из CI или другого шага.
Продвинутые возможности
Для расширения возможностей вы можете реализовать визуальный редактор или вынести ваш контент во внешний CMS.