Allow pages to be async modules to enable top-level-await (#17590)
Co-authored-by: JJ Kasper <jj@jjsweb.site> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
parent
5b1be2bb98
commit
9300151118
20 changed files with 339 additions and 36 deletions
|
@ -13,4 +13,5 @@ packages/next-codemod/transforms/__testfixtures__/**/*
|
||||||
packages/next-codemod/transforms/__tests__/**/*
|
packages/next-codemod/transforms/__tests__/**/*
|
||||||
packages/next-codemod/**/*.js
|
packages/next-codemod/**/*.js
|
||||||
packages/next-codemod/**/*.d.ts
|
packages/next-codemod/**/*.d.ts
|
||||||
packages/next-env/**/*.d.ts
|
packages/next-env/**/*.d.ts
|
||||||
|
test/integration/async-modules/**
|
||||||
|
|
1
.github/workflows/build_test_deploy.yml
vendored
1
.github/workflows/build_test_deploy.yml
vendored
|
@ -113,6 +113,7 @@ jobs:
|
||||||
- run: yarn install --check-files
|
- run: yarn install --check-files
|
||||||
- run: node run-tests.js test/integration/production/test/index.test.js
|
- run: node run-tests.js test/integration/production/test/index.test.js
|
||||||
- run: node run-tests.js test/integration/basic/test/index.test.js
|
- run: node run-tests.js test/integration/basic/test/index.test.js
|
||||||
|
- run: node run-tests.js test/integration/async-modules/test/index.test.js
|
||||||
- run: node run-tests.js test/integration/font-optimization/test/index.test.js
|
- run: node run-tests.js test/integration/font-optimization/test/index.test.js
|
||||||
- run: node run-tests.js test/acceptance/*
|
- run: node run-tests.js test/acceptance/*
|
||||||
|
|
||||||
|
|
|
@ -531,7 +531,7 @@ export default async function build(
|
||||||
const serverBundle = getPagePath(page, distDir, isLikeServerless)
|
const serverBundle = getPagePath(page, distDir, isLikeServerless)
|
||||||
|
|
||||||
if (customAppGetInitialProps === undefined) {
|
if (customAppGetInitialProps === undefined) {
|
||||||
customAppGetInitialProps = hasCustomGetInitialProps(
|
customAppGetInitialProps = await hasCustomGetInitialProps(
|
||||||
isLikeServerless
|
isLikeServerless
|
||||||
? serverBundle
|
? serverBundle
|
||||||
: getPagePath('/_app', distDir, isLikeServerless),
|
: getPagePath('/_app', distDir, isLikeServerless),
|
||||||
|
|
|
@ -704,21 +704,21 @@ export async function isPageStatic(
|
||||||
}> {
|
}> {
|
||||||
try {
|
try {
|
||||||
require('../next-server/lib/runtime-config').setConfig(runtimeEnvConfig)
|
require('../next-server/lib/runtime-config').setConfig(runtimeEnvConfig)
|
||||||
const mod = require(serverBundle)
|
const mod = await require(serverBundle)
|
||||||
const Comp = mod.default || mod
|
const Comp = await (mod.default || mod)
|
||||||
|
|
||||||
if (!Comp || !isValidElementType(Comp) || typeof Comp === 'string') {
|
if (!Comp || !isValidElementType(Comp) || typeof Comp === 'string') {
|
||||||
throw new Error('INVALID_DEFAULT_EXPORT')
|
throw new Error('INVALID_DEFAULT_EXPORT')
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasGetInitialProps = !!(Comp as any).getInitialProps
|
const hasGetInitialProps = !!(Comp as any).getInitialProps
|
||||||
const hasStaticProps = !!mod.getStaticProps
|
const hasStaticProps = !!(await mod.getStaticProps)
|
||||||
const hasStaticPaths = !!mod.getStaticPaths
|
const hasStaticPaths = !!(await mod.getStaticPaths)
|
||||||
const hasServerProps = !!mod.getServerSideProps
|
const hasServerProps = !!(await mod.getServerSideProps)
|
||||||
const hasLegacyServerProps = !!mod.unstable_getServerProps
|
const hasLegacyServerProps = !!(await mod.unstable_getServerProps)
|
||||||
const hasLegacyStaticProps = !!mod.unstable_getStaticProps
|
const hasLegacyStaticProps = !!(await mod.unstable_getStaticProps)
|
||||||
const hasLegacyStaticPaths = !!mod.unstable_getStaticPaths
|
const hasLegacyStaticPaths = !!(await mod.unstable_getStaticPaths)
|
||||||
const hasLegacyStaticParams = !!mod.unstable_getStaticParams
|
const hasLegacyStaticParams = !!(await mod.unstable_getStaticParams)
|
||||||
|
|
||||||
if (hasLegacyStaticParams) {
|
if (hasLegacyStaticParams) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -804,19 +804,20 @@ export async function isPageStatic(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasCustomGetInitialProps(
|
export async function hasCustomGetInitialProps(
|
||||||
bundle: string,
|
bundle: string,
|
||||||
runtimeEnvConfig: any,
|
runtimeEnvConfig: any,
|
||||||
checkingApp: boolean
|
checkingApp: boolean
|
||||||
): boolean {
|
): Promise<boolean> {
|
||||||
require('../next-server/lib/runtime-config').setConfig(runtimeEnvConfig)
|
require('../next-server/lib/runtime-config').setConfig(runtimeEnvConfig)
|
||||||
let mod = require(bundle)
|
let mod = require(bundle)
|
||||||
|
|
||||||
if (checkingApp) {
|
if (checkingApp) {
|
||||||
mod = mod._app || mod.default || mod
|
mod = (await mod._app) || mod.default || mod
|
||||||
} else {
|
} else {
|
||||||
mod = mod.default || mod
|
mod = mod.default || mod
|
||||||
}
|
}
|
||||||
|
mod = await mod
|
||||||
return mod.getInitialProps !== mod.origGetInitialProps
|
return mod.getInitialProps !== mod.origGetInitialProps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -339,7 +339,7 @@ const nextServerlessLoader: loader.Loader = function () {
|
||||||
: `{}`
|
: `{}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolver = require('${absolutePagePath}')
|
const resolver = await require('${absolutePagePath}')
|
||||||
await apiResolver(
|
await apiResolver(
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
|
@ -386,35 +386,57 @@ const nextServerlessLoader: loader.Loader = function () {
|
||||||
const {sendPayload} = require('next/dist/next-server/server/send-payload');
|
const {sendPayload} = require('next/dist/next-server/server/send-payload');
|
||||||
const buildManifest = require('${buildManifest}');
|
const buildManifest = require('${buildManifest}');
|
||||||
const reactLoadableManifest = require('${reactLoadableManifest}');
|
const reactLoadableManifest = require('${reactLoadableManifest}');
|
||||||
const Document = require('${absoluteDocumentPath}').default;
|
|
||||||
const Error = require('${absoluteErrorPath}').default;
|
const appMod = require('${absoluteAppPath}')
|
||||||
const App = require('${absoluteAppPath}').default;
|
let App = appMod.default || appMod.then && appMod.then(mod => mod.default);
|
||||||
|
|
||||||
${dynamicRouteImports}
|
${dynamicRouteImports}
|
||||||
${rewriteImports}
|
${rewriteImports}
|
||||||
|
|
||||||
const ComponentInfo = require('${absolutePagePath}')
|
const compMod = require('${absolutePagePath}')
|
||||||
|
|
||||||
const Component = ComponentInfo.default
|
let Component = compMod.default || compMod.then && compMod.then(mod => mod.default)
|
||||||
export default Component
|
export default Component
|
||||||
export const unstable_getStaticParams = ComponentInfo['unstable_getStaticParam' + 's']
|
export let getStaticProps = compMod['getStaticProp' + 's'] || compMod.then && compMod.then(mod => mod['getStaticProp' + 's'])
|
||||||
export const getStaticProps = ComponentInfo['getStaticProp' + 's']
|
export let getStaticPaths = compMod['getStaticPath' + 's'] || compMod.then && compMod.then(mod => mod['getStaticPath' + 's'])
|
||||||
export const getStaticPaths = ComponentInfo['getStaticPath' + 's']
|
export let getServerSideProps = compMod['getServerSideProp' + 's'] || compMod.then && compMod.then(mod => mod['getServerSideProp' + 's'])
|
||||||
export const getServerSideProps = ComponentInfo['getServerSideProp' + 's']
|
|
||||||
|
|
||||||
// kept for detecting legacy exports
|
// kept for detecting legacy exports
|
||||||
export const unstable_getStaticProps = ComponentInfo['unstable_getStaticProp' + 's']
|
export const unstable_getStaticParams = compMod['unstable_getStaticParam' + 's'] || compMod.then && compMod.then(mod => mod['unstable_getStaticParam' + 's'])
|
||||||
export const unstable_getStaticPaths = ComponentInfo['unstable_getStaticPath' + 's']
|
export const unstable_getStaticProps = compMod['unstable_getStaticProp' + 's'] || compMod.then && compMod.then(mod => mod['unstable_getStaticProp' + 's'])
|
||||||
export const unstable_getServerProps = ComponentInfo['unstable_getServerProp' + 's']
|
export const unstable_getStaticPaths = compMod['unstable_getStaticPath' + 's'] || compMod.then && compMod.then(mod => mod['unstable_getStaticPath' + 's'])
|
||||||
|
export const unstable_getServerProps = compMod['unstable_getServerProp' + 's'] || compMod.then && compMod.then(mod => mod['unstable_getServerProp' + 's'])
|
||||||
|
|
||||||
${dynamicRouteMatcher}
|
${dynamicRouteMatcher}
|
||||||
${defaultRouteRegex}
|
${defaultRouteRegex}
|
||||||
${normalizeDynamicRouteParams}
|
${normalizeDynamicRouteParams}
|
||||||
${handleRewrites}
|
${handleRewrites}
|
||||||
|
|
||||||
export const config = ComponentInfo['confi' + 'g'] || {}
|
export let config = compMod['confi' + 'g'] || (compMod.then && compMod.then(mod => mod['confi' + 'g'])) || {}
|
||||||
export const _app = App
|
export const _app = App
|
||||||
export async function renderReqToHTML(req, res, renderMode, _renderOpts, _params) {
|
export async function renderReqToHTML(req, res, renderMode, _renderOpts, _params) {
|
||||||
|
let Document
|
||||||
|
let Error
|
||||||
|
;[
|
||||||
|
getStaticProps,
|
||||||
|
getServerSideProps,
|
||||||
|
getStaticPaths,
|
||||||
|
Component,
|
||||||
|
App,
|
||||||
|
config,
|
||||||
|
{ default: Document },
|
||||||
|
{ default: Error }
|
||||||
|
] = await Promise.all([
|
||||||
|
getStaticProps,
|
||||||
|
getServerSideProps,
|
||||||
|
getStaticPaths,
|
||||||
|
Component,
|
||||||
|
App,
|
||||||
|
config,
|
||||||
|
require('${absoluteDocumentPath}'),
|
||||||
|
require('${absoluteErrorPath}')
|
||||||
|
])
|
||||||
|
|
||||||
const fromExport = renderMode === 'export' || renderMode === true;
|
const fromExport = renderMode === 'export' || renderMode === true;
|
||||||
const nextStartMode = renderMode === 'passthrough'
|
const nextStartMode = renderMode === 'passthrough'
|
||||||
|
|
||||||
|
|
|
@ -340,9 +340,9 @@ export default class PageLoader {
|
||||||
|
|
||||||
// This method if called by the route code.
|
// This method if called by the route code.
|
||||||
registerPage(route: string, regFn: () => any) {
|
registerPage(route: string, regFn: () => any) {
|
||||||
const register = (styleSheets: StyleSheetTuple[]) => {
|
const register = async (styleSheets: StyleSheetTuple[]) => {
|
||||||
try {
|
try {
|
||||||
const mod = regFn()
|
const mod = await regFn()
|
||||||
const pageData: PageCacheEntry = {
|
const pageData: PageCacheEntry = {
|
||||||
page: mod.default || mod,
|
page: mod.default || mod,
|
||||||
mod,
|
mod,
|
||||||
|
|
|
@ -41,20 +41,27 @@ export async function loadComponents(
|
||||||
): Promise<LoadComponentsReturnType> {
|
): Promise<LoadComponentsReturnType> {
|
||||||
if (serverless) {
|
if (serverless) {
|
||||||
const Component = await requirePage(pathname, distDir, serverless)
|
const Component = await requirePage(pathname, distDir, serverless)
|
||||||
const { getStaticProps, getStaticPaths, getServerSideProps } = Component
|
let { getStaticProps, getStaticPaths, getServerSideProps } = Component
|
||||||
|
|
||||||
|
getStaticProps = await getStaticProps
|
||||||
|
getStaticPaths = await getStaticPaths
|
||||||
|
getServerSideProps = await getServerSideProps
|
||||||
|
const pageConfig = (await Component.config) || {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Component,
|
Component,
|
||||||
pageConfig: Component.config || {},
|
pageConfig,
|
||||||
getStaticProps,
|
getStaticProps,
|
||||||
getStaticPaths,
|
getStaticPaths,
|
||||||
getServerSideProps,
|
getServerSideProps,
|
||||||
} as LoadComponentsReturnType
|
} as LoadComponentsReturnType
|
||||||
}
|
}
|
||||||
|
|
||||||
const DocumentMod = requirePage('/_document', distDir, serverless)
|
const [DocumentMod, AppMod, ComponentMod] = await Promise.all([
|
||||||
const AppMod = requirePage('/_app', distDir, serverless)
|
requirePage('/_document', distDir, serverless),
|
||||||
const ComponentMod = requirePage(pathname, distDir, serverless)
|
requirePage('/_app', distDir, serverless),
|
||||||
|
requirePage(pathname, distDir, serverless),
|
||||||
|
])
|
||||||
|
|
||||||
const [
|
const [
|
||||||
buildManifest,
|
buildManifest,
|
||||||
|
|
|
@ -866,7 +866,7 @@ export default class Server {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageModule = require(builtPagePath)
|
const pageModule = await require(builtPagePath)
|
||||||
query = { ...query, ...params }
|
query = { ...query, ...params }
|
||||||
|
|
||||||
if (!this.renderOpts.dev && this._isLikeServerless) {
|
if (!this.renderOpts.dev && this._isLikeServerless) {
|
||||||
|
|
9
test/integration/async-modules/next.config.js
Normal file
9
test/integration/async-modules/next.config.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = {
|
||||||
|
// target: 'experimental-serverless-trace',
|
||||||
|
webpack: (config, options) => {
|
||||||
|
config.experiments = {
|
||||||
|
topLevelAwait: true,
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
}
|
5
test/integration/async-modules/pages/404.jsx
Normal file
5
test/integration/async-modules/pages/404.jsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const content = await Promise.resolve("hi y'all")
|
||||||
|
|
||||||
|
export default function Custom404() {
|
||||||
|
return <h1 id="content-404">{content}</h1>
|
||||||
|
}
|
5
test/integration/async-modules/pages/_app.jsx
Normal file
5
test/integration/async-modules/pages/_app.jsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const appValue = await Promise.resolve('hello')
|
||||||
|
|
||||||
|
export default function MyApp({ Component, pageProps }) {
|
||||||
|
return <Component {...pageProps} appValue={appValue} />
|
||||||
|
}
|
25
test/integration/async-modules/pages/_document.jsx
Normal file
25
test/integration/async-modules/pages/_document.jsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
const docValue = await Promise.resolve('doc value')
|
||||||
|
|
||||||
|
class MyDocument extends Document {
|
||||||
|
static async getInitialProps(ctx) {
|
||||||
|
const initialProps = await Document.getInitialProps(ctx)
|
||||||
|
return { ...initialProps, docValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Html>
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<div id="doc-value">{this.props.docValue}</div>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyDocument
|
7
test/integration/async-modules/pages/_error.jsx
Normal file
7
test/integration/async-modules/pages/_error.jsx
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
const errorContent = await Promise.resolve('hello error')
|
||||||
|
|
||||||
|
function Error({ statusCode }) {
|
||||||
|
return <p id="content-error">{errorContent}</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Error
|
5
test/integration/async-modules/pages/api/hello.js
Normal file
5
test/integration/async-modules/pages/api/hello.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const value = await Promise.resolve(42)
|
||||||
|
|
||||||
|
export default function (req, res) {
|
||||||
|
res.json({ value })
|
||||||
|
}
|
22
test/integration/async-modules/pages/config.jsx
Normal file
22
test/integration/async-modules/pages/config.jsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
export const config = {
|
||||||
|
amp: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.resolve('tadaa')
|
||||||
|
|
||||||
|
export default function Config() {
|
||||||
|
const date = new Date()
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<amp-timeago
|
||||||
|
id="amp-timeago"
|
||||||
|
width="0"
|
||||||
|
height="15"
|
||||||
|
datetime={date.toJSON()}
|
||||||
|
layout="responsive"
|
||||||
|
>
|
||||||
|
fail
|
||||||
|
</amp-timeago>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
15
test/integration/async-modules/pages/gsp.jsx
Normal file
15
test/integration/async-modules/pages/gsp.jsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
const gspValue = await Promise.resolve(42)
|
||||||
|
|
||||||
|
export async function getStaticProps() {
|
||||||
|
return {
|
||||||
|
props: { gspValue },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Index({ gspValue }) {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<div id="gsp-value">{gspValue}</div>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
15
test/integration/async-modules/pages/gssp.jsx
Normal file
15
test/integration/async-modules/pages/gssp.jsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
const gsspValue = await Promise.resolve(42)
|
||||||
|
|
||||||
|
export async function getServerSideProps() {
|
||||||
|
return {
|
||||||
|
props: { gsspValue },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Index({ gsspValue }) {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<div id="gssp-value">{gsspValue}</div>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
10
test/integration/async-modules/pages/index.jsx
Normal file
10
test/integration/async-modules/pages/index.jsx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const value = await Promise.resolve(42)
|
||||||
|
|
||||||
|
export default function Index({ appValue }) {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<div id="app-value">{appValue}</div>
|
||||||
|
<div id="page-value">{value}</div>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
7
test/integration/async-modules/pages/make-error.jsx
Normal file
7
test/integration/async-modules/pages/make-error.jsx
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export async function getServerSideProps() {
|
||||||
|
throw new Error('BOOM')
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return <div>hello</div>
|
||||||
|
}
|
146
test/integration/async-modules/test/index.test.js
Normal file
146
test/integration/async-modules/test/index.test.js
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/* eslint-env jest */
|
||||||
|
|
||||||
|
import webdriver from 'next-webdriver'
|
||||||
|
|
||||||
|
import cheerio from 'cheerio'
|
||||||
|
import {
|
||||||
|
fetchViaHTTP,
|
||||||
|
renderViaHTTP,
|
||||||
|
findPort,
|
||||||
|
killApp,
|
||||||
|
launchApp,
|
||||||
|
nextBuild,
|
||||||
|
nextStart,
|
||||||
|
File,
|
||||||
|
} from 'next-test-utils'
|
||||||
|
import { join } from 'path'
|
||||||
|
import webpack from 'webpack'
|
||||||
|
|
||||||
|
jest.setTimeout(1000 * 60 * 2)
|
||||||
|
|
||||||
|
const isWebpack5 = parseInt(webpack.version) === 5
|
||||||
|
let app
|
||||||
|
let appPort
|
||||||
|
const appDir = join(__dirname, '../')
|
||||||
|
const nextConfig = new File(join(appDir, 'next.config.js'))
|
||||||
|
|
||||||
|
function runTests(dev = false) {
|
||||||
|
it('ssr async page modules', async () => {
|
||||||
|
const html = await renderViaHTTP(appPort, '/')
|
||||||
|
const $ = cheerio.load(html)
|
||||||
|
expect($('#app-value').text()).toBe('hello')
|
||||||
|
expect($('#page-value').text()).toBe('42')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('csr async page modules', async () => {
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
browser = await webdriver(appPort, '/')
|
||||||
|
expect(await browser.elementByCss('#app-value').text()).toBe('hello')
|
||||||
|
expect(await browser.elementByCss('#page-value').text()).toBe('42')
|
||||||
|
expect(await browser.elementByCss('#doc-value').text()).toBe('doc value')
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works on async api routes', async () => {
|
||||||
|
const res = await fetchViaHTTP(appPort, '/api/hello')
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
const result = await res.json()
|
||||||
|
expect(result).toHaveProperty('value', 42)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works with getServerSideProps', async () => {
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
browser = await webdriver(appPort, '/gssp')
|
||||||
|
expect(await browser.elementByCss('#gssp-value').text()).toBe('42')
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works with getStaticProps', async () => {
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
browser = await webdriver(appPort, '/gsp')
|
||||||
|
expect(await browser.elementByCss('#gsp-value').text()).toBe('42')
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can render async 404 pages', async () => {
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
browser = await webdriver(appPort, '/dhiuhefoiahjeoij')
|
||||||
|
expect(await browser.elementByCss('#content-404').text()).toBe("hi y'all")
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can render async AMP pages', async () => {
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
browser = await webdriver(appPort, '/config')
|
||||||
|
expect(await browser.elementByCss('#amp-timeago').text()).not.toBe('fail')
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
;(dev ? it.skip : it)('can render async error page', async () => {
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
browser = await webdriver(appPort, '/make-error')
|
||||||
|
expect(await browser.elementByCss('#content-error').text()).toBe(
|
||||||
|
'hello error'
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
if (browser) await browser.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
;(isWebpack5 ? describe : describe.skip)('Async modules', () => {
|
||||||
|
describe('dev mode', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
appPort = await findPort()
|
||||||
|
app = await launchApp(appDir, appPort)
|
||||||
|
})
|
||||||
|
afterAll(async () => {
|
||||||
|
await killApp(app)
|
||||||
|
})
|
||||||
|
|
||||||
|
runTests(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('production mode', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await nextBuild(appDir)
|
||||||
|
appPort = await findPort()
|
||||||
|
app = await nextStart(appDir, appPort)
|
||||||
|
})
|
||||||
|
afterAll(async () => {
|
||||||
|
await killApp(app)
|
||||||
|
})
|
||||||
|
|
||||||
|
runTests()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('serverless mode', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
nextConfig.replace('// target:', 'target:')
|
||||||
|
await nextBuild(appDir)
|
||||||
|
appPort = await findPort()
|
||||||
|
app = await nextStart(appDir, appPort)
|
||||||
|
})
|
||||||
|
afterAll(async () => {
|
||||||
|
await nextConfig.restore()
|
||||||
|
await killApp(app)
|
||||||
|
})
|
||||||
|
|
||||||
|
runTests()
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue