Skip to content

Commit 9989c0a

Browse files
authored
feat: warn if zip is too large, and log the largest files (#730)
* feat: warn if zip is too large, and log the largest files * chore: fix test
1 parent 3da9c77 commit 9989c0a

File tree

5 files changed

+75
-11
lines changed

5 files changed

+75
-11
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,12 @@
5858
"chalk": "^4.1.2",
5959
"fs-extra": "^10.0.0",
6060
"moize": "^6.1.0",
61+
"node-stream-zip": "^1.15.0",
6162
"node-fetch": "^2.6.5",
6263
"outdent": "^0.8.0",
6364
"p-limit": "^3.1.0",
6465
"pathe": "^0.2.0",
66+
"pretty-bytes": "^5.6.0",
6567
"semver": "^7.3.5",
6668
"slash": "^3.0.0",
6769
"tiny-glob": "^0.2.9"

src/helpers/verification.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
const { existsSync, promises } = require('fs')
12
const path = require('path')
3+
const { relative } = require('path')
24

3-
const { yellowBright, greenBright, blueBright } = require('chalk')
4-
const { existsSync } = require('fs-extra')
5+
const { yellowBright, greenBright, blueBright, redBright } = require('chalk')
6+
const { async: StreamZip } = require('node-stream-zip')
57
const outdent = require('outdent')
8+
const prettyBytes = require('pretty-bytes')
69
const { satisfies } = require('semver')
710

811
exports.verifyBuildTarget = (target) => {
@@ -53,6 +56,46 @@ exports.checkForRootPublish = ({ publish, failBuild }) => {
5356
}
5457
}
5558

59+
// 50MB, which is the documented max, though the hard max seems to be higher
60+
const LAMBDA_MAX_SIZE = 1024 * 1024 * 50
61+
62+
exports.checkZipSize = async (file) => {
63+
if (!existsSync(file)) {
64+
console.warn(`Could not check zip size because ${file} does not exist`)
65+
return
66+
}
67+
const size = await promises.stat(file).then(({ size }) => size)
68+
if (size < LAMBDA_MAX_SIZE) {
69+
return
70+
}
71+
// We don't fail the build, because the actual hard max size is larger so it might still succeed
72+
console.log(
73+
redBright(outdent`
74+
75+
The function zip ${yellowBright(relative(process.cwd(), file))} size is ${prettyBytes(
76+
size,
77+
)}, which is larger than the maximum supported size of ${prettyBytes(LAMBDA_MAX_SIZE)}.
78+
There are a few reasons this could happen. You may have accidentally bundled a large dependency, or you might have a
79+
large number of pre-rendered pages included.
80+
81+
`),
82+
)
83+
const zip = new StreamZip({ file })
84+
console.log(`Contains ${await zip.entriesCount} files`)
85+
const sortedFiles = Object.values(await zip.entries()).sort((a, b) => b.size - a.size)
86+
87+
const largest = {}
88+
for (let i = 0; i < 10; i++) {
89+
largest[`${i + 1}`] = {
90+
File: sortedFiles[i].name,
91+
'Compressed Size': prettyBytes(sortedFiles[i].compressedSize),
92+
'Uncompressed Size': prettyBytes(sortedFiles[i].size),
93+
}
94+
}
95+
console.log(yellowBright`\n\nThese are the largest files in the zip:`)
96+
console.table(largest)
97+
}
98+
5699
exports.logBetaMessage = () =>
57100
console.log(
58101
greenBright(

src/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { join, relative } = require('path')
44

55
const { copy, existsSync } = require('fs-extra')
66

7+
const { ODB_FUNCTION_NAME } = require('./constants')
78
const { restoreCache, saveCache } = require('./helpers/cache')
89
const { getNextConfig, configureHandlerFunctions, generateRedirects } = require('./helpers/config')
910
const { moveStaticPages, movePublicFiles } = require('./helpers/files')
@@ -14,6 +15,7 @@ const {
1415
verifyBuildTarget,
1516
checkForRootPublish,
1617
logBetaMessage,
18+
checkZipSize,
1719
} = require('./helpers/verification')
1820

1921
module.exports = {
@@ -68,8 +70,9 @@ module.exports = {
6870
})
6971
},
7072

71-
async onPostBuild({ netlifyConfig, utils: { cache } }) {
72-
return saveCache({ cache, publish: netlifyConfig.build.publish })
73+
async onPostBuild({ netlifyConfig, utils: { cache }, constants }) {
74+
await saveCache({ cache, publish: netlifyConfig.build.publish })
75+
await checkZipSize(join(process.cwd(), constants.FUNCTIONS_DIST, `${ODB_FUNCTION_NAME}.zip`))
7376
},
7477
onEnd() {
7578
logBetaMessage()

test/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const SAMPLE_PROJECT_DIR = `${__dirname}/../demo`
1414
const constants = {
1515
INTERNAL_FUNCTIONS_SRC: '.netlify/internal-functions',
1616
PUBLISH_DIR: '.next',
17+
FUNCTIONS_DIST: '.netlify/functions',
1718
}
1819
const utils = {
1920
build: {
@@ -226,8 +227,6 @@ describe('onBuild()', () => {
226227

227228
describe('onPostBuild', () => {
228229
test('saves cache with right paths', async () => {
229-
await useFixture('dist_dir_next_config')
230-
231230
const save = jest.fn()
232231

233232
await plugin.onPostBuild({

0 commit comments

Comments
 (0)