NextJs:通过动态路由进行静态导出

时间:2020-08-31 14:59:45

标签: next.js netlify

我对文档有些困惑,不确定是否可以尝试做。

目标:

  • 静态导出NextJS应用并将其托管在netlify上
  • 允许用户创建帖子,并具有指向这些帖子的链接

例如:

  • 用户创建一个ID为2的新帖子
  • 该帖子应该可以在mysite.com/posts/2下公开访问

我想我可以创建一个名为posts.html的框架html文件,然后netlify将所有posts/<id>的请求重定向到该posts.html文件,然后将显示该框架并加载必要的数据通过运行中的API。

我认为,如果没有这种netlify技巧,那么根据documentation,next.js不可能实现静态导出+动态链接到动态路由的目标,因为fallback: true仅在使用SSR时才是可能的。 / p>

问题:如何实现我的梦想,即静态nextjs导出+到动态路由的有效链接的设置?

编辑: 我刚刚发现了Redirects。它们可以解决我的问题。

1 个答案:

答案 0 :(得分:3)

如果您要创建静态网站,则需要在next export之前提前查询帖子。

以下是您可能已在博客文章中设置的使用Contentful的示例:

首先在pages/blog/[post].js下创建一个页面。

下一步可以在exportMap内使用next.config.js

// next.config.js
const contentful = require('contentful');

// Connects to Contentful
const contentfulClient = async () => {
  const client = await contentful.createClient({
    space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID,
    accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN,
  });
  return client;
};

// Gets all of the blog posts
const getBlogPostEntries = async (client) => {
  const entries = await client.getEntries({
    content_type: 'blogPost',
    order: 'fields.date',
  });
  return entries;
};

module.exports = {
  async exportPathMap() {
    const routes = {
      '/': { page: '/' }, // Index page
      '/blog/index': { page: '/blog' }, // Blog page
    };

    const client = await contentfulClient();
    const posts = await getBlogPostEntries(client);

    // See explanation below
    posts.items.forEach((item) => {
      routes[`/blog/${item.fields.route}`] = { page: '/blog/[post]' };
    });

    return routes;
  },
};

就在return routes;以上,我正在连接到Contentful,并获取所有博客文章。在这种情况下,每个帖子都有一个我定义的值,称为route。我给每条内容都提供了一个路由值,例如this-is-my-first-postjust-started-blogging。最后,路由对象看起来像这样:

routes = {
  '/': { page: '/' }, // Index page
  '/blog/index': { page: '/blog' }, // Blog page
  '/blog/this-is-my-first-post': { page: '/blog/[post]' },
  '/blog/just-started-blogging': { page: '/blog/[post]' },
};

您在out/目录中的导出将是:

out/
   /index.html
   /blog/index.html
   /blog/this-is-my-first-post.html
   /blog/just-started-blogging.html

以您为例,如果您使用的是帖子ID号,则必须获取博客帖子,然后执行以下操作:

const posts = await getAllPosts();

posts.forEach((post) => {
  routes[`/blog/${post.id}`] = { page: '/blog/[post]' };
});

// Routes end up like
// routes = {
//   '/': { page: '/' }, // Index page
//   '/blog/index': { page: '/blog' }, // Blog page
//   '/blog/1': { page: '/blog/[post]' },
//   '/blog/2': { page: '/blog/[post]' },
// };

下一步是在Netlify上创建某种挂钩,以在用户创建内容时触发静态网站构建。

这也是您pages/blog/[post].js的外观的想法。

import Head from 'next/head';

export async function getBlogPostContent(route) {
  const post = await client.getEntries({
    content_type: 'blogPost',
    'fields.route': route,
  });
  return post;
}

const Post = (props) => {
  const { title, content } = props;
  return (
    <>
      <Head>
        <title>{title}</title>
      </Head>
      {content}
    </>
  );
};

Post.getInitialProps = async ({ asPath }) => {
  // asPath is something like `/blog/this-is-my-first-post`
  const pageContent = await getBlogPostContent(asPath.replace('/blog/', ''));
  const { items } = pageContent;
  const { title, content } = items[0].fields;
  return { title, content };
};

export default Post;