【问题标题】:Getting 404 when first loading dynamic routes on nextjs首次在 nextjs 上加载动态路由时出现 404
【发布时间】:2020-05-21 19:12:56
【问题描述】:

我正在尝试创建一个博客页面来测试nextjs,并为帖子创建了一条动态路由,该路由将从 Contentful 中检索。从主页导航并单击next/router<Link /> 组件时,博客文章加载正确,但如果我获取 URL 并尝试直接从浏览器地址栏加载页面,我会得到 404。

重现步骤:

 1. git clone https://github.com/zeit/next-learn-demo.git
 2. cd next-learn-demo/8-deploying
 3. yarn
 4. next build && next export
 5. cd out
 6. serve
 7. Navigate to http://localhost:5000/p/learn-nextjs
 8. See 404

这是 NextJS 的限制(在文档中没有找到与它相关的任何内容)还是我们需要配置其他任何东西?

【问题讨论】:

    标签: reactjs next.js


    【解决方案1】:

    真正的问题是导出next 应用程序会使其生成静态HTML 文件。尽管它仍然能够在呈现页面之前请求数据,但可用路径集不是动态的(它们是在next export 命令期间生成的)。请参阅此docs 和此example

    基于此,我有两种可能的解决方案:

    • 每次在 Contentful 中发布新博文时,都会生成一个 webhook 以触发 next build && next export 命令;
    • 避免导出我的 next 应用程序并托管将处理动态路由的 Node 服务器。

    【讨论】:

      【解决方案2】:

      那是因为当您直接访问链接或刷新页面时,它会在路径末尾添加一个斜杠。 next.js 无法识别任何类似的路线。为了解决这个问题,我希望应该有一个最简单的方法来做到这一点。但是,您可以使用custom server 执行此操作。这是一个例子:

      server.get("/about/", (req, res) => {
        return app.render(req, res, "/about")
      });
      

      希望这会对你有所帮助。

      【讨论】:

      • 谢谢!你的回答帮助我理解了这个问题。我会回答这个问题,以便任何有这个问题的人都清楚。
      【解决方案3】:

      为了扩展@Minoru 提供的答案,Next 官方文档在example 中介绍了这种情况。

      使用 getStaticPathsgetStaticProps 允许您在构建时创建动态页面,避免 404。

      帖子动态页面的示例代码:

      import { GetStaticPaths, GetStaticProps } from 'next';
      
      const Post = ({ post }) => {
          const { id, content } = post;
      
          return (
              <div>
                  <h1>Post {id}</h1>
                  <p>{content}</p>
              </div>
          );
      };
      
      export const getStaticPaths: GetStaticPaths = async () => {
          // Get all posts via API, file, etc.
          const posts = [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }, { id: '5' }]; // Example
          const paths = posts.map(post => ({
              params: { id: post.id },
          }));
          return { paths, fallback: false };
      };
      
      export const getStaticProps: GetStaticProps = async context => {
          const postId = context.params?.id || '';
          // Get post detail via API, file, etc.
          const post = { id: postId, content: `I'm the post with id ${postId}!` }; // Example
          return { props: { post } };
      };
      
      export default Post;
      

      使用next build &amp;&amp; next export 构建网站时,我们将在out 文件夹中看到 Next 创建了每个帖子页面

      然后,当您导航到 /posts/3/ 时,您将看到 id 为 3 的帖子

      作为参考,此docs 页面包含此案例和许多其他用例。

      【讨论】:

      • 如果我们有一个动态路由文件,比如 users -> edit -> [id] 并且该编辑页面正在通过下一个路由器呈现,路径如下 localhost:3000/users/edit/[id] 那么我认为正确的方法是使用 getStaticPaths 是这样的export const getStaticPaths = () =&gt; ({ paths: ['/users/edit/[id]'], fallback: true, });。但是在构建 nextjs 应用程序时出现构建错误,这是对我的线程 stackoverflow.com/questions/67624322/… 的引用
      【解决方案4】:

      不想违反任何旧帖子规则,但如果我上下文中的任何其他人使用 vercel 的功能 webhook 来进行新部署,并且在使用 firebase 时,我创建了一个简单的 firebase function 与页面的新事件创建会触发 webhook。我使用 fetch 是因为我们可以根据docs 发出 GET 请求

      exports.newEventAdded = functions.region('us-central1').firestore.document('local_events/{localeventId}')
      .onCreate((snap, context) => {
          fetch('https://api.vercel.com/v1/integrations/deploy/process.env.NEXT_PUBLIC_VERCEL_WEBHOOK_ID')
              .then(function (response) {
                  return response.json();
              })
              .then(function (myJson) {
                  console.log(JSON.stringify(myJson));
              });
      })
      

      【讨论】:

        猜你喜欢
        • 2023-03-03
        • 2020-06-20
        • 2020-09-04
        • 1970-01-01
        • 1970-01-01
        • 2021-10-12
        • 2020-12-16
        • 2020-12-19
        • 2022-08-10
        相关资源
        最近更新 更多