NextJS/Django Ручной ввод URL-адресов
Я пытаюсь создать приложение, которое использует Django на бэкенде и NextJS на фронтэнде.
Я установил это, статически экспортируя приложение NextJS, затем приложение Django обрабатывает маршрутизацию и использует index.html как ловушку для всех маршрутов, которые оно не знает.
Это работает относительно хорошо, однако я столкнулся с проблемой маршрутизации в NextJS, и я не уверен, откуда именно это происходит. Хотя моя маршрутизация на стороне клиента работает нормально (т.е. компоненты Link работают, как ожидалось), она ничего не делает, если я делаю это, вводя URL.
Моя структура каталогов выглядит следующим образом:
...
- pages
- _app.tsx
- index.tsx
- login.tsx
...
Следовательно, я должен ожидать, что /login будет перенаправлять на страницу входа, и снова это работает, как ожидалось, в теге Link, однако когда я вручную ввожу localhost:8000/login/, он просто перенаправляет на index.tsx.
Некоторые другие потенциально значимые файлы:
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/styles/*": ["styles/*"],
"@/components/*": ["components/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
images: {
loader: "akamai",
path: "/",
},
}
У меня есть ощущение, что это происходит потому, что файлы рендерятся на стороне клиента, а не на стороне сервера, но я не видел ничего, что указывало бы на то, что это неизбежный побочный эффект. Для этого я пробовал использовать getStaticPaths и getStaticProps, но ни то, ни другое не работает, как ожидалось. Я даже пробовал использовать свойство redirects, но ничего.
Я действительно в тупике, почему это не работает, и я не могу найти никакой информации об этом - опять же, это наводит меня на мысль, что это просто то, как NextJS работает для CSR, но я действительно не могу поверить, что это так.
Заранее спасибо!
Так что я еще не до конца разобрался с этим, но после более тщательного исследования проблема, похоже, на стороне NextJS, а не Django.
"Реальное" решение - начать использовать NextJS через команду next start, а не статический экспорт. Опять же, основываясь на документации, мне кажется, что это не тот случай, но после перехода на него и получения его для работы с Django все работает как ожидалось.
Однако это не всегда возможно сделать, поэтому, если вы должны использовать статический экспорт, я добавил следующее к моему pages/_app.tsx, чтобы получить функциональные URL:
const router = useRouter()
useEffect(() => {
try {
// get pathname and location
let pathname = router.pathname
let location = window.location.pathname
// ensure paths have trailing '/'
const lastLocation = location.charAt(location.length - 1);
if (lastLocation != '/') {
location = `${location}/`
}
const lastPath = pathname.charAt(pathname.length - 1);
if (lastPath != '/') {
pathname = `${pathname}/`
}
// redirect to page in actual url
if (pathname != location) {
router.replace(location).then((success) => {
if (!success) {
const newPath = '/404'
window.location.pathname = newPath
let res = router.replace(newPath)
}
})
}
} catch (e) {
console.error(e)
}
})
Вам также необходимо trailingSlash: true, вписать next.config.js.
Не могу сказать, что я поклонник этого "хака", но, похоже, он работает так, как ожидалось, но я не могу представить, что это "самый правильный" ответ. Однако это полностью исправляет ручной ввод URL, а также любую другую маршрутизацию CSR, т.е. a tags.