在nextjs上首次加载动态路由时出现404

6qfn3psc  于 2023-05-17  发布在  其他
关注(0)|答案(5)|浏览(515)

我试图创建一个博客页面来测试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的一个限制吗(在文档中没有找到任何与之相关的东西),或者我们需要配置其他东西吗?

gblwokeq

gblwokeq1#

真实的的问题是导出next应用程序将使其生成静态HTML文件。尽管它仍然能够在呈现页面之前请求数据,但可用路径集不是动态的(它们是在next export命令期间生成的)。看这个docs和这个example
基于此,我有两种可能的解决方案:

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

toe950272#

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

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

希望这对你有帮助。

whhtz7ly

whhtz7ly3#

为了扩展@Minoru提供的答案,官方Next文档在此example中涵盖了这种情况。
使用getStaticPathsgetStaticProps允许您在构建时创建动态页面,避免404。
posts动态页面的示例代码:

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 && next export构建站点时,我们将在out文件夹中看到Next创建了每个帖子页面

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

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

r1zhe5dt

r1zhe5dt4#

我不想违反任何旧的posts规则,但如果其他人在我的上下文中,我使用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));
        });
})
fbcarpbf

fbcarpbf5#

2023更新

添加cleanUrls:true到“firebase.json”文件如下

{
  "hosting": {
    "public": "out",
    "ignore": ["firebase.json","**/.*","**/node_modules/**"],
    "cleanUrls": true,
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

相关问题