Skip to content

Commit faeb703

Browse files
fix: use glob to select files to move (#768)
* fix: check default locale exists before trying to copy * fix: use glob to move files * chore: add tests * chore: exclude nft from zip * chore: windows! Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent 4a03e3a commit faeb703

File tree

5 files changed

+126
-24
lines changed

5 files changed

+126
-24
lines changed

src/helpers/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ exports.configureHandlerFunctions = ({ netlifyConfig, publish, ignore = [] }) =>
150150
`${publish}/*.json`,
151151
`${publish}/BUILD_ID`,
152152
`${publish}/static/chunks/webpack-middleware*.js`,
153+
`!${publish}/server/**/*.js.nft.json`,
153154
...ignore.map((path) => `!${slash(path)}`),
154155
)
155156

src/helpers/files.js

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,55 @@
11
// @ts-check
2+
const { cpus } = require('os')
3+
24
const { existsSync, readJson, move, cpSync, copy, writeJson } = require('fs-extra')
35
const pLimit = require('p-limit')
46
const { join } = require('pathe')
7+
const slash = require('slash')
8+
const glob = require('tiny-glob')
59

6-
const TEST_ROUTE = /\/\[[^/]+?](?=\/|$)/
10+
const TEST_ROUTE = /(|\/)\[[^/]+?](\/|\.html|$)/
711

812
const isDynamicRoute = (route) => TEST_ROUTE.test(route)
913

