未验证 提交 6c2ce706 编写于 作者: T Tim Neutkens 提交者: GitHub

Remove buildId from server-side files (#14413)

Gets rid of the custom function for naming files by removing buildId from the file paths.
上级 a7af0133
......@@ -101,7 +101,7 @@ export function createEntrypoints(
const isApiRoute = page.match(API_ROUTE)
const clientBundlePath = join('static', 'pages', bundleFile)
const serverBundlePath = join('static', 'BUILD_ID', 'pages', bundleFile)
const serverBundlePath = join('pages', bundleFile)
const isLikeServerless = isTargetLikeServerless(target)
......@@ -111,7 +111,7 @@ export function createEntrypoints(
absolutePagePath,
...defaultServerlessOptions,
}
server[join('pages', bundleFile)] = `next-serverless-loader?${stringify(
server[serverBundlePath] = `next-serverless-loader?${stringify(
serverlessLoaderOptions
)}!`
} else if (isApiRoute || target === 'server') {
......@@ -122,7 +122,7 @@ export function createEntrypoints(
absolutePagePath,
...defaultServerlessOptions,
}
server[join('pages', bundleFile)] = `next-serverless-loader?${stringify(
server[serverBundlePath] = `next-serverless-loader?${stringify(
serverlessLoaderOptions
)}!`
}
......
......@@ -679,24 +679,8 @@ export default async function getBaseWebpackConfig(
},
output: {
path: outputPath,
filename: isServer
? ({ chunk }: { chunk: { name: string } }) => {
// Use `[name]-[contenthash].js` in production
if (chunk.name.includes('BUILD_ID')) {
return (
escapePathVariables(chunk.name).replace(
'BUILD_ID',
isServer || dev ? buildId : '[contenthash]'
) + '.js'
)
}
return '[name].js'
}
: // Client compilation only
dev
? '[name].js'
: '[name]-[chunkhash].js',
// On the server we don't use the chunkhash
filename: dev || isServer ? '[name].js' : '[name]-[chunkhash].js',
libraryTarget: isServer ? 'commonjs2' : 'var',
hotUpdateChunkFilename: isWebpack5
? 'static/webpack/[id].[fullhash].hot-update.js'
......
......@@ -41,6 +41,7 @@ import { loadEnvConfig } from '../lib/load-env-config'
import { PrerenderManifest } from '../build'
import type exportPage from './worker'
import { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin'
import { getPagePath } from '../next-server/server/require'
const exists = promisify(existsOrig)
......@@ -157,14 +158,6 @@ export default async function exportApp(
prerenderManifest = require(join(distDir, PRERENDER_MANIFEST))
} catch (_) {}
const distPagesDir = join(
distDir,
isLikeServerless
? SERVERLESS_DIRECTORY
: join(SERVER_DIRECTORY, 'static', buildId),
'pages'
)
const excludedPrerenderRoutes = new Set<string>()
const pages = options.pages || Object.keys(pagesManifest)
const defaultPathMap: ExportPathMap = {}
......@@ -425,7 +418,21 @@ export default async function exportApp(
if (!options.buildExport && prerenderManifest) {
await Promise.all(
Object.keys(prerenderManifest.routes).map(async (route) => {
const { srcRoute } = prerenderManifest!.routes[route]
const pageName = srcRoute || route
const pagePath = getPagePath(pageName, distDir, isLikeServerless)
const distPagesDir = join(
pagePath,
// strip leading / and then recurse number of nested dirs
// to place from base folder
pageName
.substr(1)
.split('/')
.map(() => '..')
.join('/')
)
route = normalizePagePath(route)
const orig = join(distPagesDir, route)
const htmlDest = join(
outDir,
......
import { denormalizePagePath } from './normalize-page-path'
// matches static/<buildid>/pages/:page*.js
const ROUTE_NAME_REGEX = /^static[/\\][^/\\]+[/\\]pages[/\\](.*)$/
// const SERVER_ROUTE_NAME_REGEX = /^static[/\\][^/\\]+[/\\]pages[/\\](.*)$/
// matches pages/:page*.js
const SERVERLESS_ROUTE_NAME_REGEX = /^pages[/\\](.*)$/
const SERVER_ROUTE_NAME_REGEX = /^pages[/\\](.*)$/
// matches static/pages/:page*.js
const BROWSER_ROUTE_NAME_REGEX = /^static[/\\]pages[/\\](.*)$/
......@@ -19,12 +19,10 @@ function matchBundle(regex: RegExp, input: string): string | null {
export default function getRouteFromEntrypoint(
entryFile: string,
isServerlessLike: boolean = false
// TODO: Remove this parameter
_isServerlessLike: boolean = false
): string | null {
let pagePath = matchBundle(
isServerlessLike ? SERVERLESS_ROUTE_NAME_REGEX : ROUTE_NAME_REGEX,
entryFile
)
let pagePath = matchBundle(SERVER_ROUTE_NAME_REGEX, entryFile)
if (pagePath) {
return pagePath
......
......@@ -220,9 +220,7 @@ export default class Server {
distDir: this.distDir,
pagesDir: join(
this.distDir,
this._isLikeServerless
? SERVERLESS_DIRECTORY
: `${SERVER_DIRECTORY}/static/${this.buildId}`,
this._isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY,
'pages'
),
flushToDisk: this.nextConfig.experimental.sprFlushToDisk,
......
......@@ -380,7 +380,7 @@ export default class HotReloader {
// We only watch `_document` for changes on the server compilation
// the rest of the files will be triggered by the client compilation
const documentChunk = compilation.chunks.find(
(c) => c.name === normalize(`static/BUILD_ID/pages/_document`)
(c) => c.name === normalize(`pages/_document`)
)
// If the document chunk can't be found we do nothing
if (!documentChunk) {
......
......@@ -228,7 +228,7 @@ export default function onDemandEntryHandler(
pageUrl = pageUrl === '' ? '/' : pageUrl
const bundleFile = normalizePagePath(pageUrl)
const serverBundlePath = join('static', 'BUILD_ID', 'pages', bundleFile)
const serverBundlePath = join('pages', bundleFile)
const clientBundlePath = join('static', 'pages', bundleFile)
const absolutePagePath = pagePath.startsWith('next/dist/pages')
? require.resolve(pagePath)
......
const page = (props) => {
return <h1 id="404-title">{props.extraProp}</h1>
}
export default page
import App from 'next/app'
function MyApp({ Component, pageProps, extraProp }) {
return <Component {...pageProps} extraProp={extraProp} />
}
// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.
MyApp.getInitialProps = async (appContext) => {
// calls page's `getInitialProps` and fills `appProps.pageProps`
const appProps = await App.getInitialProps(appContext)
return { ...appProps, extraProp: 'Hi There' }
}
export default MyApp
const page = () => 'custom 404 page'
page.getInitialProps = () => {
throw new Error('oops')
}
export default page
export default () => 'hello from index'
/* eslint-env jest */
import fs from 'fs-extra'
import { join } from 'path'
import {
killApp,
findPort,
launchApp,
nextStart,
nextBuild,
fetchViaHTTP,
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import cheerio from 'cheerio'
jest.setTimeout(1000 * 60 * 2)
const appDir = join(__dirname, '../')
const gip404Err = /`pages\/404` can not have getInitialProps\/getServerSideProps/
let appPort
let app
describe('404 Page Support with _app', () => {
describe('production mode', () => {
afterAll(() => killApp(app))
it('should build successfully', async () => {
const { code, stderr, stdout } = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
})
expect(code).toBe(0)
expect(stderr).not.toMatch(gip404Err)
expect(stdout).not.toMatch(gip404Err)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
it('should not output static 404 if _app has getInitialProps', async () => {
const browser = await webdriver(appPort, '/404')
const isAutoExported = await browser.eval('__NEXT_DATA__.autoExport')
expect(isAutoExported).toBe(null)
})
it('specify to use the 404 page still in the routes-manifest', async () => {
const manifest = await fs.readJSON(
join(appDir, '.next/routes-manifest.json')
)
expect(manifest.pages404).toBe(true)
})
it('should still use 404 page', async () => {
const res = await fetchViaHTTP(appPort, '/abc')
expect(res.status).toBe(404)
const $ = cheerio.load(await res.text())
expect($('#404-title').text()).toBe('Hi There')
})
})
describe('dev mode', () => {
let stderr = ''
let stdout = ''
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort, {
onStderr(msg) {
stderr += msg
},
onStdout(msg) {
stdout += msg
},
})
})
afterAll(() => killApp(app))
it('should not show pages/404 GIP error if _app has GIP', async () => {
const res = await fetchViaHTTP(appPort, '/abc')
expect(res.status).toBe(404)
const $ = cheerio.load(await res.text())
expect($('#404-title').text()).toBe('Hi There')
expect(stderr).not.toMatch(gip404Err)
expect(stdout).not.toMatch(gip404Err)
})
})
})
......@@ -10,6 +10,7 @@ import {
nextBuild,
renderViaHTTP,
fetchViaHTTP,
getPageFileFromPagesManifest,
} from 'next-test-utils'
jest.setTimeout(1000 * 60 * 2)
......@@ -18,7 +19,6 @@ const appDir = join(__dirname, '../')
const nextConfig = join(appDir, 'next.config.js')
let appPort
let buildId
let app
const runTests = (mode) => {
......@@ -47,21 +47,8 @@ const runTests = (mode) => {
})
it('should have output 404.html', async () => {
expect(
await fs
.access(
join(
appDir,
'.next',
...(mode === 'server'
? ['server', 'static', buildId, 'pages']
: ['serverless', 'pages']),
'404.html'
)
)
.then(() => true)
.catch(() => false)
).toBe(true)
const page = getPageFileFromPagesManifest(appDir, '/404')
expect(page.endsWith('.html')).toBe(true)
})
}
}
......@@ -81,7 +68,6 @@ describe('Default 404 Page with custom _error', () => {
appPort = await findPort()
app = await nextStart(appDir, appPort)
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
runTests('server')
......@@ -109,7 +95,6 @@ describe('Default 404 Page with custom _error', () => {
appPort = await findPort()
app = await nextStart(appDir, appPort)
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
runTests('serverless')
......
......@@ -11,18 +11,17 @@ import {
renderViaHTTP,
fetchViaHTTP,
waitFor,
getPageFileFromPagesManifest,
} from 'next-test-utils'
jest.setTimeout(1000 * 60 * 2)
const appDir = join(__dirname, '../')
const pages404 = join(appDir, 'pages/404.js')
const appPage = join(appDir, 'pages/_app.js')
const nextConfig = join(appDir, 'next.config.js')
const gip404Err = /`pages\/404` can not have getInitialProps\/getServerSideProps/
let nextConfigContent
let buildId
let appPort
let app
......@@ -51,18 +50,8 @@ const runTests = (mode = 'server') => {
if (mode !== 'dev') {
it('should output 404.html during build', async () => {
expect(
await fs.exists(
join(
appDir,
'.next',
mode === 'serverless'
? 'serverless/pages'
: `server/static/${buildId}/pages`,
'404.html'
)
)
).toBe(true)
const page = getPageFileFromPagesManifest(appDir, '/404')
expect(page.endsWith('.html')).toBe(true)
})
it('should add /404 to pages-manifest correctly', async () => {
......@@ -79,7 +68,6 @@ describe('404 Page Support', () => {
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
buildId = 'development'
})
afterAll(() => killApp(app))
......@@ -91,7 +79,6 @@ describe('404 Page Support', () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
afterAll(() => killApp(app))
......@@ -112,7 +99,6 @@ describe('404 Page Support', () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
afterAll(async () => {
await fs.writeFile(nextConfig, nextConfigContent)
......@@ -275,85 +261,4 @@ describe('404 Page Support', () => {
expect(stderr).toMatch(gip404Err)
})
describe('_app with getInitialProps', () => {
beforeAll(() =>
fs.writeFile(
appPage,
`
import NextApp from 'next/app'
const App = ({ Component, pageProps }) => <Component {...pageProps} />
App.getInitialProps = NextApp.getInitialProps
export default App
`
)
)
afterAll(() => fs.remove(appPage))
describe('production mode', () => {
afterAll(() => killApp(app))
it('should build successfully', async () => {
const { code, stderr, stdout } = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
})
expect(code).toBe(0)
expect(stderr).not.toMatch(gip404Err)
expect(stdout).not.toMatch(gip404Err)
appPort = await findPort()
app = await nextStart(appDir, appPort)
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
})
it('should not output static 404 if _app has getInitialProps', async () => {
expect(
await fs.exists(
join(appDir, '.next/server/static', buildId, 'pages/404.html')
)
).toBe(false)
})
it('specify to use the 404 page still in the routes-manifest', async () => {
const manifest = await fs.readJSON(
join(appDir, '.next/routes-manifest.json')
)
expect(manifest.pages404).toBe(true)
})
it('should still use 404 page', async () => {
const res = await fetchViaHTTP(appPort, '/abc')
expect(res.status).toBe(404)
expect(await res.text()).toContain('custom 404 page')
})
})
describe('dev mode', () => {
let stderr = ''
let stdout = ''
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort, {
onStderr(msg) {
stderr += msg
},
onStdout(msg) {
stdout += msg
},
})
})
afterAll(() => killApp(app))
it('should not show pages/404 GIP error if _app has GIP', async () => {
const res = await fetchViaHTTP(appPort, '/abc')
expect(res.status).toBe(404)
expect(await res.text()).toContain('custom 404 page')
expect(stderr).not.toMatch(gip404Err)
expect(stdout).not.toMatch(gip404Err)
})
})
})
})
......@@ -117,13 +117,8 @@ describe('AMP SSG Support', () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
const buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
builtServerPagesDir = join(
appDir,
'.next/server/static',
buildId,
'pages'
)
// TODO: use browser instead to do checks that now need filesystem access
builtServerPagesDir = join(appDir, '.next', 'server', 'pages')
})
afterAll(() => killApp(app))
runTests()
......
import Link from 'next/link'
if (typeof window !== 'undefined') {
window.NAV_PAGE_LOADED = true
}
export default function Nav() {
return (
<ul>
<li>
<Link href="/only-amp">
<a id="only-amp-link">AMP First Page</a>
</Link>
</li>
</ul>
)
}
......@@ -2,13 +2,7 @@
import { validateAMP } from 'amp-test-utils'
import cheerio from 'cheerio'
import {
accessSync,
readFile,
readFileSync,
writeFile,
writeFileSync,
} from 'fs-extra'
import { readFile, readFileSync, writeFile, writeFileSync } from 'fs-extra'
import {
check,
findPort,
......@@ -72,31 +66,12 @@ describe('AMP Usage', () => {
})
it('should not output client pages for AMP only', async () => {
const buildId = readFileSync(join(appDir, '.next/BUILD_ID'), 'utf8')
const ampOnly = ['only-amp', 'root-hmr', 'another-amp']
for (const pg of ampOnly) {
expect(() =>
accessSync(
join(appDir, '.next/static', buildId, 'pages', pg + '.js')
)
).toThrow()
expect(() =>
accessSync(
join(
appDir,
'.next/server/static',
buildId,
'pages',
pg + '.html'
)
)
).not.toThrow()
expect(() =>
accessSync(
join(appDir, '.next/server/static', buildId, 'pages', pg + '.js')
)
).toThrow()
}
const browser = await webdriver(appPort, '/nav')
await browser.elementByCss('#only-amp-link').click()
const result = await browser.eval('window.NAV_PAGE_LOADED')
expect(result).toBe(null)
})
it('should add link preload for amp script', async () => {
......@@ -285,51 +260,12 @@ describe('AMP Usage', () => {
})
it('should not output client pages for AMP only', async () => {
const buildId = readFileSync(join(appDir, '.next/BUILD_ID'), 'utf8')
const ampOnly = ['only-amp', 'root-hmr', 'another-amp']
for (const pg of ampOnly) {
expect(() =>
accessSync(join(appDir, '.next/static', buildId, 'pages', pg + '.js'))
).toThrow()
expect(() =>
accessSync(
join(appDir, '.next/server/static', buildId, 'pages', pg + '.html')
)
).not.toThrow()
expect(() =>
accessSync(
join(appDir, '.next/server/static', buildId, 'pages', pg + '.js')
)
).toThrow()
}
})
const browser = await webdriver(appPort, '/nav')
await browser.elementByCss('#only-amp-link').click()
it('should not output modern client pages for AMP only', async () => {
const buildId = readFileSync(join(appDir, '.next/BUILD_ID'), 'utf8')
const ampOnly = ['only-amp', 'root-hmr', 'another-amp']
for (const pg of ampOnly) {
expect(() =>
accessSync(
join(appDir, '.next/static', buildId, 'pages', pg + '.module.js')
)
).toThrow()
expect(() =>
accessSync(
join(appDir, '.next/server/static', buildId, 'pages', pg + '.html')
)
).not.toThrow()
expect(() =>
accessSync(
join(
appDir,
'.next/server/static',
buildId,
'pages',
pg + '.module.js'
)
)
).toThrow()
}
const result = await browser.eval('window.NAV_PAGE_LOADED')
expect(result).toBe(null)
})
})
......
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
.BundleAnalyzerPlugin
module.exports = {
assetPrefix: '/foo/',
webpack(config) {
config.plugins = config.plugins || []
config.plugins.push(
......
/* eslint-env jest */
import cheerio from 'cheerio'
import express from 'express'
import { access, readdir, readFile, unlink } from 'fs-extra'
import http from 'http'
import { nextBuild, nextServer, promiseCall, stopApp } from 'next-test-utils'
import { readdir, readFile, unlink } from 'fs-extra'
import {
nextBuild,
killApp,
nextStart,
findPort,
renderViaHTTP,
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import { join } from 'path'
......@@ -12,10 +16,10 @@ jest.setTimeout(1000 * 60 * 1)
const appDir = join(__dirname, '../')
let buildId
let chunks
let stats
let appPort
let app
const existsChunkNamed = (name) => {
return chunks.some((chunk) => new RegExp(name).test(chunk))
}
......@@ -33,21 +37,20 @@ describe('Chunking', () => {
} catch (e) {
// Error here means old chunks don't exist, so we don't need to do anything
}
const { stdout, stderr } = await nextBuild(appDir, [], {
stdout: true,
stderr: true,
})
console.log(stdout)
console.error(stderr)
await nextBuild(appDir, [])
stats = (await readFile(join(appDir, '.next', 'stats.json'), 'utf8'))
// fixes backslashes in keyNames not being escaped on windows
.replace(/"static\\(.*?":?)/g, (match) => match.replace(/\\/g, '\\\\'))
stats = JSON.parse(stats)
buildId = await readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
appPort = await findPort()
app = await nextStart(appDir, appPort)
chunks = await readdir(join(appDir, '.next', 'static', 'chunks'))
})
afterAll(() => killApp(app))
it('should use all url friendly names', () => {
expect(chunks).toEqual(chunks.map((name) => encodeURIComponent(name)))
})
......@@ -68,20 +71,9 @@ describe('Chunking', () => {
expect(existsChunkNamed('react|react-dom')).toBe(false)
})
it('should create a _buildManifest.js file', async () => {
expect(
await access(
join(appDir, '.next', 'static', buildId, '_buildManifest.js')
)
).toBe(undefined) /* fs.access callback returns undefined if file exists */
})
it('should not preload the build manifest', async () => {
const indexPage = await readFile(
join(appDir, '.next', 'server', 'static', buildId, 'pages', 'index.html')
)
const $ = cheerio.load(indexPage)
const html = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(html)
expect(
[].slice
.call($('link[rel="preload"][as="script"]'))
......@@ -91,11 +83,9 @@ describe('Chunking', () => {
})
it('should execute the build manifest', async () => {
const indexPage = await readFile(
join(appDir, '.next', 'server', 'static', buildId, 'pages', 'index.html')
)
const $ = cheerio.load(indexPage)
const html = await renderViaHTTP(appPort, '/')
console.log(html)
const $ = cheerio.load(html)
expect(
Array.from($('script'))
.map((e) => e.attribs.src)
......@@ -117,28 +107,6 @@ describe('Chunking', () => {
})
describe('Serving', () => {
let server
let appPort
beforeAll(async () => {
await nextBuild(appDir)
const app = nextServer({
dir: join(__dirname, '../'),
dev: false,
quiet: true,
})
const expressApp = express()
await app.prepare()
expressApp.use('/foo/_next', express.static(join(__dirname, '../.next')))
expressApp.use(app.getRequestHandler())
server = http.createServer(expressApp)
await promiseCall(server, 'listen')
appPort = server.address().port
})
afterAll(() => stopApp(server))
it('should hydrate with aggressive chunking', async () => {
const browser = await webdriver(appPort, '/page2')
const text = await browser.elementByCss('#padded-str').text()
......
......@@ -4,9 +4,6 @@ import cheerio from 'cheerio'
import { BUILD_MANIFEST, REACT_LOADABLE_MANIFEST } from 'next/constants'
import { join } from 'path'
import url from 'url'
import { getPageFileFromBuildManifest } from 'next-test-utils'
const appDir = join(__dirname, '../')
export default function (render, fetch) {
async function get$(path, query) {
......@@ -268,25 +265,6 @@ export default function (render, fetch) {
expect(res.status).toBe(200)
})
test('should expose the compiled page file in development', async () => {
await fetch('/stateless') // make sure the stateless page is built
const statelessPageFile = getPageFileFromBuildManifest(
appDir,
'/stateless'
)
const clientSideJsRes = await fetch(join('/_next', statelessPageFile))
expect(clientSideJsRes.status).toBe(200)
const clientSideJsBody = await clientSideJsRes.text()
expect(clientSideJsBody).toMatch(/My component!/)
const serverSideJsRes = await fetch(
'/_next/development/server/static/development/pages/stateless.js'
)
expect(serverSideJsRes.status).toBe(200)
const serverSideJsBody = await serverSideJsRes.text()
expect(serverSideJsBody).toMatch(/My component!/)
})
test('allows to import .json files', async () => {
const html = await render('/json')
expect(html.includes('Vercel')).toBeTruthy()
......
/* eslint-env jest */
import fs from 'fs-extra'
import path from 'path'
import { nextBuild } from 'next-test-utils'
import { nextBuild, readNextBuildServerPageFile } from 'next-test-utils'
import escapeStringRegexp from 'escape-string-regexp'
jest.setTimeout(1000 * 60 * 1)
const appDir = path.join(__dirname, '../app')
let buildId
describe('externalize next/dist/next-server', () => {
beforeAll(async () => {
await nextBuild(appDir)
buildId = await fs.readFile(path.join(appDir, '.next/BUILD_ID'), 'utf8')
})
it('Does not bundle next/dist/next-server/lib/head.js in _error', async () => {
const content = await fs.readFile(
path.join(appDir, '.next/server/static', buildId, 'pages/_error.js'),
'utf8'
)
const content = readNextBuildServerPageFile(appDir, '/_error')
expect(content).toMatch(
new RegExp(
'^' +
......
/* eslint-env jest */
import fs from 'fs-extra'
import path from 'path'
import { nextBuild } from 'next-test-utils'
import { nextBuild, readNextBuildServerPageFile } from 'next-test-utils'
jest.setTimeout(1000 * 60 * 1)
const appDir = path.join(__dirname, '../app')
let buildId
describe('Non-Next externalization', () => {
beforeAll(async () => {
await nextBuild(appDir)
buildId = await fs.readFile(path.join(appDir, '.next/BUILD_ID'), 'utf8')
})
it('Externalized non-Next dist-using package', async () => {
const content = await fs.readFile(
path.join(appDir, '.next/server/static', buildId, 'pages/index.js'),
'utf8'
)
const content = readNextBuildServerPageFile(appDir, '/')
expect(content).not.toContain('BrokenExternalMarker')
})
})
......@@ -8,6 +8,7 @@ import {
nextStart,
renderViaHTTP,
waitFor,
getPageFileFromPagesManifest,
} from 'next-test-utils'
import { join } from 'path'
......@@ -23,9 +24,9 @@ function runTests(route, routePath, serverless) {
it(`[${route}] should not revalidate when set to false`, async () => {
const fileName = join(
appDir,
`.next`,
...(serverless ? ['serverless'] : ['server', 'static', buildId]),
`pages/${routePath}.html`
'.next',
serverless ? 'serverless' : 'server',
getPageFileFromPagesManifest(appDir, routePath)
)
const initialHtml = await renderViaHTTP(appPort, route)
const initialFileHtml = await fs.readFile(fileName, 'utf8')
......@@ -50,13 +51,13 @@ function runTests(route, routePath, serverless) {
})
it(`[${route}] should not revalidate /_next/data when set to false`, async () => {
const route = join(`/_next/data/${buildId}`, `${routePath}.json`)
const fileName = join(
appDir,
`.next`,
...(serverless ? ['serverless'] : ['server', 'static', buildId]),
`pages/${routePath}.json`
'.next',
serverless ? 'serverless' : 'server',
getPageFileFromPagesManifest(appDir, routePath)
)
const route = join(`/_next/data/${buildId}`, `${routePath}.json`)
const initialData = JSON.parse(await renderViaHTTP(appPort, route))
const initialFileJson = await fs.readFile(fileName, 'utf8')
......@@ -99,7 +100,7 @@ describe('SSG Prerender No Revalidate', () => {
})
afterAll(() => killApp(app))
runTests('/', '/index', true)
runTests('/', '/', true)
runTests('/named', '/named', true)
runTests('/nested', '/nested', true)
runTests('/nested/named', '/nested/named', true)
......@@ -121,7 +122,7 @@ describe('SSG Prerender No Revalidate', () => {
})
afterAll(() => killApp(app))
runTests('/', '/index')
runTests('/', '/')
runTests('/named', '/named')
runTests('/nested', '/nested')
runTests('/nested/named', '/nested/named')
......
......@@ -1541,7 +1541,8 @@ describe('SSG Prerender', () => {
},
})
buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8')
distPagesDir = join(appDir, '.next/server/static', buildId, 'pages')
// TODO: Don't rely on this path
distPagesDir = join(appDir, '.next', 'server', 'pages')
})
afterAll(() => killApp(app))
......
/* eslint-env jest */
/* global browserName */
import cheerio from 'cheerio'
import { existsSync, readFileSync } from 'fs'
import { existsSync } from 'fs'
import {
nextServer,
renderViaHTTP,
......@@ -9,6 +9,7 @@ import {
startApp,
stopApp,
waitFor,
getPageFileFromPagesManifest,
} from 'next-test-utils'
import webdriver from 'next-webdriver'
import {
......@@ -23,7 +24,6 @@ import dynamicImportTests from './dynamic'
import processEnv from './process-env'
import security from './security'
const appDir = join(__dirname, '../')
let serverDir
let appPort
let server
let app
......@@ -43,9 +43,6 @@ describe('Production Usage', () => {
server = await startApp(app)
context.appPort = appPort = server.address().port
const buildId = readFileSync(join(appDir, '.next/BUILD_ID'), 'utf8')
serverDir = join(appDir, '.next/server/static/', buildId, 'pages')
})
afterAll(() => stopApp(server))
......@@ -641,18 +638,21 @@ describe('Production Usage', () => {
})
it('should replace static pages with HTML files', async () => {
const staticFiles = ['about', 'another', 'counter', 'dynamic', 'prefetch']
for (const file of staticFiles) {
expect(existsSync(join(serverDir, file + '.html'))).toBe(true)
expect(existsSync(join(serverDir, file + '.js'))).toBe(false)
const pages = ['/about', '/another', '/counter', '/dynamic', '/prefetch']
for (const page of pages) {
const file = getPageFileFromPagesManifest(appDir, page)
expect(file.endsWith('.html')).toBe(true)
}
})
it('should not replace non-static pages with HTML files', async () => {
const nonStaticFiles = ['api', 'external-and-back', 'finish-response']
for (const file of nonStaticFiles) {
expect(existsSync(join(serverDir, file + '.js'))).toBe(true)
expect(existsSync(join(serverDir, file + '.html'))).toBe(false)
const pages = ['/api', '/external-and-back', '/finish-response']
for (const page of pages) {
const file = getPageFileFromPagesManifest(appDir, page)
expect(file.endsWith('.js')).toBe(true)
}
})
......
......@@ -11,6 +11,7 @@ import {
fetchViaHTTP,
renderViaHTTP,
readNextBuildClientPageFile,
getPageFileFromPagesManifest,
} from 'next-test-utils'
import fetch from 'node-fetch'
......@@ -117,21 +118,23 @@ describe('Serverless Trace', () => {
})
it('should replace static pages with HTML files', async () => {
const staticFiles = ['abc', 'dynamic', 'dynamic-two', 'some-amp']
for (const file of staticFiles) {
expect(existsSync(join(serverlessDir, file + '.html'))).toBe(true)
expect(existsSync(join(serverlessDir, file + '.js'))).toBe(false)
const pages = ['/abc', '/dynamic', '/dynamic-two', '/some-amp']
for (const page of pages) {
const file = getPageFileFromPagesManifest(appDir, page)
expect(file.endsWith('.html')).toBe(true)
}
})
it('should not replace non-static pages with HTML files', async () => {
const nonStaticFiles = ['fetch', '_error']
for (const file of nonStaticFiles) {
expect(existsSync(join(serverlessDir, file + '.js'))).toBe(true)
expect(existsSync(join(serverlessDir, file + '.html'))).toBe(false)
const pages = ['/fetch', '/_error']
for (const page of pages) {
const file = getPageFileFromPagesManifest(appDir, page)
expect(file.endsWith('.js')).toBe(true)
}
})
it('should reply on API request successfully', async () => {
const content = await renderViaHTTP(appPort, '/api/hello')
expect(content).toMatch(/hello world/)
......
......@@ -13,6 +13,7 @@ import {
fetchViaHTTP,
renderViaHTTP,
getPageFileFromBuildManifest,
getPageFileFromPagesManifest,
} from 'next-test-utils'
import qs from 'querystring'
import path from 'path'
......@@ -186,18 +187,21 @@ describe('Serverless', () => {
})
it('should replace static pages with HTML files', async () => {
const staticFiles = ['abc', 'dynamic', 'dynamic-two', 'some-amp']
for (const file of staticFiles) {
expect(existsSync(join(serverlessDir, file + '.html'))).toBe(true)
expect(existsSync(join(serverlessDir, file + '.js'))).toBe(false)
const pages = ['/abc', '/dynamic', '/dynamic-two', '/some-amp']
for (const page of pages) {
const file = getPageFileFromPagesManifest(appDir, page)
expect(file.endsWith('.html')).toBe(true)
}
})
it('should not replace non-static pages with HTML files', async () => {
const nonStaticFiles = ['fetch', '_error']
for (const file of nonStaticFiles) {
expect(existsSync(join(serverlessDir, file + '.js'))).toBe(true)
expect(existsSync(join(serverlessDir, file + '.html'))).toBe(false)
const pages = ['/fetch', '/_error']
for (const page of pages) {
const file = getPageFileFromPagesManifest(appDir, page)
expect(file.endsWith('.js')).toBe(true)
}
})
......
......@@ -13,10 +13,8 @@ import {
jest.setTimeout(1000 * 60 * 2)
const appDir = join(__dirname, '..')
const nextConfig = join(appDir, 'next.config.js')
const static404 = join(appDir, '.next/server/static/test-id/pages/404.html')
const appPage = join(appDir, 'pages/_app.js')
const errorPage = join(appDir, 'pages/_error.js')
const buildId = `generateBuildId: () => 'test-id'`
let app
let appPort
......@@ -29,10 +27,6 @@ describe('Static 404 page', () => {
beforeEach(() => fs.remove(join(appDir, '.next/server')))
describe('With config enabled', () => {
beforeEach(() =>
fs.writeFile(nextConfig, `module.exports = { ${buildId} }`)
)
it('should export 404 page without custom _error', async () => {
await nextBuild(appDir)
appPort = await findPort()
......@@ -40,7 +34,6 @@ describe('Static 404 page', () => {
const html = await renderViaHTTP(appPort, '/non-existent')
await killApp(app)
expect(html).toContain('This page could not be found')
expect(await fs.exists(static404)).toBe(true)
})
it('should export 404 page without custom _error (serverless)', async () => {
......@@ -58,9 +51,6 @@ describe('Static 404 page', () => {
const html = await renderViaHTTP(appPort, '/non-existent')
await killApp(app)
expect(html).toContain('This page could not be found')
expect(
await fs.exists(join(appDir, '.next/serverless/pages/404.html'))
).toBe(true)
})
it('should not export 404 page with custom _error GIP', async () => {
......@@ -79,7 +69,6 @@ describe('Static 404 page', () => {
)
await nextBuild(appDir)
await fs.remove(errorPage)
expect(await fs.exists(static404)).toBe(false)
})
it('should not export 404 page with getInitialProps in _app', async () => {
......@@ -95,7 +84,6 @@ describe('Static 404 page', () => {
)
await nextBuild(appDir)
await fs.remove(appPage)
expect(await fs.exists(static404)).toBe(false)
})
})
})
......@@ -493,8 +493,12 @@ export function normalizeRegEx(src) {
return new RegExp(src).source.replace(/\^\//g, '^\\/')
}
function readJson(path) {
return JSON.parse(readFileSync(path))
}
export function getBuildManifest(dir) {
return JSON.parse(readFileSync(path.join(dir, '.next/build-manifest.json')))
return readJson(path.join(dir, '.next/build-manifest.json'))
}
export function getPageFileFromBuildManifest(dir, page) {
......@@ -522,7 +526,12 @@ export function readNextBuildClientPageFile(appDir, page) {
}
export function getPagesManifest(dir) {
return require(path.join(dir, '.next/server/pages-manifest.json'))
const serverFile = path.join(dir, '.next/server/pages-manifest.json')
if (existsSync(serverFile)) {
return readJson(serverFile)
}
return readJson(path.join(dir, '.next/serverless/pages-manifest.json'))
}
export function getPageFileFromPagesManifest(dir, page) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册