Skip to content

Commit af0ef8a

Browse files
feat: handle large zipfiles (#241)
* feat: handle large zipfiles * chore: changes from review * chore: close the zipfile Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent 2396192 commit af0ef8a

File tree

5 files changed

+106
-16
lines changed

5 files changed

+106
-16
lines changed

plugin/package-lock.json

Lines changed: 39 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugin/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
},
4343
"dependencies": {
4444
"@netlify/functions": "^0.11.0",
45+
"chalk": "^4.1.2",
4546
"co-body": "^6.1.0",
4647
"cookie": "^0.4.1",
4748
"download": "^8.0.0",
@@ -50,7 +51,9 @@
5051
"linkfs": "^2.1.0",
5152
"multer": "^1.4.2",
5253
"node-fetch": "^2.6.1",
54+
"node-stream-zip": "^1.15.0",
5355
"pathe": "^0.2.0",
56+
"pretty-bytes": "^5.6.0",
5457
"tempy": "^1.0.0"
5558
},
5659
"devDependencies": {

plugin/src/helpers/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export function mutateConfig({
111111
path.posix.join(CACHE_DIR, 'data', '**'),
112112
path.posix.join(CACHE_DIR, 'query-engine', '**'),
113113
path.posix.join(CACHE_DIR, 'page-ssr', '**'),
114+
'!**/*.js.map',
114115
],
115116
external_node_modules: ['msgpackr-extract'],
116117
node_bundler: 'esbuild',

plugin/src/helpers/verification.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import process from 'process'
2+
3+
import { yellowBright, redBright } from 'chalk'
4+
import { stripIndent } from 'common-tags'
5+
import { existsSync, promises } from 'fs-extra'
6+
import { async as StreamZip } from 'node-stream-zip'
7+
import { relative } from 'pathe'
8+
import prettyBytes from 'pretty-bytes'
9+
10+
// 50MB, which is the documented max, though the hard max seems to be higher
11+
// eslint-disable-next-line no-magic-numbers
12+
export const LAMBDA_MAX_SIZE = 1024 * 1024 * 50
13+
14+
// eslint-disable-next-line max-statements
15+
export const checkZipSize = async (
16+
file: string,
17+
maxSize: number = LAMBDA_MAX_SIZE,
18+
): Promise<void> => {
19+
if (!existsSync(file)) {
20+
console.warn(`Could not check zip size because ${file} does not exist`)
21+
return
22+
}
23+
const fileSize = await promises.stat(file).then(({ size }) => size)
24+
if (fileSize < maxSize) {
25+
return
26+
}
27+
// We don't fail the build, because the actual hard max size is larger so it might still succeed
28+
console.log(
29+
redBright(stripIndent`
30+
The function zip ${yellowBright(
31+
relative(process.cwd(), file),
32+
)} size is ${prettyBytes(
33+
fileSize,
34+
)}, which is larger than the maximum supported size of ${prettyBytes(
35+
maxSize,
36+
)}.
37+
There are a few reasons this could happen, such as accidentally bundling a large dependency or adding lots of files to "included_files".
38+
`),
39+
)
40+
const zip = new StreamZip({ file })
41+
console.log(`Contains ${await zip.entriesCount} files`)
42+
const sortedFiles = Object.values(await zip.entries()).sort(
43+
(entryA, entryB) => entryB.size - entryA.size,
44+
)
45+
46+
const largest = {}
47+
const MAX_ROWS = 10
48+
for (let idx = 0; idx < MAX_ROWS && idx < sortedFiles.length; idx++) {
49+
largest[`${idx + 1}`] = {
50+
File: sortedFiles[idx].name,
51+
'Compressed Size': prettyBytes(sortedFiles[idx].compressedSize),
52+
'Uncompressed Size': prettyBytes(sortedFiles[idx].size),
53+
}
54+
}
55+
await zip.close()
56+
console.log(yellowBright`\n\nThese are the largest files in the zip:`)
57+
console.table(largest)
58+
}

plugin/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import fs from 'fs-extra'
66
import { normalizedCacheDir, restoreCache, saveCache } from './helpers/cache'
77
import { checkGatsbyConfig, mutateConfig, spliceConfig } from './helpers/config'
88
import { writeFunctions } from './helpers/functions'
9+
import { checkZipSize } from './helpers/verification'
910

1011
// eslint-disable-next-line no-template-curly-in-string
1112
const lmdbCacheString = 'process.cwd(), `.cache/${cacheDbFile}`'
@@ -104,8 +105,11 @@ The plugin no longer uses this and it should be deleted to avoid conflicts.\n`)
104105
}
105106

106107
export async function onPostBuild({
107-
constants: { PUBLISH_DIR },
108+
constants: { PUBLISH_DIR, FUNCTIONS_DIST },
108109
utils,
109110
}): Promise<void> {
110111
await saveCache({ publish: PUBLISH_DIR, utils })
112+
for (const func of ['api', 'dsg', 'ssr']) {
113+
await checkZipSize(path.join(FUNCTIONS_DIST, `__${func}.zip`))
114+
}
111115
}

0 commit comments

Comments
 (0)