From ec6bc21273688946b00e86a2942068a093f0fbc1 Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Fri, 5 Nov 2021 10:07:01 +0000 Subject: [PATCH 1/5] fix: check default locale exists before trying to copy --- src/helpers/files.js | 5 ++++- src/index.js | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/helpers/files.js b/src/helpers/files.js index 9d8e8a3f24..f3852b0bca 100644 --- a/src/helpers/files.js +++ b/src/helpers/files.js @@ -46,7 +46,10 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n, failBuild }) => if (i18n?.defaultLocale) { // Copy the default locale into the root - await copy(join(netlifyConfig.build.publish, i18n.defaultLocale), `${netlifyConfig.build.publish}/`) + const defaultLocaleDir = join(netlifyConfig.build.publish, i18n.defaultLocale) + if (existsSync(defaultLocaleDir)) { + await copy(defaultLocaleDir, `${netlifyConfig.build.publish}/`) + } } } diff --git a/src/index.js b/src/index.js index 388f007a41..c61b51a583 100644 --- a/src/index.js +++ b/src/index.js @@ -2,8 +2,6 @@ const { join, relative } = require('path') -const { copy, existsSync } = require('fs-extra') - const { ODB_FUNCTION_NAME } = require('./constants') const { restoreCache, saveCache } = require('./helpers/cache') const { getNextConfig, configureHandlerFunctions, generateRedirects } = require('./helpers/config') From fe35a5df79b60a4b579d96843dcdaf103c338e24 Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Fri, 5 Nov 2021 12:56:41 +0000 Subject: [PATCH 2/5] fix: use glob to move files --- src/helpers/files.js | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/helpers/files.js b/src/helpers/files.js index f3852b0bca..62f0605bc0 100644 --- a/src/helpers/files.js +++ b/src/helpers/files.js @@ -1,45 +1,43 @@ // @ts-check +const { cpus } = require('os') + const { existsSync, readJson, move, cpSync, copy, writeJson } = require('fs-extra') const pLimit = require('p-limit') const { join } = require('pathe') +const glob = require('tiny-glob') -const TEST_ROUTE = /\/\[[^/]+?](?=\/|$)/ +const TEST_ROUTE = /(|\/)\[[^/]+?](\/|\.html|$)/ const isDynamicRoute = (route) => TEST_ROUTE.test(route) exports.moveStaticPages = async ({ netlifyConfig, target, i18n, failBuild }) => { - const root = join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless') - const pagesManifestPath = join(root, 'pages-manifest.json') - if (!existsSync(pagesManifestPath)) { - failBuild(`Could not find pages manifest at ${pagesManifestPath}`) - } + console.log('Moving static page files to serve from CDN...') + const root = join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless', 'pages') + const files = [] const moveFile = async (file) => { const source = join(root, file) - // Trim the initial "pages" - const filePath = file.slice(6) - files.push(filePath) - const dest = join(netlifyConfig.build.publish, filePath) + files.push(file) + const dest = join(netlifyConfig.build.publish, source) await move(source, dest) } + // Move all static files, except error documents and nft manifests + const pages = await glob('**/!(500|404|*.nft).{html,json}', { + cwd: root, + dot: true, + }) - const pagesManifest = await readJson(pagesManifestPath) - // Arbitrary limit of 10 concurrent file moves - const limit = pLimit(10) - const promises = Object.entries(pagesManifest).map(async ([route, filePath]) => { - if ( - isDynamicRoute(route) || - !(filePath.endsWith('.html') || filePath.endsWith('.json')) || - filePath.endsWith('/404.html') || - filePath.endsWith('/500.html') - ) { + // Limit concurrent file moves to number of cpus or 2 if there is only 1 + const limit = pLimit(Math.max(2, cpus().length)) + const promises = pages.map(async (filePath) => { + if (isDynamicRoute(filePath)) { return } return limit(moveFile, filePath) }) await Promise.all(promises) - console.log(`Moved ${files.length} page files`) + console.log(`Moved ${files.length} files`) // Write the manifest for use in the serverless functions await writeJson(join(netlifyConfig.build.publish, 'static-manifest.json'), files) From ad3810e8e1f59311a03d3f40a0e13187f664c5db Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Fri, 5 Nov 2021 14:47:55 +0000 Subject: [PATCH 3/5] chore: add tests --- src/helpers/files.js | 2 +- test/__snapshots__/index.js.snap | 56 ++++++++++++++++++++++++++++++++ test/index.js | 43 ++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/helpers/files.js b/src/helpers/files.js index 62f0605bc0..f20bc8ff87 100644 --- a/src/helpers/files.js +++ b/src/helpers/files.js @@ -19,7 +19,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n, failBuild }) => const moveFile = async (file) => { const source = join(root, file) files.push(file) - const dest = join(netlifyConfig.build.publish, source) + const dest = join(netlifyConfig.build.publish, file) await move(source, dest) } // Move all static files, except error documents and nft manifests diff --git a/test/__snapshots__/index.js.snap b/test/__snapshots__/index.js.snap index c61322a691..5c693ff14e 100644 --- a/test/__snapshots__/index.js.snap +++ b/test/__snapshots__/index.js.snap @@ -68,6 +68,62 @@ exports.resolvePages = () => { }" `; +exports[`onBuild() generates static files manifest 1`] = ` +Array [ + "en/getStaticProps/1.html", + "en/getStaticProps/1.json", + "en/getStaticProps/2.html", + "en/getStaticProps/2.json", + "en/getStaticProps/static.html", + "en/getStaticProps/static.json", + "en/getStaticProps/with-revalidate.html", + "en/getStaticProps/with-revalidate.json", + "en/getStaticProps/withFallback/3.html", + "en/getStaticProps/withFallback/3.json", + "en/getStaticProps/withFallback/4.html", + "en/getStaticProps/withFallback/4.json", + "en/getStaticProps/withFallback/my/path/1.html", + "en/getStaticProps/withFallback/my/path/1.json", + "en/getStaticProps/withFallback/my/path/2.html", + "en/getStaticProps/withFallback/my/path/2.json", + "en/getStaticProps/withFallbackBlocking/3.html", + "en/getStaticProps/withFallbackBlocking/3.json", + "en/getStaticProps/withFallbackBlocking/4.html", + "en/getStaticProps/withFallbackBlocking/4.json", + "en/getStaticProps/withRevalidate/1.html", + "en/getStaticProps/withRevalidate/1.json", + "en/getStaticProps/withRevalidate/2.html", + "en/getStaticProps/withRevalidate/2.json", + "en/getStaticProps/withRevalidate/withFallback/1.html", + "en/getStaticProps/withRevalidate/withFallback/1.json", + "en/getStaticProps/withRevalidate/withFallback/2.html", + "en/getStaticProps/withRevalidate/withFallback/2.json", + "en/image.html", + "en/middle.html", + "en/previewTest.html", + "en/previewTest.json", + "en/static.html", + "es/getStaticProps/static.html", + "es/getStaticProps/static.json", + "es/getStaticProps/with-revalidate.html", + "es/getStaticProps/with-revalidate.json", + "es/image.html", + "es/middle.html", + "es/previewTest.html", + "es/previewTest.json", + "es/static.html", + "fr/getStaticProps/static.html", + "fr/getStaticProps/static.json", + "fr/getStaticProps/with-revalidate.html", + "fr/getStaticProps/with-revalidate.json", + "fr/image.html", + "fr/middle.html", + "fr/previewTest.html", + "fr/previewTest.json", + "fr/static.html", +] +`; + exports[`onBuild() writes correct redirects to netlifyConfig 1`] = ` Array [ Object { diff --git a/test/index.js b/test/index.js index e6f77c44c3..8d86f0a5e6 100644 --- a/test/index.js +++ b/test/index.js @@ -203,6 +203,49 @@ describe('onBuild()', () => { expect(existsSync(path.resolve('.next/BUILD_ID'))).toBeTruthy() }) + test('generates static files manifest', async () => { + await moveNextDist() + process.env.EXPERIMENTAL_MOVE_STATIC_PAGES = 'true' + await plugin.onBuild(defaultArgs) + expect(existsSync(path.resolve('.next/static-manifest.json'))).toBeTruthy() + const data = JSON.parse(readFileSync(path.resolve('.next/static-manifest.json'), 'utf8')) + expect(data).toMatchSnapshot() + delete process.env.EXPERIMENTAL_MOVE_STATIC_PAGES + }) + + test('moves static files to root', async () => { + await moveNextDist() + process.env.EXPERIMENTAL_MOVE_STATIC_PAGES = 'true' + await plugin.onBuild(defaultArgs) + const data = JSON.parse(readFileSync(path.resolve('.next/static-manifest.json'), 'utf8')) + + data.forEach((file) => { + expect(existsSync(path.resolve(path.join('.next', file)))).toBeTruthy() + expect(existsSync(path.resolve(path.join('.next', 'server', 'pages', file)))).toBeFalsy() + }) + + delete process.env.EXPERIMENTAL_MOVE_STATIC_PAGES + }) + + test('copies default locale files to top level', async () => { + await moveNextDist() + process.env.EXPERIMENTAL_MOVE_STATIC_PAGES = 'true' + await plugin.onBuild(defaultArgs) + const data = JSON.parse(readFileSync(path.resolve('.next/static-manifest.json'), 'utf8')) + + const locale = 'en/' + + data.forEach((file) => { + if (!file.startsWith(locale)) { + return + } + const trimmed = file.substring(locale.length) + expect(existsSync(path.resolve(path.join('.next', trimmed)))).toBeTruthy() + }) + + delete process.env.EXPERIMENTAL_MOVE_STATIC_PAGES + }) + test('sets correct config', async () => { await moveNextDist() From 7ec3740085a86e6eda3f7ac2ce330bfd2262b90f Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Fri, 5 Nov 2021 14:54:45 +0000 Subject: [PATCH 4/5] chore: exclude nft from zip --- src/helpers/config.js | 1 + src/helpers/files.js | 2 +- test/index.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/config.js b/src/helpers/config.js index 0b1589d985..ba1490d9b9 100644 --- a/src/helpers/config.js +++ b/src/helpers/config.js @@ -150,6 +150,7 @@ exports.configureHandlerFunctions = ({ netlifyConfig, publish, ignore = [] }) => `${publish}/*.json`, `${publish}/BUILD_ID`, `${publish}/static/chunks/webpack-middleware*.js`, + `!${publish}/server/**/*.js.nft.json`, ...ignore.map((path) => `!${slash(path)}`), ) diff --git a/src/helpers/files.js b/src/helpers/files.js index f20bc8ff87..75859595c2 100644 --- a/src/helpers/files.js +++ b/src/helpers/files.js @@ -23,7 +23,7 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n, failBuild }) => await move(source, dest) } // Move all static files, except error documents and nft manifests - const pages = await glob('**/!(500|404|*.nft).{html,json}', { + const pages = await glob('**/!(500|404|*.js.nft).{html,json}', { cwd: root, dot: true, }) diff --git a/test/index.js b/test/index.js index 8d86f0a5e6..2dc0a1f412 100644 --- a/test/index.js +++ b/test/index.js @@ -256,6 +256,7 @@ describe('onBuild()', () => { '.next/*.json', '.next/BUILD_ID', '.next/static/chunks/webpack-middleware*.js', + '!.next/server/**/*.js.nft.json', '!../node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*', `!node_modules/next/dist/server/lib/squoosh/**/*.wasm`, `!node_modules/next/dist/next-server/server/lib/squoosh/**/*.wasm`, From f1474671ba44d9cd46781fdc0c16b8987fef74f9 Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Fri, 5 Nov 2021 16:25:59 +0000 Subject: [PATCH 5/5] chore: windows! --- src/helpers/files.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/files.js b/src/helpers/files.js index 75859595c2..72bda85c75 100644 --- a/src/helpers/files.js +++ b/src/helpers/files.js @@ -4,6 +4,7 @@ const { cpus } = require('os') const { existsSync, readJson, move, cpSync, copy, writeJson } = require('fs-extra') const pLimit = require('p-limit') const { join } = require('pathe') +const slash = require('slash') const glob = require('tiny-glob') const TEST_ROUTE = /(|\/)\[[^/]+?](\/|\.html|$)/ @@ -30,7 +31,8 @@ exports.moveStaticPages = async ({ netlifyConfig, target, i18n, failBuild }) => // Limit concurrent file moves to number of cpus or 2 if there is only 1 const limit = pLimit(Math.max(2, cpus().length)) - const promises = pages.map(async (filePath) => { + const promises = pages.map(async (rawPath) => { + const filePath = slash(rawPath) if (isDynamicRoute(filePath)) { return }