NextJS/Django 手动输入 URL

NextJS/Django Manually Typing in URLs

我正在尝试设置一个在后端使用 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: "/",
    },
}

我觉得这是因为文件是客户端呈现的,而不是服务器端,但我没有看到任何迹象表明这是不可避免的副作用。为此,我尝试使用 exportPathMapgetStaticPathsgetStaticProps,但 none 似乎按预期工作。我什至尝试了 redirects 属性 但什么也没有。

我真的很困惑为什么这不起作用而且我真的找不到任何关于它的信息 - 它再次让我相信这就是 NextJS 为 CSR 工作的方式,但我真的不敢相信那是案.

提前致谢!

编辑:django 路由信息如下:

urls.py

urlpatterns += [
    # APIS =============================== #
    path("api/", include("api.urls")),
    # ADMIN ============================== #
    path("admin/", admin.site.urls),
    # NEXTJS ============================= #
    re_path('^.*$', TemplateView.as_view(template_name="index.html")),
]

views.py

front_end_view = TemplateView.as_view(template_name="index.html")

我的前端在 client 文件夹中,我将 client/out 列为 staticfiles_dir。

所以我还没有完全弄清楚这一点,但经过更多调查后,问题似乎出在 NextJS 方面而不是 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.

不能说我喜欢这个答案,但它似乎按预期工作,但我无法想象这是 'most correct' 答案。然而,这确实完全修复了手动输入 URL 以及任何其他 CSR 路由,即 a 标签。

如果其他人遇到类似问题,希望这对您有所帮助!