Skip to content

Commit cc58495

Browse files
committed
Merge branch 'main' into fix/windows-require-path
2 parents 6e5bb52 + ef2da0d commit cc58495

File tree

7 files changed

+55
-24
lines changed

7 files changed

+55
-24
lines changed

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ publish = ".next"
3131
package = "@netlify/plugin-nextjs"
3232
```
3333

34-
If you previously set `target: "serverless"`, `node_bundler` or `external_node_modules` in your `next.config.js` these are no longer needed and can be removed.
34+
If you previously set `target: "serverless"` or a custom `distDir` in your `next.config.js`, or set `node_bundler` or `external_node_modules` in your `netlify.toml` these are no longer needed and can be removed.
35+
36+
If you are using a monorepo you will need to change `publish` to point to the full path to the built `.next` directory, which may be in a subdirectory. If you have changed your `distDir` then it will need to match that.
37+
38+
If you are using Nx, then you will need to point `publish` to the folder inside `dist`, e.g. `dist/apps/myapp/.next`.
3539

3640
## Beta feedback
3741

docs/large-functions.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Troubleshooting large functions
2+
3+
You may see an error about generated functions being too large. This is because when deploying your site it is packaged into a zipfile, which is limited by AWS to 50MB in size.
4+
There are two possible causes for this, each with its own solution. The list of largest files shown in the build logs will help you see what the cause is.
5+
6+
- **Large dependencies**
7+
This is the most common cause of the problem. Some node modules are very large, mostly those that include native modules. Examples include `electron` and `chromium`. The function bundler is usually able to find out which modules are actually used by your code, but sometimes it will incorrectly include unneeded modules. If this is the case, you can either remove the module from your dependencies if you installed it yourself, or exclude it manually by adding something like this to your `netlify.toml`, changing the value according to the problematic module:
8+
9+
```toml
10+
[functions]
11+
excluded_files = "node_modules/electron/**/*"
12+
```
13+
If you do need large modules (e.g. if you are running Puppeteer in a Next API route), consider changing to a Netlify function.
14+
15+
- **Large numbers of pre-rendered pages**
16+
If you have a very large number of pre-rendered pages, these can take up a lot of space in the function. There are two approaches to fixing this. One is to consider deferring the building of the pages. If you set `fallback = "blocking"`, the rendering will be deferred until the first user requests the page. This is a good choice for low-traffic pages. It reduces build and deploy time, and can make your bundle a lot smaller. The other option is to enable an experimental feature that moves static files out of the function bundle. To do this, set the environment variable `EXPERIMENTAL_MOVE_STATIC_PAGES` to true.

src/helpers/config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @ts-check
22
const { readJSON } = require('fs-extra')
33
const { join, dirname, relative } = require('pathe')
4+
const slash = require('slash')
45

56
const defaultFailBuild = (message, { error }) => {
67
throw new Error(`${message}\n${error && error.stack}`)
@@ -131,7 +132,7 @@ exports.configureHandlerFunctions = ({ netlifyConfig, publish, ignore = [] }) =>
131132
`${publish}/serverless/**`,
132133
`${publish}/*.json`,
133134
`${publish}/BUILD_ID`,
134-
...ignore.map((path) => `!${path}`),
135+
...ignore.map((path) => `!${slash(path)}`),
135136
)
136137

137138
const nextRoot = resolveModuleRoot('next')

src/helpers/verification.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ exports.checkForRootPublish = ({ publish, failBuild }) => {
5959
// 50MB, which is the documented max, though the hard max seems to be higher
6060
const LAMBDA_MAX_SIZE = 1024 * 1024 * 50
6161

62-
exports.checkZipSize = async (file) => {
62+
exports.checkZipSize = async (file, maxSize = LAMBDA_MAX_SIZE) => {
6363
if (!existsSync(file)) {
6464
console.warn(`Could not check zip size because ${file} does not exist`)
6565
return
6666
}
6767
const size = await promises.stat(file).then(({ size }) => size)
68-
if (size < LAMBDA_MAX_SIZE) {
68+
if (size < maxSize) {
6969
return
7070
}
7171
// We don't fail the build, because the actual hard max size is larger so it might still succeed
@@ -74,7 +74,7 @@ exports.checkZipSize = async (file) => {
7474
7575
The function zip ${yellowBright(relative(process.cwd(), file))} size is ${prettyBytes(
7676
size,
77-
)}, which is larger than the maximum supported size of ${prettyBytes(LAMBDA_MAX_SIZE)}.
77+
)}, which is larger than the maximum supported size of ${prettyBytes(maxSize)}.
7878
There are a few reasons this could happen. You may have accidentally bundled a large dependency, or you might have a
7979
large number of pre-rendered pages included.
8080
@@ -85,7 +85,7 @@ exports.checkZipSize = async (file) => {
8585
const sortedFiles = Object.values(await zip.entries()).sort((a, b) => b.size - a.size)
8686

8787
const largest = {}
88-
for (let i = 0; i < 10; i++) {
88+
for (let i = 0; i < 10 && i < sortedFiles.length; i++) {
8989
largest[`${i + 1}`] = {
9090
File: sortedFiles[i].name,
9191
'Compressed Size': prettyBytes(sortedFiles[i].compressedSize),
@@ -94,14 +94,17 @@ exports.checkZipSize = async (file) => {
9494
}
9595
console.log(yellowBright`\n\nThese are the largest files in the zip:`)
9696
console.table(largest)
97+
console.log(
98+
greenBright`\n\nFor more information on fixing this, see ${blueBright`https://ntl.fyi/large-next-functions`}`,
99+
)
97100
}
98101

99102
exports.logBetaMessage = () =>
100103
console.log(
101104
greenBright(
102105
outdent`
103106
Thank you for trying the Essential Next.js beta plugin.
104-
Please share feedback at ${blueBright`https://ntl.fyi/next-beta-feedback`}
107+
Please share feedback (both good and bad) at ${blueBright`https://ntl.fyi/next-beta-feedback`}
105108
`,
106109
),
107110
)

src/templates/getHandler.js

+5
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ const makeHandler =
136136
multiValueHeaders['cache-control'] = ['no-cache']
137137
}
138138

139+
// Sending SWR headers causes undefined behaviour with the Netlify CDN
140+
if (multiValueHeaders['cache-control']?.[0]?.includes('stale-while-revalidate')) {
141+
multiValueHeaders['cache-control'] = ['public, max-age=0, must-revalidate']
142+
}
143+
139144
return {
140145
...result,
141146
multiValueHeaders,

src/templates/getPageResolver.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
const {
2-
posix: { resolve, join, relative },
3-
} = require('path')
4-
51
const { outdent } = require('outdent')
2+
const { resolve, join, relative } = require('pathe')
63
const slash = require('slash')
74
const glob = require('tiny-glob')
85

@@ -13,13 +10,13 @@ const { HANDLER_FUNCTION_NAME } = require('../constants')
1310

1411
exports.getPageResolver = async ({ netlifyConfig, target }) => {
1512
const functionDir = resolve(join('.netlify', 'functions', HANDLER_FUNCTION_NAME))
16-
const root = join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless', 'pages')
13+
const root = join(slash(netlifyConfig.build.publish), target === 'server' ? 'server' : 'serverless', 'pages')
1714

1815
const pages = await glob('**/*.js', {
1916
cwd: root,
2017
dot: true,
2118
})
22-
const pageFiles = pages.map((page) => `require.resolve('${relative(functionDir, join(root, slash(page)))}')`).sort()
19+
const pageFiles = pages.map((page) => `require.resolve('${relative(functionDir, join(root, page))}')`).sort()
2320

