Skip to content

Commit

Permalink
Add paths field for unstable_getStaticPaths (#10454)
Browse files Browse the repository at this point in the history
* Add paths field for unstable_getStaticPaths

* Make sure to specify page in getStaticPaths errors
  • Loading branch information
ijjk authored Feb 8, 2020
1 parent 0183a13 commit f6e7a38
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 33 deletions.
37 changes: 31 additions & 6 deletions packages/next/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { recursiveReadDir } from '../lib/recursive-readdir'
import { getRouteMatcher, getRouteRegex } from '../next-server/lib/router/utils'
import { isDynamicRoute } from '../next-server/lib/router/utils/is-dynamic'
import { findPageFile } from '../server/lib/find-page-file'
import { Unstable_getStaticPaths } from '../next-server/server/load-components'

const fileGzipStats: { [k: string]: Promise<number> } = {}
const fsStatGzip = (file: string) => {
Expand Down Expand Up @@ -559,9 +560,35 @@ export async function isPageStatic(
// Get the default list of allowed params.
const _validParamKeys = Object.keys(_routeMatcher(page))

const toPrerender: Array<
{ params?: { [key: string]: string } } | string
> = await mod.unstable_getStaticPaths()
const staticPathsResult = await (mod.unstable_getStaticPaths as Unstable_getStaticPaths)()

if (!staticPathsResult || typeof staticPathsResult !== 'object') {
throw new Error(
`Invalid value returned from unstable_getStaticPaths in ${page}. Received ${typeof staticPathsResult} Expected: { paths: [] }`
)
}

const invalidStaticPathKeys = Object.keys(staticPathsResult).filter(
key => key !== 'paths'
)

if (invalidStaticPathKeys.length > 0) {
throw new Error(
`Extra keys returned from unstable_getStaticPaths in ${page} (${invalidStaticPathKeys.join(
', '
)}) The only field allowed currently is \`paths\``
)
}

const toPrerender = staticPathsResult.paths

if (!Array.isArray(toPrerender)) {
throw new Error(
`Invalid \`paths\` value returned from unstable_getStaticProps in ${page}.\n` +
`\`paths\` must be an array of strings or objects of shape { params: [key: string]: string }`
)
}

toPrerender.forEach(entry => {
// For a string-provided path, we must make sure it matches the dynamic
// route.
Expand Down Expand Up @@ -594,9 +621,7 @@ export async function isPageStatic(
let builtPage = page
_validParamKeys.forEach(validParamKey => {
const { repeat } = _routeRegex.groups[validParamKey]
const paramValue: string | string[] = params[validParamKey] as
| string
| string[]
const paramValue = params[validParamKey]
if (
(repeat && !Array.isArray(paramValue)) ||
(!repeat && typeof paramValue !== 'string')
Expand Down
4 changes: 3 additions & 1 deletion packages/next/next-server/server/load-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ type Unstable_getStaticProps = (params: {
revalidate?: number | boolean
}>

type Unstable_getStaticPaths = () => Promise<Array<string | ParsedUrlQuery>>
export type Unstable_getStaticPaths = () => Promise<{
paths: Array<string | { params: ParsedUrlQuery }>
}>

type Unstable_getServerProps = (context: {
params: ParsedUrlQuery | undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export async function unstable_getStaticPaths() {
return ['/hello', '/world']
return { paths: ['/hello', '/world'] }
}

export default () => <p>something is missing 🤔</p>
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ export function unstable_getStaticProps({ params }) {
}

export function unstable_getStaticPaths() {
return [
`/p1/p2/predefined-ssg/one-level`,
`/p1/p2/predefined-ssg/1st-level/2nd-level`,
]
return {
paths: [
`/p1/p2/predefined-ssg/one-level`,
`/p1/p2/predefined-ssg/1st-level/2nd-level`,
],
}
}

export default All
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'

// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
return [{ params: { slug: 'hello' } }]
return { paths: [{ params: { slug: 'hello' } }] }
}

// eslint-disable-next-line camelcase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'

// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
return [{ foo: 'bad', baz: 'herro' }]
return { paths: [{ foo: 'bad', baz: 'herro' }] }
}

// eslint-disable-next-line camelcase
Expand Down
10 changes: 6 additions & 4 deletions test/integration/prerender/pages/blog/[post]/[comment].js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import Link from 'next/link'

// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
return [
'/blog/post-1/comment-1',
{ params: { post: 'post-2', comment: 'comment-2' } },
]
return {
paths: [
'/blog/post-1/comment-1',
{ params: { post: 'post-2', comment: 'comment-2' } },
],
}
}

// eslint-disable-next-line camelcase
Expand Down
18 changes: 10 additions & 8 deletions test/integration/prerender/pages/blog/[post]/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { useRouter } from 'next/router'

// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
return [
'/blog/post-1',
{ params: { post: 'post-2' } },
'/blog/[post3]',
'/blog/post-4',
'/blog/post.1',
'/blog/post.1', // handle duplicates
]
return {
paths: [
'/blog/post-1',
{ params: { post: 'post-2' } },
'/blog/[post3]',
'/blog/post-4',
'/blog/post.1',
'/blog/post.1', // handle duplicates
],
}
}

// eslint-disable-next-line camelcase
Expand Down
14 changes: 8 additions & 6 deletions test/integration/prerender/pages/catchall/[...slug].js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ export async function unstable_getStaticProps({ params: { slug } }) {
}

export async function unstable_getStaticPaths() {
return [
{ params: { slug: ['first'] } },
'/catchall/second',
{ params: { slug: ['another', 'value'] } },
'/catchall/hello/another',
]
return {
paths: [
{ params: { slug: ['first'] } },
'/catchall/second',
{ params: { slug: ['another', 'value'] } },
'/catchall/hello/another',
],
}
}

export default ({ slug }) => <p id="catchall">Hi {slug?.join('/')}</p>
2 changes: 1 addition & 1 deletion test/integration/prerender/pages/user/[user]/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Link from 'next/link'

// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
return []
return { paths: [] }
}

// eslint-disable-next-line camelcase
Expand Down

0 comments on commit f6e7a38

Please sign in to comment.