未验证 提交 ccb6ce7e 编写于 作者: J JJ Kasper 提交者: GitHub

Add support for getStaticProps in pages/404 (#10984)

* Make sure to not show pages/404 GIP error from _app having GIP

* Add error for getStaticProps in pages/404 too

* Add support for getStaticProps in pages/404

* Update test
上级 9d9f7a58
......@@ -549,12 +549,12 @@ export default async function build(dir: string, conf = null): Promise<void> {
}
if (hasPages404 && page === '/404') {
if (!result.isStatic) {
if (!result.isStatic && !result.hasStaticProps) {
throw new Error(PAGES_404_GET_INITIAL_PROPS_ERROR)
}
// we need to ensure the 404 lambda is present since we use
// it when _app has getInitialProps
if (customAppGetInitialProps) {
if (customAppGetInitialProps && !result.hasStaticProps) {
staticPages.delete(page)
}
}
......
......@@ -30,4 +30,4 @@ export const SERVER_PROPS_GET_INIT_PROPS_CONFLICT = `You can not use getInitialP
export const SERVER_PROPS_SSG_CONFLICT = `You can not use getStaticProps with getServerSideProps. To use SSG, please remove getServerSideProps`
export const PAGES_404_GET_INITIAL_PROPS_ERROR = `\`pages/404\` can not have getInitialProps/getServerSideProps/getStaticProps, https://err.sh/zeit/next.js/404-get-initial-props`
export const PAGES_404_GET_INITIAL_PROPS_ERROR = `\`pages/404\` can not have getInitialProps/getServerSideProps, https://err.sh/zeit/next.js/404-get-initial-props`
......@@ -418,10 +418,7 @@ export async function renderToHTML(
renderOpts.nextExport = true
}
if (
pathname === '/404' &&
(hasPageGetInitialProps || getServerSideProps || isSSG)
) {
if (pathname === '/404' && (hasPageGetInitialProps || getServerSideProps)) {
throw new Error(PAGES_404_GET_INITIAL_PROPS_ERROR)
}
}
......
export const getStaticProps = () => ({
props: { hello: 'world', random: Math.random() },
})
const page = ({ random }) => `custom 404 page ${random}`
export default page
const App = ({ Component, pageProps }) => <Component {...pageProps} />
App.getInitialProps = async ({ Component, ctx }) => {
if (Component.getInitialProps) {
await Component.getInitialProps(ctx)
}
return {
pageProps: {},
}
}
export default App
const page = () => 'err page'
page.getInitialProps = () => {
throw new Error('oops')
}
export default page
export default () => 'hello from index'
/* eslint-env jest */
/* global jasmine */
import fs from 'fs-extra'
import { join } from 'path'
import {
killApp,
findPort,
launchApp,
nextStart,
nextBuild,
renderViaHTTP,
fetchViaHTTP,
} from 'next-test-utils'
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
const appDir = join(__dirname, '../')
const nextConfig = join(appDir, 'next.config.js')
const gip404Err = /`pages\/404` can not have getInitialProps\/getServerSideProps/
let nextConfigContent
let stdout
let stderr
let buildId
let appPort
let app
const runTests = isDev => {
it('should respond to 404 correctly', async () => {
const res = await fetchViaHTTP(appPort, '/404')
expect(res.status).toBe(404)
expect(await res.text()).toContain('custom 404 page')
})
it('should render error correctly', async () => {
const text = await renderViaHTTP(appPort, '/err')
expect(text).toContain(isDev ? 'oops' : 'An unexpected error has occurred')
})
it('should not show an error in the logs for 404 SSG', async () => {
await renderViaHTTP(appPort, '/non-existent')
expect(stderr).not.toMatch(gip404Err)
expect(stdout).not.toMatch(gip404Err)
})
it('should render index page normal', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toContain('hello from index')
})
if (!isDev) {
it('should not revalidate custom 404 page', async () => {
const res1 = await renderViaHTTP(appPort, '/non-existent')
const res2 = await renderViaHTTP(appPort, '/non-existent')
const res3 = await renderViaHTTP(appPort, '/non-existent')
const res4 = await renderViaHTTP(appPort, '/non-existent')
expect(res1 === res2 && res2 === res3 && res3 === res4).toBe(true)
expect(res1).toContain('custom 404 page')
})
it('should set pages404 in routes-manifest correctly', async () => {
const data = await fs.readJSON(join(appDir, '.next/routes-manifest.json'))
expect(data.pages404).toBe(true)
})
it('should have 404 page in prerender-manifest', async () => {
const data = await fs.readJSON(
join(appDir, '.next/prerender-manifest.json')
)
expect(data.routes['/404']).toEqual({
initialRevalidateSeconds: false,
srcRoute: null,
dataRoute: `/_next/data/${buildId}/404.json`,
})
})
}
}
describe('404 Page Support SSG', () => {
describe('server mode', () => {
afterAll(() => killApp(app))
it('should build successfully', async () => {
nextConfigContent = await fs.readFile(nextConfig, 'utf8')
const {
code,
stderr: buildStderr,
stdout: buildStdout,
} = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
})
expect(code).toBe(0)
expect(buildStderr).not.toMatch(gip404Err)
expect(buildStdout).not.toMatch(gip404Err)
appPort = await findPort()
stderr = ''
stdout = ''
app = await nextStart(appDir, appPort, {
onStdout(msg) {
stdout += msg
},
onStderr(msg) {
stderr += msg
},
})
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
runTests()
})
describe('serverless mode', () => {
afterAll(async () => {
await fs.writeFile(nextConfig, nextConfigContent)
await killApp(app)
})
it('should build successfully', async () => {
nextConfigContent = await fs.readFile(nextConfig, 'utf8')
await fs.writeFile(
nextConfig,
`
module.exports = { target: 'experimental-serverless-trace' }
`
)
const {
code,
stderr: buildStderr,
stdout: buildStdout,
} = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
})
expect(code).toBe(0)
expect(buildStderr).not.toMatch(gip404Err)
expect(buildStdout).not.toMatch(gip404Err)
appPort = await findPort()
stderr = ''
stdout = ''
app = await nextStart(appDir, appPort, {
onStdout(msg) {
stdout += msg
},
onStderr(msg) {
stderr += msg
},
})
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
runTests()
})
describe('dev mode', () => {
beforeAll(async () => {
appPort = await findPort()
stderr = ''
stdout = ''
app = await launchApp(appDir, appPort, {
onStdout(msg) {
stdout += msg
},
onStderr(msg) {
stderr += msg
},
})
})
afterAll(() => killApp(app))
runTests(true)
})
})
......@@ -182,7 +182,7 @@ describe('404 Page Support', () => {
expect(stderr).toMatch(gip404Err)
})
it('shows error with getStaticProps in pages/404 build', async () => {
it('does not show error with getStaticProps in pages/404 build', async () => {
await fs.move(pages404, `${pages404}.bak`)
await fs.writeFile(
pages404,
......@@ -196,11 +196,11 @@ describe('404 Page Support', () => {
await fs.remove(pages404)
await fs.move(`${pages404}.bak`, pages404)
expect(stderr).toMatch(gip404Err)
expect(code).toBe(1)
expect(stderr).not.toMatch(gip404Err)
expect(code).toBe(0)
})
it('shows error with getStaticProps in pages/404 dev', async () => {
it('does not show error with getStaticProps in pages/404 dev', async () => {
await fs.move(pages404, `${pages404}.bak`)
await fs.writeFile(
pages404,
......@@ -226,7 +226,7 @@ describe('404 Page Support', () => {
await fs.remove(pages404)
await fs.move(`${pages404}.bak`, pages404)
expect(stderr).toMatch(gip404Err)
expect(stderr).not.toMatch(gip404Err)
})
it('shows error with getServerSideProps in pages/404 build', async () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册