diff --git a/demos/default/hello.txt b/demos/default/hello.txt
new file mode 100644
index 0000000000..04fea06420
--- /dev/null
+++ b/demos/default/hello.txt
@@ -0,0 +1 @@
+world
\ No newline at end of file
diff --git a/demos/default/pages/getServerSideProps/file.js b/demos/default/pages/getServerSideProps/file.js
new file mode 100644
index 0000000000..a9f1581a94
--- /dev/null
+++ b/demos/default/pages/getServerSideProps/file.js
@@ -0,0 +1,29 @@
+import Link from 'next/link'
+import path from 'path'
+import fs from 'fs'
+
+export async function getServerSideProps() {
+ const text = fs.readFileSync(path.join(process.cwd(), 'hello.txt'), 'utf8').trim()
+
+ return {
+ props: {
+ world: text,
+ time: new Date().getTime(),
+ },
+ }
+}
+
+const File = ({ world, time }) => (
+ <>
+
hello {world}
+ time: {time}
+
+ to home
+
+
+
+ to something
+
+ >
+)
+export default File
diff --git a/packages/runtime/src/helpers/functions.ts b/packages/runtime/src/helpers/functions.ts
index 052e0b5efc..88c7b07886 100644
--- a/packages/runtime/src/helpers/functions.ts
+++ b/packages/runtime/src/helpers/functions.ts
@@ -11,7 +11,7 @@ import { join, relative, resolve } from 'pathe'
import { HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME, IMAGE_FUNCTION_NAME, DEFAULT_FUNCTIONS_SRC } from '../constants'
import { getApiHandler } from '../templates/getApiHandler'
import { getHandler } from '../templates/getHandler'
-import { getPageResolver, getSinglePageResolver } from '../templates/getPageResolver'
+import { getResolverForPages, getResolverForSourceFiles } from '../templates/getPageResolver'
import { ApiConfig, ApiRouteType, extractConfigFromFile } from './analysis'
import { getSourceFileForPage } from './files'
@@ -52,7 +52,7 @@ export const generateFunctions = async (
const resolveSourceFile = (file: string) => join(publish, 'server', file)
- const resolverSource = await getSinglePageResolver({
+ const resolverSource = await getResolverForSourceFiles({
functionsDir,
// These extra pages are always included by Next.js
sourceFiles: [compiled, 'pages/_app.js', 'pages/_document.js', 'pages/_error.js'].map(resolveSourceFile),
@@ -80,18 +80,13 @@ export const generateFunctions = async (
* This is just so that the nft bundler knows about them. We'll eventually do this better.
*/
export const generatePagesResolver = async ({
- constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC, PUBLISH_DIR },
- target,
-}: {
- constants: NetlifyPluginConstants
- target: string
-}): Promise => {
+ INTERNAL_FUNCTIONS_SRC,
+ FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC,
+ PUBLISH_DIR,
+}: NetlifyPluginConstants): Promise => {
const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC
- const jsSource = await getPageResolver({
- publish: PUBLISH_DIR,
- target,
- })
+ const jsSource = await getResolverForPages(PUBLISH_DIR)
await writeFile(join(functionsPath, ODB_FUNCTION_NAME, 'pages.js'), jsSource)
await writeFile(join(functionsPath, HANDLER_FUNCTION_NAME, 'pages.js'), jsSource)
diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts
index 90ffcb43b6..05f9eb0b2d 100644
--- a/packages/runtime/src/index.ts
+++ b/packages/runtime/src/index.ts
@@ -155,7 +155,7 @@ const plugin: NetlifyPlugin = {
const apiRoutes = await getExtendedApiRouteConfigs(publish, appDir)
await generateFunctions(constants, appDir, apiRoutes)
- await generatePagesResolver({ target, constants })
+ await generatePagesResolver(constants)
await movePublicFiles({ appDir, outdir, publish })
diff --git a/packages/runtime/src/templates/getPageResolver.ts b/packages/runtime/src/templates/getPageResolver.ts
index 6ca5165858..1326558c30 100644
--- a/packages/runtime/src/templates/getPageResolver.ts
+++ b/packages/runtime/src/templates/getPageResolver.ts
@@ -1,9 +1,6 @@
-import { posix } from 'path'
-
+import glob from 'globby'
import { outdent } from 'outdent'
-import { relative, resolve } from 'pathe'
-import slash from 'slash'
-import glob from 'tiny-glob'
+import { join, relative, resolve } from 'pathe'
import { HANDLER_FUNCTION_NAME } from '../constants'
import { getDependenciesOfFile } from '../helpers/files'
@@ -11,20 +8,33 @@ import { getDependenciesOfFile } from '../helpers/files'
// Generate a file full of require.resolve() calls for all the pages in the
// build. This is used by the nft bundler to find all the pages.
-export const getPageResolver = async ({ publish, target }: { publish: string; target: string }) => {
- const functionDir = posix.resolve(posix.join('.netlify', 'functions', HANDLER_FUNCTION_NAME))
- const root = posix.resolve(slash(publish), target === 'server' ? 'server' : 'serverless', 'pages')
+export const getUniqueDependencies = async (sourceFiles: Array) => {
+ const dependencies = await Promise.all(sourceFiles.map((sourceFile) => getDependenciesOfFile(sourceFile)))
+ return [...new Set([...sourceFiles, ...dependencies.flat()])].sort()
+}
- const pages = await glob('**/*.js', {
+export const getAllPageDependencies = async (publish: string) => {
+ const root = resolve(publish, 'server')
+
+ const pageFiles = await glob('{pages,app}/**/*.js', {
cwd: root,
dot: true,
})
- const pageFiles = pages
- .map((page) => `require.resolve('${posix.relative(functionDir, posix.join(root, slash(page)))}')`)
- .sort()
+ // We don't use `absolute: true` because that returns Windows paths on Windows.
+ // Instead we use pathe to normalize the paths.
+ return getUniqueDependencies(pageFiles.map((pageFile) => join(root, pageFile)))
+}
- return outdent`
- // This file is purely to allow nft to know about these pages. It should be temporary.
+export const getResolverForDependencies = ({
+ dependencies,
+ functionDir,
+}: {
+ dependencies: string[]
+ functionDir: string
+}) => {
+ const pageFiles = dependencies.map((file) => `require.resolve('${relative(functionDir, file)}')`)
+ return outdent/* javascript */ `
+ // This file is purely to allow nft to know about these pages.
exports.resolvePages = () => {
try {
${pageFiles.join('\n ')}
@@ -33,31 +43,21 @@ export const getPageResolver = async ({ publish, target }: { publish: string; ta
`
}
-/**
- * API routes only need the dependencies for a single entrypoint, so we use the
- * NFT trace file to get the dependencies.
- */
-export const getSinglePageResolver = async ({
+export const getResolverForPages = async (publish: string) => {
+ const functionDir = resolve('.netlify', 'functions', HANDLER_FUNCTION_NAME)
+ const dependencies = await getAllPageDependencies(publish)
+ return getResolverForDependencies({ dependencies, functionDir })
+}
+
+export const getResolverForSourceFiles = async ({
functionsDir,
sourceFiles,
}: {
functionsDir: string
sourceFiles: Array
}) => {
- const dependencies = await Promise.all(sourceFiles.map((sourceFile) => getDependenciesOfFile(sourceFile)))
// We don't need the actual name, just the relative path.
const functionDir = resolve(functionsDir, 'functionName')
-
- const deduped = [...new Set(dependencies.flat())]
-
- const pageFiles = [...sourceFiles, ...deduped]
- .map((file) => `require.resolve('${relative(functionDir, file)}')`)
- .sort()
-
- return outdent/* javascript */ `
- // This file is purely to allow nft to know about these pages.
- try {
- ${pageFiles.join('\n ')}
- } catch {}
- `
+ const dependencies = await getUniqueDependencies(sourceFiles)
+ return getResolverForDependencies({ dependencies, functionDir })
}
diff --git a/test/__snapshots__/index.js.snap b/test/__snapshots__/index.js.snap
index 78b56bbeb2..e9bea87306 100644
--- a/test/__snapshots__/index.js.snap
+++ b/test/__snapshots__/index.js.snap
@@ -1,9 +1,97 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`onBuild() generates a file referencing all API route sources 1`] = `
-"// This file is purely to allow nft to know about these pages. It should be temporary.
+exports[`function helpers config dependency tracing extracts a list of all dependencies 1`] = `
+Array [
+ ".next/package.json",
+ ".next/server/chunks/1987.js",
+ ".next/server/chunks/274.js",
+ ".next/server/chunks/4271.js",
+ ".next/server/chunks/5237.js",
+ ".next/server/chunks/9097.js",
+ ".next/server/chunks/header.js",
+ ".next/server/pages/_app.js",
+ ".next/server/pages/_document.js",
+ ".next/server/pages/_error.js",
+ ".next/server/pages/api/enterPreview.js",
+ ".next/server/pages/api/exitPreview.js",
+ ".next/server/pages/api/hello-background.js",
+ ".next/server/pages/api/hello-scheduled.js",
+ ".next/server/pages/api/hello.js",
+ ".next/server/pages/api/og.js",
+ ".next/server/pages/api/shows/[...params].js",
+ ".next/server/pages/api/shows/[id].js",
+ ".next/server/pages/deep/import.js",
+ ".next/server/pages/getServerSideProps/[id].js",
+ ".next/server/pages/getServerSideProps/all/[[...slug]].js",
+ ".next/server/pages/getServerSideProps/file.js",
+ ".next/server/pages/getServerSideProps/static.js",
+ ".next/server/pages/getStaticProps/[id].js",
+ ".next/server/pages/getStaticProps/env.js",
+ ".next/server/pages/getStaticProps/static.js",
+ ".next/server/pages/getStaticProps/with-revalidate-404.js",
+ ".next/server/pages/getStaticProps/with-revalidate.js",
+ ".next/server/pages/getStaticProps/withFallback/[...slug].js",
+ ".next/server/pages/getStaticProps/withFallback/[id].js",
+ ".next/server/pages/getStaticProps/withFallbackBlocking/[id].js",
+ ".next/server/pages/getStaticProps/withRevalidate/[id].js",
+ ".next/server/pages/getStaticProps/withRevalidate/withFallback/[id].js",
+ ".next/server/pages/getStaticProps/withRevalidate/withFallbackBlocking/[id].js",
+ ".next/server/pages/index.js",
+ ".next/server/pages/previewTest.js",
+ ".next/server/pages/shows/[...params].js",
+ ".next/server/pages/shows/[id].js",
+ ".next/server/webpack-api-runtime.js",
+ ".next/server/webpack-runtime.js",
+ "components/Header.js",
+ "hello.txt",
+ "package.json",
+]
+`;
+
+exports[`onBuild() generates a file referencing all API route sources: for _api_hello-background-background 1`] = `
+"// This file is purely to allow nft to know about these pages.
+exports.resolvePages = () => {
+ try {
+ require.resolve('../../../.next/package.json')
+ require.resolve('../../../.next/server/chunks/274.js')
+ require.resolve('../../../.next/server/pages/_app.js')
+ require.resolve('../../../.next/server/pages/_document.js')
+ require.resolve('../../../.next/server/pages/_error.js')
+ require.resolve('../../../.next/server/pages/api/hello-background.js')
+ require.resolve('../../../.next/server/webpack-api-runtime.js')
+ require.resolve('../../../.next/server/webpack-runtime.js')
+ } catch {}
+}"
+`;
+
+exports[`onBuild() generates a file referencing all API route sources: for _api_hello-scheduled-handler 1`] = `
+"// This file is purely to allow nft to know about these pages.
+exports.resolvePages = () => {
+ try {
+ require.resolve('../../../.next/package.json')
+ require.resolve('../../../.next/server/chunks/274.js')
+ require.resolve('../../../.next/server/pages/_app.js')
+ require.resolve('../../../.next/server/pages/_document.js')
+ require.resolve('../../../.next/server/pages/_error.js')
+ require.resolve('../../../.next/server/pages/api/hello-scheduled.js')
+ require.resolve('../../../.next/server/webpack-api-runtime.js')
+ require.resolve('../../../.next/server/webpack-runtime.js')
+ require.resolve('../../../package.json')
+ } catch {}
+}"
+`;
+
+exports[`onBuild() generates a file referencing all page sources 1`] = `
+"// This file is purely to allow nft to know about these pages.
exports.resolvePages = () => {
try {
+ require.resolve('../../../.next/package.json')
+ require.resolve('../../../.next/server/chunks/1987.js')
+ require.resolve('../../../.next/server/chunks/274.js')
+ require.resolve('../../../.next/server/chunks/4271.js')
+ require.resolve('../../../.next/server/chunks/5237.js')
+ require.resolve('../../../.next/server/chunks/9097.js')
+ require.resolve('../../../.next/server/chunks/header.js')
require.resolve('../../../.next/server/pages/_app.js')
require.resolve('../../../.next/server/pages/_document.js')
require.resolve('../../../.next/server/pages/_error.js')
@@ -18,6 +106,7 @@ exports.resolvePages = () => {
require.resolve('../../../.next/server/pages/deep/import.js')
require.resolve('../../../.next/server/pages/getServerSideProps/[id].js')
require.resolve('../../../.next/server/pages/getServerSideProps/all/[[...slug]].js')
+ require.resolve('../../../.next/server/pages/getServerSideProps/file.js')
require.resolve('../../../.next/server/pages/getServerSideProps/static.js')
require.resolve('../../../.next/server/pages/getStaticProps/[id].js')
require.resolve('../../../.next/server/pages/getStaticProps/env.js')
@@ -34,14 +123,26 @@ exports.resolvePages = () => {
require.resolve('../../../.next/server/pages/previewTest.js')
require.resolve('../../../.next/server/pages/shows/[...params].js')
require.resolve('../../../.next/server/pages/shows/[id].js')
+ require.resolve('../../../.next/server/webpack-api-runtime.js')
+ require.resolve('../../../.next/server/webpack-runtime.js')
+ require.resolve('../../../components/Header.js')
+ require.resolve('../../../hello.txt')
+ require.resolve('../../../package.json')
} catch {}
}"
`;
-exports[`onBuild() generates a file referencing all API route sources 2`] = `
-"// This file is purely to allow nft to know about these pages. It should be temporary.
+exports[`onBuild() generates a file referencing all page sources 2`] = `
+"// This file is purely to allow nft to know about these pages.
exports.resolvePages = () => {
try {
+ require.resolve('../../../.next/package.json')
+ require.resolve('../../../.next/server/chunks/1987.js')
+ require.resolve('../../../.next/server/chunks/274.js')
+ require.resolve('../../../.next/server/chunks/4271.js')
+ require.resolve('../../../.next/server/chunks/5237.js')
+ require.resolve('../../../.next/server/chunks/9097.js')
+ require.resolve('../../../.next/server/chunks/header.js')
require.resolve('../../../.next/server/pages/_app.js')
require.resolve('../../../.next/server/pages/_document.js')
require.resolve('../../../.next/server/pages/_error.js')
@@ -56,6 +157,7 @@ exports.resolvePages = () => {
require.resolve('../../../.next/server/pages/deep/import.js')
require.resolve('../../../.next/server/pages/getServerSideProps/[id].js')
require.resolve('../../../.next/server/pages/getServerSideProps/all/[[...slug]].js')
+ require.resolve('../../../.next/server/pages/getServerSideProps/file.js')
require.resolve('../../../.next/server/pages/getServerSideProps/static.js')
require.resolve('../../../.next/server/pages/getStaticProps/[id].js')
require.resolve('../../../.next/server/pages/getStaticProps/env.js')
@@ -72,43 +174,26 @@ exports.resolvePages = () => {
require.resolve('../../../.next/server/pages/previewTest.js')
require.resolve('../../../.next/server/pages/shows/[...params].js')
require.resolve('../../../.next/server/pages/shows/[id].js')
- } catch {}
-}"
-`;
-
-exports[`onBuild() generates a file referencing all page sources: for _api_hello-background-background 1`] = `
-"// This file is purely to allow nft to know about these pages.
- try {
- require.resolve('../../../.next/package.json')
- require.resolve('../../../.next/server/chunks/274.js')
- require.resolve('../../../.next/server/pages/_app.js')
- require.resolve('../../../.next/server/pages/_document.js')
- require.resolve('../../../.next/server/pages/_error.js')
- require.resolve('../../../.next/server/pages/api/hello-background.js')
- require.resolve('../../../.next/server/webpack-api-runtime.js')
- require.resolve('../../../.next/server/webpack-runtime.js')
- } catch {}"
-`;
-
-exports[`onBuild() generates a file referencing all page sources: for _api_hello-scheduled-handler 1`] = `
-"// This file is purely to allow nft to know about these pages.
- try {
- require.resolve('../../../.next/package.json')
- require.resolve('../../../.next/server/chunks/274.js')
- require.resolve('../../../.next/server/pages/_app.js')
- require.resolve('../../../.next/server/pages/_document.js')
- require.resolve('../../../.next/server/pages/_error.js')
- require.resolve('../../../.next/server/pages/api/hello-scheduled.js')
require.resolve('../../../.next/server/webpack-api-runtime.js')
require.resolve('../../../.next/server/webpack-runtime.js')
+ require.resolve('../../../components/Header.js')
+ require.resolve('../../../hello.txt')
require.resolve('../../../package.json')
- } catch {}"
+ } catch {}
+}"
`;
exports[`onBuild() generates a file referencing all when publish dir is a subdirectory 1`] = `
-"// This file is purely to allow nft to know about these pages. It should be temporary.
+"// This file is purely to allow nft to know about these pages.
exports.resolvePages = () => {
try {
+ require.resolve('../../../web/.next/package.json')
+ require.resolve('../../../web/.next/server/chunks/1987.js')
+ require.resolve('../../../web/.next/server/chunks/274.js')
+ require.resolve('../../../web/.next/server/chunks/4271.js')
+ require.resolve('../../../web/.next/server/chunks/5237.js')
+ require.resolve('../../../web/.next/server/chunks/9097.js')
+ require.resolve('../../../web/.next/server/chunks/header.js')
require.resolve('../../../web/.next/server/pages/_app.js')
require.resolve('../../../web/.next/server/pages/_document.js')
require.resolve('../../../web/.next/server/pages/_error.js')
@@ -123,6 +208,7 @@ exports.resolvePages = () => {
require.resolve('../../../web/.next/server/pages/deep/import.js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/[id].js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/all/[[...slug]].js')
+ require.resolve('../../../web/.next/server/pages/getServerSideProps/file.js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/static.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/env.js')
@@ -139,14 +225,26 @@ exports.resolvePages = () => {
require.resolve('../../../web/.next/server/pages/previewTest.js')
require.resolve('../../../web/.next/server/pages/shows/[...params].js')
require.resolve('../../../web/.next/server/pages/shows/[id].js')
+ require.resolve('../../../web/.next/server/webpack-api-runtime.js')
+ require.resolve('../../../web/.next/server/webpack-runtime.js')
+ require.resolve('../../../web/components/Header.js')
+ require.resolve('../../../web/hello.txt')
+ require.resolve('../../../web/package.json')
} catch {}
}"
`;
exports[`onBuild() generates a file referencing all when publish dir is a subdirectory 2`] = `
-"// This file is purely to allow nft to know about these pages. It should be temporary.
+"// This file is purely to allow nft to know about these pages.
exports.resolvePages = () => {
try {
+ require.resolve('../../../web/.next/package.json')
+ require.resolve('../../../web/.next/server/chunks/1987.js')
+ require.resolve('../../../web/.next/server/chunks/274.js')
+ require.resolve('../../../web/.next/server/chunks/4271.js')
+ require.resolve('../../../web/.next/server/chunks/5237.js')
+ require.resolve('../../../web/.next/server/chunks/9097.js')
+ require.resolve('../../../web/.next/server/chunks/header.js')
require.resolve('../../../web/.next/server/pages/_app.js')
require.resolve('../../../web/.next/server/pages/_document.js')
require.resolve('../../../web/.next/server/pages/_error.js')
@@ -161,6 +259,7 @@ exports.resolvePages = () => {
require.resolve('../../../web/.next/server/pages/deep/import.js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/[id].js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/all/[[...slug]].js')
+ require.resolve('../../../web/.next/server/pages/getServerSideProps/file.js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/static.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/env.js')
@@ -177,6 +276,11 @@ exports.resolvePages = () => {
require.resolve('../../../web/.next/server/pages/previewTest.js')
require.resolve('../../../web/.next/server/pages/shows/[...params].js')
require.resolve('../../../web/.next/server/pages/shows/[id].js')
+ require.resolve('../../../web/.next/server/webpack-api-runtime.js')
+ require.resolve('../../../web/.next/server/webpack-runtime.js')
+ require.resolve('../../../web/components/Header.js')
+ require.resolve('../../../web/hello.txt')
+ require.resolve('../../../web/package.json')
} catch {}
}"
`;
@@ -518,6 +622,12 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "force": false,
+ "from": "/_next/data/build-id/en/getServerSideProps/file.json",
+ "status": 200,
+ "to": "/.netlify/functions/___netlify-handler",
+ },
Object {
"force": false,
"from": "/_next/data/build-id/en/getServerSideProps/static.json",
@@ -746,6 +856,12 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "force": false,
+ "from": "/_next/data/build-id/es/getServerSideProps/file.json",
+ "status": 200,
+ "to": "/.netlify/functions/___netlify-handler",
+ },
Object {
"force": false,
"from": "/_next/data/build-id/es/getServerSideProps/static.json",
@@ -938,6 +1054,12 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "force": false,
+ "from": "/_next/data/build-id/fr/getServerSideProps/file.json",
+ "status": 200,
+ "to": "/.netlify/functions/___netlify-handler",
+ },
Object {
"force": false,
"from": "/_next/data/build-id/fr/getServerSideProps/static.json",
@@ -1236,6 +1358,12 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "force": false,
+ "from": "/es/getServerSideProps/file",
+ "status": 200,
+ "to": "/.netlify/functions/___netlify-handler",
+ },
Object {
"force": false,
"from": "/es/getServerSideProps/static",
@@ -1434,6 +1562,12 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "force": false,
+ "from": "/fr/getServerSideProps/file",
+ "status": 200,
+ "to": "/.netlify/functions/___netlify-handler",
+ },
Object {
"force": false,
"from": "/fr/getServerSideProps/static",
@@ -1584,6 +1718,12 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "force": false,
+ "from": "/getServerSideProps/file",
+ "status": 200,
+ "to": "/.netlify/functions/___netlify-handler",
+ },
Object {
"force": false,
"from": "/getServerSideProps/static",
@@ -1704,6 +1844,17 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "conditions": Object {
+ "Cookie": Array [
+ "__prerender_bypass",
+ "__next_preview_data",
+ ],
+ },
+ "from": "/next-on-netlify.png",
+ "status": 200,
+ "to": "/next-on-netlify.png",
+ },
Object {
"force": false,
"from": "/old/image",
@@ -1770,6 +1921,17 @@ Array [
"status": 200,
"to": "/.netlify/functions/___netlify-handler",
},
+ Object {
+ "conditions": Object {
+ "Cookie": Array [
+ "__prerender_bypass",
+ "__next_preview_data",
+ ],
+ },
+ "from": "/shows1.json",
+ "status": 200,
+ "to": "/shows1.json",
+ },
Object {
"force": false,
"from": "/static",
diff --git a/test/index.js b/test/index.js
index 538787a1a7..c442be43ce 100644
--- a/test/index.js
+++ b/test/index.js
@@ -1,3 +1,6 @@
+import { relative } from 'pathe'
+import { getAllPageDependencies } from '../packages/runtime/src/templates/getPageResolver'
+
jest.mock('../packages/runtime/src/helpers/utils', () => {
return {
...jest.requireActual('../packages/runtime/src/helpers/utils'),
@@ -6,7 +9,7 @@ jest.mock('../packages/runtime/src/helpers/utils', () => {
})
const Chance = require('chance')
-const { writeJSON, unlink, existsSync, readFileSync, copy, ensureDir, readJson } = require('fs-extra')
+const { writeJSON, unlink, existsSync, readFileSync, copy, ensureDir, readJson, pathExists } = require('fs-extra')
const path = require('path')
const process = require('process')
const os = require('os')
@@ -120,7 +123,14 @@ export const moveNextDist = async function (dir = '.next') {
await stubModules(['next', 'sharp'])
await ensureDir(dirname(dir))
await copy(path.join(SAMPLE_PROJECT_DIR, '.next'), path.join(process.cwd(), dir))
- await copy(path.join(SAMPLE_PROJECT_DIR, 'pages'), path.join(process.cwd(), 'pages'))
+
+ for (const file of ['pages', 'app', 'src', 'components', 'public', 'components', 'hello.txt', 'package.json']) {
+ const source = path.join(SAMPLE_PROJECT_DIR, file)
+ if (existsSync(source)) {
+ await copy(source, path.join(process.cwd(), file))
+ }
+ }
+
await rewriteAppDir(dir)
}
@@ -573,7 +583,7 @@ describe('onBuild()', () => {
}
})
- it('generates a file referencing all page sources', async () => {
+ it('generates a file referencing all API route sources', async () => {
await moveNextDist()
await nextRuntime.onBuild(defaultArgs)
@@ -584,7 +594,7 @@ describe('onBuild()', () => {
}
})
- test('generates a file referencing all API route sources', async () => {
+ test('generates a file referencing all page sources', async () => {
await moveNextDist()
await nextRuntime.onBuild(defaultArgs)
const handlerPagesFile = path.join(constants.INTERNAL_FUNCTIONS_SRC, HANDLER_FUNCTION_NAME, 'pages.js')
@@ -1247,6 +1257,23 @@ describe('function helpers', () => {
})
describe('config', () => {
+ describe('dependency tracing', () => {
+ it('extracts a list of all dependencies', async () => {
+ await moveNextDist()
+ await nextRuntime.onBuild(defaultArgs)
+ const dependencies = await getAllPageDependencies(constants.PUBLISH_DIR)
+ expect(dependencies.map((dep) => relative(process.cwd(), dep))).toMatchSnapshot()
+ })
+
+ it('extracts dependencies that exist', async () => {
+ await moveNextDist()
+ await nextRuntime.onBuild(defaultArgs)
+ const dependencies = await getAllPageDependencies(constants.PUBLISH_DIR)
+ const filesExist = await Promise.all(dependencies.map((dep) => pathExists(dep)))
+ expect(filesExist.every((exists) => exists)).toBeTruthy()
+ })
+ })
+
describe('generateCustomHeaders', () => {
// The routesManifest is the contents of the routes-manifest.json file which will already contain the generated
// header paths which take locales and base path into account which is why you'll see them in the paths already