Исправление React Router на GitHub Pages: Полное руководство
Решение проблем с React Router при развертывании на GitHub Pages. Узнайте, как настроить basename, создать перенаправления 404 и использовать HashRouter для правильной маршрутизации на стороне клиента.
Почему моя конфигурация React Router работает на localhost, но не на GitHub Pages?
Я настроил React-приложение с использованием React Router, и оно работает идеально при запуске на локальном сервере разработки. Однако после развертывания на GitHub Pages маршрутизация работает некорректно. Вот моя текущая конфигурация роутера:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import './App.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import NavbarEffect from './Components/navbar';
import Home from './Page/home';
import Services from "./Page/services";
import Project from "./Page/project";
import Contact from "./Page/contact";
import Notfound from "./Page/notfound";
import About from "./Page/about";
function App() {
const navLinks = [
{ name: "Home", href: "/" },
{ name: "About", href: "/about" },
{ name: "Services", href: "/services" },
{ name: "Projects", href: "/project" },
{ name: "Contact", href: "/contact" },
];
return (
<BrowserRouter>
<NavbarEffect links={navLinks} />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About/>}/>
<Route path="/project" element={<Project />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<Notfound />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Что может быть причиной этой проблемы, и как я могу исправить свою конфигурацию React Router, чтобы она корректно работала на GitHub Pages?
Проблема возникает из-за того, что React Router использует клиентскую маршрутизацию, в то время как GitHub Pages рассматривает ваше приложение как статический файловый сервер. При переходе на маршрут, такой как /about на GitHub Pages, сервер ищет фактический файл /about, а не обслуживает ваш index.html и не позволяет React Router обрабатывать маршрутизацию.
Чтобы исправить это, необходимо правильно настроить как React Router, так и GitHub Pages для совместной работы. Вот ключевые решения:
Содержание
- Понимание основной причины
- Решение 1: Использование basename в BrowserRouter
- Решение 2: Создание файла перенаправления 404
- Решение 3: Альтернатива с HashRouter
- Решение 4: Конфигурация развертывания на GitHub Pages
- Полная реализация решения
- Тестирование развертывания
Понимание основной причины
Когда вы запускаете свое React-приложение локально, сервер разработки настроен на обработку любого URL путем постоянного обслуживания index.html и предоставления React Router возможности обрабатывать маршрутизацию. Однако GitHub Pages - это сервис статического хостинга, который обслуживает файлы на основе их фактических путей в репозитории.
Когда пользователь посещает https://yourusername.github.io/yourrepo/about на GitHub Pages, сервер ищет файл по пути /about в вашем репозитории. Поскольку у вас нет физических файлов для каждого маршрута, он возвращает страницу ошибки 404 вместо файла index.html вашего React-приложения.
Решение 1: Использование basename в BrowserRouter
Первым шагом является настройка вашего BrowserRouter для работы со структурой URL GitHub Pages.
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
const navLinks = [
{ name: "Главная", href: "/" },
{ name: "О нас", href: "/about" },
{ name: "Услуги", href: "/services" },
{ name: "Проекты", href: "/project" },
{ name: "Контакты", href: "/contact" },
];
return (
<BrowserRouter basename="/your-repo-name">
<NavbarEffect links={navLinks} />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/project" element={<Project />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<Notfound />} />
</Routes>
</BrowserRouter>
);
}
Свойство basename сообщает React Router, что все маршруты должны иметь префикс с именем вашего репозитория, что соответствует структуре URL GitHub Pages.
Решение 2: Создание файла перенаправления 404
Создайте файл 404.html в папке public вашего React-проекта со следующим содержанием:
<!DOCTYPE html>
<html>
<head>
<title>Страница не найдена</title>
<script>
// Перенаправление на главную страницу
window.location.href = "/your-repo-name/";
</script>
</head>
<body>
<h1>Страница не найдена</h1>
<p>Страница, которую вы ищете, не существует.</p>
</body>
</html>
Этот файл перенаправляет все запросы 404 обратно в ваше основное приложение, позволяя React Router обрабатывать маршрутизацию.
Решение 3: Альтернатива с HashRouter
Если приведенные выше решения не работают, вы можете переключиться с BrowserRouter на HashRouter, который использует хеш URL для маршрутизации и лучше работает со статическим хостингом:
import { HashRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<HashRouter>
<NavbarEffect links={navLinks} />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/project" element={<Project />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<Notfound />} />
</Routes>
</HashRouter>
);
}
HashRouter создает URL вида https://yourusername.github.io/yourrepo/#/about, которые обрабатываются полностью на стороне клиента, избегая проблем с серверной маршрутизацией.
Решение 4: Конфигурация развертывания на GitHub Pages
Убедитесь, что ваше развертывание на GitHub Pages правильно настроено. Создайте или обновите ваш package.json с правильным скриптом развертывания:
{
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
}
Установите пакет gh-pages:
npm install gh-pages --save-dev
Эта настройка гарантирует, что ваш сборка будет развернута в ветку gh-pages, которую GitHub Pages использует для обслуживания вашего сайта.
Полная реализация решения
Вот полное решение, объединяющее несколько подходов:
- Обновите ваш App.js:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import './App.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import NavbarEffect from './Components/navbar';
import Home from './Page/home';
import Services from "./Page/services";
import Project from "./Page/project";
import Contact from "./Page/contact";
import Notfound from "./Page/notfound";
import About from "./Page/about";
function App() {
const navLinks = [
{ name: "Главная", href: "/" },
{ name: "О нас", href: "/about" },
{ name: "Услуги", href: "/services" },
{ name: "Проекты", href: "/project" },
{ name: "Контакты", href: "/contact" },
];
return (
<BrowserRouter basename="/your-repo-name">
<NavbarEffect links={navLinks} />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/project" element={<Project />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<Notfound />} />
</Routes>
</BrowserRouter>
);
}
export default App;
- Создайте файл 404.html в вашей папке
public:
<!DOCTYPE html>
<html>
<head>
<title>Страница не найдена</title>
<script>
// Перенаправление на главную страницу
window.location.href = "/your-repo-name/";
</script>
</head>
<body>
<h1>Страница не найдена</h1>
<p>Страница, которую вы ищете, не существует.</p>
</body>
</html>
- Обновите ваш package.json:
{
"name": "your-app-name",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.8.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
},
"devDependencies": {
"gh-pages": "^4.0.0",
"react-scripts": "5.0.1"
},
"homepage": "https://yourusername.github.io/your-repo-name"
}
Тестирование развертывания
После реализации этих решений:
- Запустите
npm run buildдля создания производственной сборки - Запустите
npm run deployдля развертывания на GitHub Pages - Протестируйте все ваши маршруты:
/,/about,/services,/project,/contact - Протестируйте обновление каждой страницы, чтобы убедиться, что она загружается правильно
- Протестируйте прямой переход по URL, чтобы убедиться, что они работают
Если вы по-прежнему сталкиваетесь с проблемами, вы также можете попробовать использовать пользовательский файл public/index.html для обеспечения правильной маршрутизации:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Описание вашего приложения" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<title>Ваше приложение</title>
</head>
<body>
<noscript>Вам необходимо включить JavaScript для запуска этого приложения.</noscript>
<div id="root"></div>
</body>
</html>
Этот комплексный подход должен решить проблемы маршрутизации при развертывании вашего React Router приложения на GitHub Pages.
Источники
- Документация React Router - BrowserRouter
- Документация GitHub Pages - О GitHub Pages
- Документация Create React App - Развертывание
Заключение
Проблемы с маршрутизацией, которые вы испытываете с React Router на GitHub Pages, являются распространенными, но решаемыми. Ключевые решения включают:
- Настройку basename в BrowserRouter для соответствия структуре URL вашего репозитория GitHub Pages
- Создание файла перенаправления 404.html для обработки ошибок серверной маршрутизации
- Использование HashRouter в качестве альтернативы, если BrowserRouter продолжает вызывать проблемы
- Правильную конфигурацию развертывания в package.json для обеспечения правильных процессов сборки и развертывания
Реализовав эти решения, ваше React Router приложение будет работать бесшовно как на localhost, так и на GitHub Pages. Не забудьте заменить "your-repo-name" на фактическое имя вашего репозитория во всех конфигурациях. Комбинация клиентской маршрутизации с правильными механизмами отката на стороне сервера обеспечивает плавный пользовательский опыт независимо от того, как пользователи перемещаются по вашему приложению.