next.js 静态路由和动态路由

11 min read

Next.js 提供了两种路由支持,静态路由与动态路由

静态路由

静态路由通过文件规范来约定,pages目录下的js文件都认为是路由(每个静态路由对应一个页面文件),例如:

pages/index.js → /
pages/blog/index.js → /blog
pages/blog/first-post.js → /blog/first-post
pages/dashboard/settings/username.js → /dashboard/settings/username

动态路由

类似的,动态路由也要在pages目录下创建文件,只是文件名有些不同寻常:

// 类似于springmvc的的路由参数,获取路由变量
pages/blog/[slug].js → /blog/:slug (/blog/hello-world)

// 动态参数可以是任意位置
pages/[username]/settings.js → /:username/settings (/foo/settings)

// 不定量的动态参数
pages/post/[...all].js → /post/* (/post/2020/id/title)

路径中变化的参数通过getStaticPaths来填充

注意下面是的形式是next.js约定好的

// pages/posts/[id].js
export async function getStaticPaths() {
  return {
    // 必须叫paths,值必须是数组
    paths: [{
      // 每一项必须是这个形式
      params: {
        // 必须含有id
        id: 'ssg-ssr'
      }
    },{
      params: {
        id: 'pre-rendering'
      }
    }],
    fallback: false
  }
}

进一步传递给getStaticProps按参数获取数据,并渲染页面:

// pages/posts/[id].js
export async function getStaticProps({ params }) {
  // 根据路由参数获取相应数据
  const postData = await getPostData(params.id)
  return {
    props: {
      postData
    }
  }
}

// 渲染页面
export default function Post({ postData }) {
  return (
    <Layout>
      <Head>
        <title>{postData.title}</title>
      </Head>
      <article>
        <h1 className={utilStyles.headingXl}>{postData.title}</h1>
        <div className={utilStyles.lightText}>
          <Date dateString={postData.date} />
        </div>
        <div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
      </article>
    </Layout>
  )
}

可以理解为先创建一个工厂 page(例如pages/[路由参数1]/[路由参数2].js),接着getStaticPaths填充路由参数,getStaticProps({ params })根据参数请求不同数据,最后数据进入页面组件开始预渲染