Skip to content

Commit efba43e

Browse files
authored
fix: correctly exclude files (#720)
* fix: correctly exclude files in monorepos * fix: update tests * fix: cross-platform paths * fix: remove some exclusions * fix: normalize paths * fix: better error handling for next server imports * chore: release 4.0.0-beta.2 Release-as: 4.0.0-beta.2
1 parent ff09cae commit efba43e

File tree

6 files changed

+85
-43
lines changed

6 files changed

+85
-43
lines changed

package-lock.json

+13-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"fs-extra": "^10.0.0",
6060
"moize": "^6.1.0",
6161
"outdent": "^0.8.0",
62+
"pathe": "^0.2.0",
6263
"semver": "^7.3.5",
6364
"slash": "^3.0.0",
6465
"tiny-glob": "^0.2.9"

src/helpers/config.js

+33-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// @ts-check
2-
const { join } = require('path')
3-
42
const { readJSON } = require('fs-extra')
3+
const { join, dirname, relative } = require('pathe')
54

65
const defaultFailBuild = (message, { error }) => {
76
throw new Error(`${message}\n${error && error.stack}`)
@@ -100,17 +99,29 @@ exports.generateRedirects = async ({ netlifyConfig, basePath, i18n }) => {
10099

101100
exports.getNextConfig = async function getNextConfig({ publish, failBuild = defaultFailBuild }) {
102101
try {
103-
const { config, appDir } = await readJSON(join(publish, 'required-server-files.json'))
102+
const { config, appDir, ignore } = await readJSON(join(publish, 'required-server-files.json'))
104103
if (!config) {
105104
return failBuild('Error loading your Next config')
106105
}
107-
return { ...config, appDir }
106+
return { ...config, appDir, ignore }
108107
} catch (error) {
109108
return failBuild('Error loading your Next config', { error })
110109
}
111110
}
112111

113-
exports.configureHandlerFunctions = ({ netlifyConfig, publish }) => {
112+
const resolveModuleRoot = (moduleName) => {
113+
try {
114+
return dirname(relative(process.cwd(), require.resolve(`${moduleName}/package.json`, { paths: [process.cwd()] })))
115+
} catch (error) {
116+
return null
117+
}
118+
}
119+
120+
exports.configureHandlerFunctions = ({ netlifyConfig, publish, ignore = [] }) => {
121+
/* eslint-disable no-underscore-dangle */
122+
netlifyConfig.functions._ipx ||= {}
123+
netlifyConfig.functions._ipx.node_bundler = 'esbuild'
124+
/* eslint-enable no-underscore-dangle */
114125
;[HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME].forEach((functionName) => {
115126
netlifyConfig.functions[functionName] ||= { included_files: [], external_node_modules: [] }
116127
netlifyConfig.functions[functionName].node_bundler = 'nft'
@@ -120,16 +131,23 @@ exports.configureHandlerFunctions = ({ netlifyConfig, publish }) => {
120131
`${publish}/serverless/**`,
121132
`${publish}/*.json`,
122133
`${publish}/BUILD_ID`,
123-
'!node_modules/@next/swc-*/**/*',
124-
'!node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*',
125-
'!node_modules/next/dist/pages/**/*',
126-
`!node_modules/next/dist/server/lib/squoosh/**/*.wasm`,
127-
`!node_modules/next/dist/next-server/server/lib/squoosh/**/*.wasm`,
128-
'!node_modules/next/dist/compiled/webpack/(bundle4|bundle5).js',
129-
'!node_modules/react/**/*.development.js',
130-
'!node_modules/react-dom/**/*.development.js',
131-
'!node_modules/use-subscription/**/*.development.js',
132-
'!node_modules/sharp/**/*',
134+
...ignore.map((path) => `!${path}`),
133135
)
136+
137+
const nextRoot = resolveModuleRoot('next')
138+
if (nextRoot) {
139+
netlifyConfig.functions[functionName].included_files.push(
140+
`!${nextRoot}/dist/server/lib/squoosh/**/*.wasm`,
141+
`!${nextRoot}/dist/next-server/server/lib/squoosh/**/*.wasm`,
142+
`!${nextRoot}/dist/compiled/webpack/bundle4.js`,
143+
`!${nextRoot}/dist/compiled/webpack/bundle5.js`,
144+
`!${nextRoot}/dist/compiled/terser/bundle.min.js`,
145+
)
146+
}
147+
148+
const sharpRoot = resolveModuleRoot('sharp')
149+
if (sharpRoot) {
150+
netlifyConfig.functions[functionName].included_files.push(`!${sharpRoot}/**/*`)
151+
}
134152
})
135153
}

src/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ module.exports = {
4343

4444
checkNextSiteHasBuilt({ publish, failBuild })
4545

46-
const { appDir, basePath, i18n, images, target } = await getNextConfig({ publish, failBuild })
46+
const { appDir, basePath, i18n, images, target, ignore } = await getNextConfig({ publish, failBuild })
4747

4848
verifyBuildTarget(target)
4949

50-
configureHandlerFunctions({ netlifyConfig, publish: relative(process.cwd(), publish) })
50+
configureHandlerFunctions({ netlifyConfig, ignore, publish: relative(process.cwd(), publish) })
5151

5252
await generateFunctions(constants, appDir)
5353
await generatePagesResolver({ netlifyConfig, target, constants })

src/templates/getHandler.js

+16-13
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,33 @@ const makeHandler =
77
() =>
88
// We return a function and then call `toString()` on it to serialise it as the launcher function
99
(conf, app) => {
10+
// This is just so nft knows about the page entrypoints
11+
try {
12+
// eslint-disable-next-line node/no-missing-require
13+
require.resolve('./pages.js')
14+
} catch {}
15+
1016
let NextServer
1117
try {
1218
// next >= 11.0.1. Yay breaking changes in patch releases!
1319
NextServer = require('next/dist/server/next-server').default
14-
} catch {
20+
} catch (error) {
21+
if (!error.message.includes("Cannot find module 'next/dist/server/next-server'")) {
22+
// A different error, so rethrow it
23+
throw error
24+
}
1525
// Probably an old version of next
1626
}
1727

18-
// This is just so nft knows about the page entrypoints
19-
try {
20-
// eslint-disable-next-line node/no-missing-require
21-
require.resolve('./pages.js')
22-
} catch {}
23-
2428
if (!NextServer) {
2529
try {
2630
// next < 11.0.1
2731
// eslint-disable-next-line node/no-missing-require, import/no-unresolved
2832
NextServer = require('next/dist/next-server/server/next-server').default
29-
} catch {
33+
} catch (error) {
34+
if (!error.message.includes("Cannot find module 'next/dist/next-server/server/next-server'")) {
35+
throw error
36+
}
3037
throw new Error('Could not find Next.js server')
3138
}
3239
}
@@ -66,11 +73,7 @@ const makeHandler =
6673
}
6774
}
6875

69-
if (
70-
multiValueHeaders['set-cookie'] &&
71-
multiValueHeaders['set-cookie'][0] &&
72-
multiValueHeaders['set-cookie'][0].includes('__prerender_bypass')
73-
) {
76+
if (multiValueHeaders['set-cookie']?.[0]?.includes('__prerender_bypass')) {
7477
delete multiValueHeaders.etag
7578
multiValueHeaders['cache-control'] = ['no-cache']
7679
}

test/index.js

+20-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const { writeJSON, unlink, existsSync, readFileSync, copy } = require('fs-extra')
1+
const { writeJSON, unlink, existsSync, readFileSync, copy, ensureDir } = require('fs-extra')
22
const path = require('path')
33
const process = require('process')
4-
4+
const os = require('os')
55
const cpy = require('cpy')
66
const { dir: getTmpDir } = require('tmp-promise')
77

@@ -42,9 +42,18 @@ const onBuildHasRun = (netlifyConfig) =>
4242

4343
// Move .next from sample project to current directory
4444
const moveNextDist = async function () {
45+
await stubModules(['next', 'sharp'])
4546
await copy(path.join(SAMPLE_PROJECT_DIR, '.next'), path.join(process.cwd(), '.next'))
4647
}
4748

49+
const stubModules = async function (modules) {
50+
for (const mod of modules) {
51+
const dir = path.join(process.cwd(), 'node_modules', mod)
52+
await ensureDir(dir)
53+
await writeJSON(path.join(dir, 'package.json'), { name: mod })
54+
}
55+
}
56+
4857
// Copy fixture files to the current directory
4958
const useFixture = async function (fixtureName) {
5059
const fixtureDir = `${FIXTURES_DIR}/${fixtureName}`
@@ -185,19 +194,19 @@ describe('onBuild()', () => {
185194
'.next/serverless/**',
186195
'.next/*.json',
187196
'.next/BUILD_ID',
188-
'!node_modules/@next/swc-*/**/*',
189-
'!node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*',
190-
'!node_modules/next/dist/pages/**/*',
197+
'!../node_modules/next/dist/compiled/@ampproject/toolbox-optimizer/**/*',
191198
`!node_modules/next/dist/server/lib/squoosh/**/*.wasm`,
192199
`!node_modules/next/dist/next-server/server/lib/squoosh/**/*.wasm`,
193-
'!node_modules/next/dist/compiled/webpack/(bundle4|bundle5).js',
194-
'!node_modules/react/**/*.development.js',
195-
'!node_modules/react-dom/**/*.development.js',
196-
'!node_modules/use-subscription/**/*.development.js',
200+
'!node_modules/next/dist/compiled/webpack/bundle4.js',
201+
'!node_modules/next/dist/compiled/webpack/bundle5.js',
202+
'!node_modules/next/dist/compiled/terser/bundle.min.js',
197203
'!node_modules/sharp/**/*',
198204
]
199-
expect(netlifyConfig.functions[HANDLER_FUNCTION_NAME].included_files).toEqual(includes)
200-
expect(netlifyConfig.functions[ODB_FUNCTION_NAME].included_files).toEqual(includes)
205+
// Relative paths in Windows are different
206+
if (os.platform() !== 'win32') {
207+
expect(netlifyConfig.functions[HANDLER_FUNCTION_NAME].included_files).toEqual(includes)
208+
expect(netlifyConfig.functions[ODB_FUNCTION_NAME].included_files).toEqual(includes)
209+
}
201210
expect(netlifyConfig.functions[HANDLER_FUNCTION_NAME].node_bundler).toEqual('nft')
202211
expect(netlifyConfig.functions[ODB_FUNCTION_NAME].node_bundler).toEqual('nft')
203212
})

0 commit comments

Comments
 (0)