2421
return outdent`
2522
// This file is purely to allow nft to know about these pages. It should be temporary.

test/index.js

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { writeJSON, unlink, existsSync, readFileSync, copy, ensureDir } = require('fs-extra')
1+
const { writeJSON, unlink, existsSync, readFileSync, copy, ensureDir, readJson } = require('fs-extra')
22
const path = require('path')
33
const process = require('process')
44
const os = require('os')
@@ -41,6 +41,14 @@ const changeCwd = function (cwd) {
4141
const onBuildHasRun = (netlifyConfig) =>
4242
Boolean(netlifyConfig.functions[HANDLER_FUNCTION_NAME]?.included_files?.some((file) => file.includes('BUILD_ID')))
4343

44+
const rewriteAppDir = async function () {
45+
const manifest = path.join('.next', 'required-server-files.json')
46+
const manifestContent = await readJson(manifest)
47+
manifestContent.appDir = process.cwd()
48+
49+
await writeJSON(manifest, manifestContent)
50+
}
51+
4452
// Move .next from sample project to current directory
4553
const moveNextDist = async function () {
4654
await stubModules(['next', 'sharp'])
@@ -225,20 +233,17 @@ describe('onBuild()', () => {
225233
})
226234

227235
test('generates entrypoints with correct references', async () => {
236+
await moveNextDist()
237+
await rewriteAppDir()
238+
239+
await plugin.onBuild(defaultArgs)
240+
228241
const handlerFile = path.join(
229-
SAMPLE_PROJECT_DIR,
230-
'.netlify',
231-
'functions-internal',
242+
constants.INTERNAL_FUNCTIONS_SRC,
232243
HANDLER_FUNCTION_NAME,
233244
`${HANDLER_FUNCTION_NAME}.js`,
234245
)
235-
const odbHandlerFile = path.join(
236-
SAMPLE_PROJECT_DIR,
237-
'.netlify',
238-
'functions-internal',
239-
ODB_FUNCTION_NAME,
240-
`${ODB_FUNCTION_NAME}.js`,
241-
)
246+
const odbHandlerFile = path.join(constants.INTERNAL_FUNCTIONS_SRC, ODB_FUNCTION_NAME, `${ODB_FUNCTION_NAME}.js`)
242247
expect(existsSync(handlerFile)).toBeTruthy()
243248
expect(existsSync(odbHandlerFile)).toBeTruthy()
244249

0 commit comments

Comments
 (0)