1014
exports.moveStaticPages = async ({ netlifyConfig, target, i18n, failBuild }) => {
11-
const root = join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless')
12-
const pagesManifestPath = join(root, 'pages-manifest.json')
13-
if (!existsSync(pagesManifestPath)) {
14-
failBuild(`Could not find pages manifest at ${pagesManifestPath}`)
15-
}
15+
console.log('Moving static page files to serve from CDN...')
16+
const root = join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless', 'pages')
17+
1618
const files = []
1719

1820
const moveFile = async (file) => {
1921
const source = join(root, file)
20-
// Trim the initial "pages"
21-
const filePath = file.slice(6)
22-
files.push(filePath)
23-
const dest = join(netlifyConfig.build.publish, filePath)
22+
files.push(file)
23+
const dest = join(netlifyConfig.build.publish, file)
2424
await move(source, dest)
2525
}
26+
// Move all static files, except error documents and nft manifests
27+
const pages = await glob('**/!(500|404|*.js.nft).{html,json}', {
28+
cwd: root,
29+
dot: true,
30+
})
2631

27-
const pagesManifest = await readJson(pagesManifestPath)
28-
// Arbitrary limit of 10 concurrent file moves
29-
const limit = pLimit(10)
30-
const promises = Object.entries(pagesManifest).map(async ([route, filePath]) => {
31-
if (
32-
isDynamicRoute(route) ||
33-
!(filePath.endsWith('.html') || filePath.endsWith('.json')) ||
34-
filePath.endsWith('/404.html') ||
35-
filePath.endsWith('/500.html')
36-
) {
32+
// Limit concurrent file moves to number of cpus or 2 if there is only 1
33+
const limit = pLimit(Math.max(2, cpus().length))
34+
const promises = pages.map(async (rawPath) => {
35+
const filePath = slash(rawPath)
36+
if (isDynamicRoute(filePath)) {
3737
return
3838
}
3939
return limit(moveFile, filePath)
4040
})
4141
await Promise.all(promises)
42-
console.log(`Moved ${files.length} page files`)
42+
console.log(`Moved ${files.length} files`)
4343

4444
// Write the manifest for use in the serverless functions
4545
await writeJson(join(netlifyConfig.build.publish, 'static-manifest.json'), files)
4646

4747
if (i18n?.defaultLocale) {
4848
// Copy the default locale into the root
49-
await copy(join(netlifyConfig.build.publish, i18n.defaultLocale), `${netlifyConfig.build.publish}/`)
49+
const defaultLocaleDir = join(netlifyConfig.build.publish, i18n.defaultLocale)
50+
if (existsSync(defaultLocaleDir)) {
51+
await copy(defaultLocaleDir, `${netlifyConfig.build.publish}/`)
52+
}
5053
}
5154
}
5255

src/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
const { join, relative } = require('path')
44

5-
const { copy, existsSync } = require('fs-extra')
6-
75
const { ODB_FUNCTION_NAME } = require('./constants')
86
const { restoreCache, saveCache } = require('./helpers/cache')
97
const { getNextConfig, configureHandlerFunctions, generateRedirects } = require('./helpers/config')

test/__snapshots__/index.js.snap

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,62 @@ exports.resolvePages = () => {
6868
}"
6969
`;
7070

71+
exports[`onBuild() generates static files manifest 1`] = `
72+
Array [
73+
"en/getStaticProps/1.html",
74+
"en/getStaticProps/1.json",
75+
"en/getStaticProps/2.html",
76+
"en/getStaticProps/2.json",
77+
"en/getStaticProps/static.html",
78+
"en/getStaticProps/static.json",
79+
"en/getStaticProps/with-revalidate.html",
80+
"en/getStaticProps/with-revalidate.json",
81+
"en/getStaticProps/withFallback/3.html",
82+
"en/getStaticProps/withFallback/3.json",
83+
"en/getStaticProps/withFallback/4.html",
84+
"en/getStaticProps/withFallback/4.json",
85+
"en/getStaticProps/withFallback/my/path/1.html",
86+
"en/getStaticProps/withFallback/my/path/1.json",
87+
"en/getStaticProps/withFallback/my/path/2.html",
88+
"en/getStaticProps/withFallback/my/path/2.json",
89+
"en/getStaticProps/withFallbackBlocking/3.html",
90+
"en/getStaticProps/withFallbackBlocking/3.json",
91+
"en/getStaticProps/withFallbackBlocking/4.html",
92+
"en/getStaticProps/withFallbackBlocking/4.json",
93+
"en/getStaticProps/withRevalidate/1.html",
94+
"en/getStaticProps/withRevalidate/1.json",
95+
"en/getStaticProps/withRevalidate/2.html",
96+
"en/getStaticProps/withRevalidate/2.json",
97+
"en/getStaticProps/withRevalidate/withFallback/1.html",
98+
"en/getStaticProps/withRevalidate/withFallback/1.json",
99+
"en/getStaticProps/withRevalidate/withFallback/2.html",
100+
"en/getStaticProps/withRevalidate/withFallback/2.json",
101+
"en/image.html",
102+
"en/middle.html",
103+
"en/previewTest.html",
104+
"en/previewTest.json",
105+
"en/static.html",
106+
"es/getStaticProps/static.html",
107+
"es/getStaticProps/static.json",
108+
"es/getStaticProps/with-revalidate.html",
109+
"es/getStaticProps/with-revalidate.json",
110+
"es/image.html",
111+
"es/middle.html",
112+
"es/previewTest.html",
113+
"es/previewTest.json",
114+
"es/static.html",
115+
"fr/getStaticProps/static.html",
116+
"fr/getStaticProps/static.json",
117+
"fr/getStaticProps/with-revalidate.html",
118+
"fr/getStaticProps/with-revalidate.json",
119+
"fr/image.html",
120+
"fr/middle.html",
121+
"fr/previewTest.html",
122+
"fr/previewTest.json",
123+
"fr/static.html",
124+
]
125+
`;
126+
71127
exports[`onBuild() writes correct redirects to netlifyConfig 1`] = `
72128
Array [
73129
Object {

test/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,49 @@ describe('onBuild()', () => {
203203
expect(existsSync(path.resolve('.next/BUILD_ID'))).toBeTruthy()
204204
})
205205

206+
test('generates static files manifest', async () => {
207+
await moveNextDist()
208+
process.env.EXPERIMENTAL_MOVE_STATIC_PAGES = 'true'
209+
await plugin.onBuild(defaultArgs)
210+
expect(existsSync(path.resolve('.next/static-manifest.json'))).toBeTruthy()
211+
const data = JSON.parse(readFileSync(path.resolve('.next/static-manifest.json'), 'utf8'))
212+
expect(data).toMatchSnapshot()
213+
delete process.env.EXPERIMENTAL_MOVE_STATIC_PAGES
214+
})
215+
216+
test('moves static files to root', async () => {
217+
await moveNextDist()
218+
process.env.EXPERIMENTAL_MOVE_STATIC_PAGES = 'true'
219+
await plugin.onBuild(defaultArgs)
220+
const data = JSON.parse(readFileSync(path.resolve('.next/static-manifest.json'), 'utf8'))
221+
222+
data.forEach((file) => {
223+
expect(existsSync(path.resolve(path.join('.next', file)))).toBeTruthy()
224+
expect(existsSync(path.resolve(path.join('.next', 'server', 'pages', file)))).toBeFalsy()
225+
})
226+
227+
delete process.env.EXPERIMENTAL_MOVE_STATIC_PAGES
228+
})
229+
230+
test('copies default locale files to top level', async () => {
231+
await moveNextDist()
232+
process.env.EXPERIMENTAL_MOVE_STATIC_PAGES = 'true'
233+
await plugin.onBuild(defaultArgs)
234+
const data = JSON.parse(readFileSync(path.resolve('.next/static-manifest.json'), 'utf8'))
235+
236+
const locale = 'en/'
237+
238+
data.forEach((file) => {
239+
if (!file.startsWith(locale)) {
240+
return
241+
}
242+
const trimmed = file.substring(locale.length)
243+
expect(existsSync(path.resolve(path.join('.next', trimmed)))).toBeTruthy()
244+
})
245+
246+
delete process.env.EXPERIMENTAL_MOVE_STATIC_PAGES
247+
})
248+
206249
test('sets correct config', async () => {
207250
await moveNextDist()
208251

@@ -213,6 +256,7 @@ describe('onBuild()', () => {
213256
'.next/*.json',
214257
'.next/BUILD_ID',
215258
'.next/static/chunks/webpack-middleware*.js',
259+
'!.next/server/**/*.js.nft.json',
216260
'!../node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*',
217261
`!node_modules/next/dist/server/lib/squoosh/**/*.wasm`,
218262
`!node_modules/next/dist/next-server/server/lib/squoosh/**/*.wasm`,

0 commit comments

Comments
 (0)