未验证 提交 2ab300dd 编写于 作者: J Joe Haddad 提交者: GitHub

Remove Old Prerender Implementation (#8218)

* Remove Prerender Implementation

* Fix PageConfig

* Fix next server

* Fix two more files

* Fix render

* Fix render

* Try to fix up page config

* Correct build file

* Switch back static checker

* Turn stuff back

* Add missing newline

* Revert changes

* Add missing newline

* Fix types
上级 6468b6c9
......@@ -402,10 +402,6 @@ export default class Router implements BaseRouter {
return new Promise((resolve, reject) => {
const ctx = { pathname, query, asPath: as }
this.getInitialProps(Component, ctx).then(props => {
// if data is inlined during prerender it is a string
if (props && typeof props.pageProps === 'string') {
props.pageProps = JSON.parse(props.pageProps)
}
routeInfo.props = props
this.components[route] = routeInfo
resolve(routeInfo)
......
......@@ -148,8 +148,6 @@ type RenderOpts = {
App: AppType
ErrorDebug?: React.ComponentType<{ error: Error }>
ampValidator?: (html: string, pathname: string) => Promise<void>
isPrerender?: boolean
pageData?: any
}
function renderDocument(
......@@ -257,7 +255,7 @@ export async function renderToHTML(
} = renderOpts
await Loadable.preloadAll() // Make sure all dynamic imports are loaded
let isStaticPage = Boolean(pageConfig.experimentalPrerender)
let isStaticPage = false
if (dev) {
const { isValidElementType } = require('react-is')
......@@ -501,10 +499,6 @@ export async function renderToHTML(
// update renderOpts so export knows current state
renderOpts.inAmpMode = inAmpMode
renderOpts.hybridAmp = hybridAmp
renderOpts.pageData = props && props.pageProps
renderOpts.isPrerender =
pageConfig.experimentalPrerender === true ||
pageConfig.experimentalPrerender === 'inline'
let html = renderDocument(Document, {
...renderOpts,
......
......@@ -10,5 +10,4 @@ export type PageConfig = {
*/
bodyParser?: { sizeLimit?: number | string } | false
}
experimentalPrerender?: boolean | 'inline' | 'legacy'
}
......@@ -3,8 +3,7 @@ import { NodePath } from '@babel/traverse'
import * as BabelTypes from '@babel/types'
import { PageConfig } from 'next-server/types'
const configKeys = new Set(['amp', 'experimentalPrerender'])
export const inlineGipIdentifier = '__NEXT_GIP_INLINE__'
const configKeys = new Set(['amp'])
export const dropBundleIdentifier = '__NEXT_DROP_CLIENT_FILE__'
// replace progam path with just a variable with the drop identifier
......@@ -29,7 +28,6 @@ function replaceBundle(path: any, t: typeof BabelTypes) {
}
interface ConfigState {
setupInlining?: boolean
bundleDropped?: boolean
}
......@@ -86,55 +84,12 @@ export default function nextPageConfig({
state.bundleDropped = true
return
}
if (
config.experimentalPrerender === true ||
config.experimentalPrerender === 'inline'
) {
state.setupInlining = true
}
},
},
state
)
},
},
// handles Page.getInitialProps = () => {}
AssignmentExpression(path, state: ConfigState) {
if (!state.setupInlining) return
const { property } = (path.node.left || {}) as any
const { name } = property
if (name !== 'getInitialProps') return
// replace the getInitialProps function with an identifier for replacing
path.node.right = t.functionExpression(
null,
[],
t.blockStatement([
t.returnStatement(t.stringLiteral(inlineGipIdentifier)),
])
)
},
// handles class { static async getInitialProps() {} }
FunctionDeclaration(path, state: ConfigState) {
if (!state.setupInlining) return
if ((path.node.id && path.node.id.name) !== 'getInitialProps') return
path.node.body = t.blockStatement([
t.returnStatement(t.stringLiteral(inlineGipIdentifier)),
])
},
// handles class { static async getInitialProps() {} }
ClassMethod(path, state: ConfigState) {
if (!state.setupInlining) return
if (
(path.node.key && (path.node.key as BabelTypes.Identifier).name) !==
'getInitialProps'
)
return
path.node.body = t.blockStatement([
t.returnStatement(t.stringLiteral(inlineGipIdentifier)),
])
},
},
}
}
......@@ -361,10 +361,7 @@ export default async function build(dir: string, conf = null): Promise<void> {
})
staticCheckSema.release()
if (
(result.static && customAppGetInitialProps === false) ||
result.prerender
) {
if (result.static && customAppGetInitialProps === false) {
staticPages.add(page)
isStatic = true
}
......
......@@ -265,7 +265,7 @@ export async function getPageSizeInKb(
export function isPageStatic(
serverBundle: string,
runtimeEnvConfig: any
): { static?: boolean; prerender?: boolean } {
): { static?: boolean } {
try {
require('next-server/config').setConfig(runtimeEnvConfig)
const mod = require(serverBundle)
......@@ -277,7 +277,6 @@ export function isPageStatic(
return {
static: typeof (Comp as any).getInitialProps !== 'function',
prerender: mod.config && mod.config.experimentalPrerender,
}
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') return {}
......
......@@ -2,11 +2,10 @@ import mkdirpModule from 'mkdirp'
import { promisify } from 'util'
import { extname, join, dirname, sep } from 'path'
import { renderToHTML } from 'next-server/dist/server/render'
import { writeFile, access, readFile } from 'fs'
import { writeFile, access } from 'fs'
import { Sema } from 'async-sema'
import AmpHtmlValidator from 'amphtml-validator'
import { loadComponents } from 'next-server/dist/server/load-components'
import { inlineGipIdentifier } from '../build/babel/plugins/next-page-config'
import { isDynamicRoute } from 'next-server/dist/lib/router/utils/is-dynamic'
import { getRouteMatcher } from 'next-server/dist/lib/router/utils/route-matcher'
import { getRouteRegex } from 'next-server/dist/lib/router/utils/route-regex'
......@@ -14,7 +13,6 @@ import { getRouteRegex } from 'next-server/dist/lib/router/utils/route-regex'
const envConfig = require('next-server/config')
const mkdirp = promisify(mkdirpModule)
const writeFileP = promisify(writeFile)
const readFileP = promisify(readFile)
const accessP = promisify(access)
global.__NEXT_DATA__ = {
......@@ -127,32 +125,6 @@ process.on(
}
}
// inline pageData for getInitialProps
if (curRenderOpts.isPrerender && curRenderOpts.pageData) {
const dataStr = JSON.stringify(curRenderOpts.pageData)
.replace(/"/g, '\\"')
.replace(/'/g, "\\'")
for (const bundleExt of [
'.js',
renderOpts.isModern && '.module.js'
].filter(Boolean)) {
const bundlePath = join(
distDir,
'static',
buildId,
'pages',
(path === '/' ? 'index' : path) + bundleExt
)
const bundleContent = await readFileP(bundlePath, 'utf8')
await writeFileP(
bundlePath,
bundleContent.replace(inlineGipIdentifier, dataStr)
)
}
}
const validateAmp = async (html, page) => {
const validator = await AmpHtmlValidator.getInstance()
const result = validator.validateString(html)
......
module.exports = {
experimental: {
autoExport: true
}
}
const Page = ({ name }) => <p>Prerender page {name}</p>
Page.getInitialProps = async () => ({ name: 'John Deux' })
export const config = { experimentalPrerender: true }
export default Page
export default () => <p>An autoExported page</p>
export const config = { experimentalPrerender: true }
const Page = ({ title }) => <p>{title}</p>
Page.getInitialProps = async () => ({ title: 'something' })
export default Page
const Page = () => <p>I'm just an old SSR page</p>
Page.getInitialProps = () => ({})
export default Page
const Page = () => <p>I'm just an old SSR page</p>
Page.getInitialProps = () => ({})
export default Page
/* eslint-env jest */
/* global jasmine */
import fs from 'fs-extra'
import path from 'path'
import {
nextBuild,
nextStart,
findPort,
killApp,
renderViaHTTP
} from 'next-test-utils'
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 3
const appDir = path.join(__dirname, '../')
let buildId
let appPort
let app
describe('Prerendering pages', () => {
beforeAll(async () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
buildId = (
(await fs.readFile(path.join(appDir, '.next/BUILD_ID'), 'utf8')) || ''
).trim()
})
afterAll(() => killApp(app))
it('should render the correct files', async () => {
let files = ['nested/hello', 'another', 'index']
for (const file of files) {
expect(
await fs.exists(
path.join(
appDir,
'.next/server/static',
buildId,
'pages',
file + '.html'
)
)
).toBe(true)
}
files = ['nested/old-school', 'old-school']
for (const file of files) {
expect(
await fs.exists(
path.join(
appDir,
'.next/server/static',
buildId,
'pages',
file + '.js'
)
)
).toBe(true)
}
})
it('should have called getInitialProps during prerender', async () => {
const hello = await renderViaHTTP(appPort, '/nested/hello')
expect(hello).toMatch(/something/)
const another = await renderViaHTTP(appPort, '/another')
expect(another).toMatch(/John Deux/)
})
it('should call getInitialProps for SSR pages', async () => {
const oldSchool1 = await renderViaHTTP(appPort, '/old-school')
expect(oldSchool1).toMatch(/I.*?m just an old SSR page/)
const oldSchool2 = await renderViaHTTP(appPort, '/nested/old-school')
expect(oldSchool2).toMatch(/I.*?m just an old SSR page/)
})
it('should autoExport correctly', async () => {
const index = await renderViaHTTP(appPort, '/')
expect(index).toMatch(/An autoExported page/)
})
})
import Link from 'next/link'
export const config = {
experimentalPrerender: 'inline'
}
const Page = ({ data }) => {
return (
<>
<h3>{data}</h3>
<Link href='/to-something'>
<a id='to-something'>Click to to-something</a>
</Link>
</>
)
}
Page.getInitialProps = async () => {
if (typeof window !== 'undefined') {
throw new Error(`this shouldn't be called`)
}
return {
data: 'this is some data to be inlined!!!'
}
}
export default Page
import React from 'react'
import Link from 'next/link'
export const config = {
experimentalPrerender: true
}
class Page extends React.Component {
static async getInitialProps () {
if (typeof window !== 'undefined') {
throw new Error(`this shouldn't be called`)
}
return {
title: 'some interesting title'
}
}
render () {
return (
<>
<h3>{this.props.title}</h3>
<Link href='/something'>
<a id='something'>Click to something</a>
</Link>
</>
)
}
}
export default Page
......@@ -546,26 +546,6 @@ describe('Production Usage', () => {
}
})
it('should prerender pages with data correctly', async () => {
const toSomething = await renderViaHTTP(appPort, '/to-something')
expect(toSomething).toMatch(/some interesting title/)
const something = await renderViaHTTP(appPort, '/something')
expect(something).toMatch(/this is some data to be inlined/)
})
it('should have inlined the data correctly in prerender', async () => {
const browser = await webdriver(appPort, '/to-something')
await browser.elementByCss('#something').click()
let text = await browser.elementByCss('h3').text()
expect(text).toMatch(/this is some data to be inlined/)
await browser.elementByCss('#to-something').click()
text = await browser.elementByCss('h3').text()
expect(text).toMatch(/some interesting title/)
})
it('should handle AMP correctly in IE', async () => {
const browser = await webdriver(appPort, '/some-amp')
await waitFor(1000)
......
import Link from 'next/link'
export const config = {
experimentalPrerender: 'inline'
}
const Page = ({ data }) => {
return (
<>
<h3>{data}</h3>
<Link href='/to-something'>
<a id='to-something'>Click to to-something</a>
</Link>
</>
)
}
Page.getInitialProps = async () => {
if (typeof window !== 'undefined') {
throw new Error(`this shouldn't be called`)
}
return {
data: 'this is some data to be inlined!!!'
}
}
export default Page
import React from 'react'
import Link from 'next/link'
export const config = {
experimentalPrerender: true
}
class Page extends React.Component {
static async getInitialProps () {
if (typeof window !== 'undefined') {
throw new Error(`this shouldn't be called`)
}
return {
title: 'some interesting title'
}
}
render () {
return (
<>
<h3>{this.props.title}</h3>
<Link href='/something'>
<a id='something'>Click to something</a>
</Link>
</>
)
}
}
export default Page
......@@ -114,26 +114,6 @@ describe('Serverless', () => {
}
})
it('should prerender pages with data correctly', async () => {
const toSomething = await renderViaHTTP(appPort, '/to-something')
expect(toSomething).toMatch(/some interesting title/)
const something = await renderViaHTTP(appPort, '/something')
expect(something).toMatch(/this is some data to be inlined/)
})
it('should have inlined the data correctly in prerender', async () => {
const browser = await webdriver(appPort, '/to-something')
await browser.elementByCss('#something').click()
let text = await browser.elementByCss('h3').text()
expect(text).toMatch(/this is some data to be inlined/)
await browser.elementByCss('#to-something').click()
text = await browser.elementByCss('h3').text()
expect(text).toMatch(/some interesting title/)
})
it('should reply on API request successfully', async () => {
const content = await renderViaHTTP(appPort, '/api/hello')
expect(content).toMatch(/hello world/)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册