Skip to content

Commit b43b49f

Browse files
authored
Merge pull request #343 from netlify/mk/force-serverless
fix: force serverless target
2 parents c9af868 + 09642bd commit b43b49f

File tree

6 files changed

+64
-91
lines changed

6 files changed

+64
-91
lines changed

helpers/doesNotNeedPlugin.js

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
const findUp = require('find-up')
22

33
// Checks all the cases for which the plugin should do nothing
4-
const isStaticExportProject = require('./isStaticExportProject')
54
const doesSiteUseNextOnNetlify = require('./doesSiteUseNextOnNetlify')
6-
const hasCorrectNextConfig = require('./hasCorrectNextConfig')
5+
const isStaticExportProject = require('./isStaticExportProject')
76

8-
const doesNotNeedPlugin = async ({ netlifyConfig, packageJson, failBuild }) => {
7+
const doesNotNeedPlugin = ({ netlifyConfig, packageJson }) => {
98
const { build } = netlifyConfig
10-
const { name, scripts = {} } = packageJson
11-
const nextConfigPath = await findUp('next.config.js')
9+
const { scripts = {} } = packageJson
1210

13-
return (
14-
isStaticExportProject({ build, scripts }) ||
15-
doesSiteUseNextOnNetlify({ packageJson }) ||
16-
!(await hasCorrectNextConfig({ nextConfigPath, failBuild }))
17-
)
11+
return isStaticExportProject({ build, scripts }) || doesSiteUseNextOnNetlify({ packageJson })
1812
}
1913

2014
module.exports = doesNotNeedPlugin

helpers/getNextConfig.js

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict'
22

33
const { cwd: getCwd } = require('process')
4-
const { resolve } = require('path')
54

65
const moize = require('moize')
76

helpers/hasCorrectNextConfig.js

-23
This file was deleted.

helpers/verifyBuildTarget.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const getNextConfig = require('./getNextConfig')
2+
// Checks if site has the correct next.config.js
3+
const verifyBuildTarget = async ({ failBuild }) => {
4+
const { target } = await getNextConfig(failBuild)
5+
6+
// If the next config exists, log warning if target isnt in acceptableTargets
7+
const acceptableTargets = ['serverless', 'experimental-serverless-trace']
8+
const isValidTarget = acceptableTargets.includes(target)
9+
if (isValidTarget) {
10+
return
11+
}
12+
console.log(
13+
`The "target" config property must be one of "${acceptableTargets.join(
14+
'", "',
15+
)}". Building with "serverless" target.`,
16+
)
17+
18+
/* eslint-disable fp/no-delete, node/no-unpublished-require */
19+
20+
// We emulate Vercel so that we can set target to serverless if needed
21+
process.env.NOW_BUILDER = true
22+
// If no valid target is set, we use an internal Next env var to force it
23+
process.env.NEXT_PRIVATE_TARGET = 'serverless'
24+
25+
// 🐉 We need Next to recalculate "isZeitNow" var so we can set the target, but it's
26+
// set as an import side effect so we need to clear the require cache first. 🐲
27+
// https://github.com/vercel/next.js/blob/canary/packages/next/telemetry/ci-info.ts
28+
29+
delete require.cache[require.resolve('next/dist/telemetry/ci-info')]
30+
delete require.cache[require.resolve('next/dist/next-server/server/config')]
31+
32+
// Clear memoized cache
33+
getNextConfig.clear()
34+
35+
/* eslint-enable fp/no-delete, node/no-unpublished-require */
36+
}
37+
38+
module.exports = verifyBuildTarget

index.js

+8-23
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
const fs = require('fs')
2-
const path = require('path')
3-
const util = require('util')
4-
5-
const findUp = require('find-up')
61
const makeDir = require('make-dir')
72

83
const { restoreCache, saveCache } = require('./helpers/cacheBuild')
94
const copyUnstableIncludedDirs = require('./helpers/copyUnstableIncludedDirs')
105
const doesNotNeedPlugin = require('./helpers/doesNotNeedPlugin')
116
const getNextConfig = require('./helpers/getNextConfig')
127
const validateNextUsage = require('./helpers/validateNextUsage')
8+
const verifyBuildTarget = require('./helpers/verifyBuildTarget')
139
const nextOnNetlify = require('./src/index.js')
1410

15-
const pWriteFile = util.promisify(fs.writeFile)
16-
1711
// * Helpful Plugin Context *
1812
// - Between the prebuild and build steps, the project's build command is run
1913
// - Between the build and postbuild steps, any functions are bundled
@@ -29,22 +23,13 @@ module.exports = {
2923
return failBuild('Could not find a package.json for this project')
3024
}
3125

32-
const pluginNotNeeded = await doesNotNeedPlugin({ netlifyConfig, packageJson, failBuild })
33-
34-
if (!pluginNotNeeded) {
35-
const nextConfigPath = await findUp('next.config.js')
36-
if (nextConfigPath === undefined) {
37-
// Create the next config file with target set to serverless by default
38-
const nextConfig = `
39-
module.exports = {
40-
target: 'serverless'
41-
}
42-
`
43-
await pWriteFile('next.config.js', nextConfig)
44-
}
26+
if (doesNotNeedPlugin({ netlifyConfig, packageJson, failBuild })) {
27+
return
4528
}
4629

47-
// Because we memoize nextConfig, we need to do this after the write file
30+
// Populates the correct config if needed
31+
await verifyBuildTarget({ netlifyConfig, packageJson, failBuild })
32+
4833
const nextConfig = await getNextConfig(utils.failBuild)
4934

5035
if (nextConfig.images.domains.length !== 0 && !process.env.NEXT_IMAGE_ALLOWED_DOMAINS) {
@@ -64,7 +49,7 @@ module.exports = {
6449
}) {
6550
const { failBuild } = utils.build
6651

67-
if (await doesNotNeedPlugin({ netlifyConfig, packageJson, failBuild })) {
52+
if (doesNotNeedPlugin({ netlifyConfig, packageJson, failBuild })) {
6853
return
6954
}
7055

@@ -76,7 +61,7 @@ module.exports = {
7661
},
7762

7863
async onPostBuild({ netlifyConfig, packageJson, constants: { FUNCTIONS_DIST }, utils }) {
79-
if (await doesNotNeedPlugin({ netlifyConfig, packageJson, utils })) {
64+
if (doesNotNeedPlugin({ netlifyConfig, packageJson, utils })) {
8065
return
8166
}
8267

test/index.js

+14-34
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
const path = require('path')
22
const process = require('process')
3+
4+
const cpy = require('cpy')
35
const pathExists = require('path-exists')
46
const { dir: getTmpDir } = require('tmp-promise')
5-
const cpy = require('cpy')
67

78
const plugin = require('..')
9+
const getNextConfig = require('../helpers/getNextConfig')
810

911
const FIXTURES_DIR = `${__dirname}/fixtures`
1012
const SAMPLE_PROJECT_DIR = `${__dirname}/sample`
@@ -47,6 +49,12 @@ const useFixture = async function (fixtureName) {
4749
// In each test, we change cwd to a temporary directory.
4850
// This allows us not to have to mock filesystem operations.
4951
beforeEach(async () => {
52+
// This is so we can test the target setting code
53+
delete process.env.NEXT_PRIVATE_TARGET
54+
delete require.cache[require.resolve('next/dist/telemetry/ci-info')]
55+
delete require.cache[require.resolve('next/dist/next-server/server/config')]
56+
57+
getNextConfig.clear()
5058
const { path, cleanup } = await getTmpDir({ unsafeCleanup: true })
5159
const restoreCwd = changeCwd(path)
5260
Object.assign(this, { cleanup, restoreCwd })
@@ -66,17 +74,6 @@ const DUMMY_PACKAGE_JSON = { name: 'dummy', version: '1.0.0' }
6674
const netlifyConfig = { build: {} }
6775

6876
describe('preBuild()', () => {
69-
test('create next.config.js with correct target if file does not exist', async () => {
70-
await plugin.onPreBuild({
71-
netlifyConfig,
72-
packageJson: DUMMY_PACKAGE_JSON,
73-
utils,
74-
constants: { FUNCTIONS_SRC: 'out_functions' },
75-
})
76-
77-
expect(await pathExists('next.config.js')).toBeTruthy()
78-
})
79-
8077
test('do nothing if the app has static html export in npm script', async () => {
8178
await plugin.onPreBuild({
8279
netlifyConfig: { build: { command: 'npm run build' } },
@@ -95,8 +92,7 @@ describe('preBuild()', () => {
9592
utils,
9693
constants: {},
9794
})
98-
99-
expect(await pathExists('next.config.js')).toBeTruthy()
95+
expect(process.env.NEXT_PRIVATE_TARGET).toBe('serverless')
10096
})
10197

10298
test('do nothing if app has static html export in toml/ntl config', async () => {
@@ -107,7 +103,7 @@ describe('preBuild()', () => {
107103
constants: { FUNCTIONS_SRC: 'out_functions' },
108104
})
109105

110-
expect(await pathExists('next.config.js')).toBeFalsy()
106+
expect(process.env.NEXT_PRIVATE_TARGET).toBeUndefined()
111107
})
112108

113109
test('do nothing if app has next-on-netlify installed', async () => {
@@ -120,7 +116,7 @@ describe('preBuild()', () => {
120116
utils,
121117
})
122118

123-
expect(await pathExists('next.config.js')).toBeFalsy()
119+
expect(process.env.NEXT_PRIVATE_TARGET).toBeUndefined()
124120
})
125121

126122
test('do nothing if app has next-on-netlify postbuild script', async () => {
@@ -133,7 +129,7 @@ describe('preBuild()', () => {
133129
utils,
134130
})
135131

136-
expect(await pathExists('next.config.js')).toBeFalsy()
132+
expect(process.env.NEXT_PRIVATE_TARGET).toBeUndefined()
137133
})
138134

139135
test('fail build if the app has no package.json', async () => {
@@ -185,6 +181,7 @@ describe('preBuild()', () => {
185181
})
186182

187183
describe('onBuild()', () => {
184+
// eslint-disable-next-line max-lines
188185
test('does not run onBuild if using next-on-netlify', async () => {
189186
const packageJson = {
190187
scripts: { postbuild: 'next-on-netlify' },
@@ -202,23 +199,6 @@ describe('onBuild()', () => {
202199
expect(await pathExists(`${PUBLISH_DIR}/index.html`)).toBeFalsy()
203200
})
204201

205-
test.each(['invalid_next_config', 'deep_invalid_next_config'])(
206-
`do nothing if the app's next config has an invalid target`,
207-
async (fixtureName) => {
208-
await useFixture(fixtureName)
209-
const PUBLISH_DIR = 'publish'
210-
await plugin.onBuild({
211-
netlifyConfig,
212-
packageJson: DUMMY_PACKAGE_JSON,
213-
utils,
214-
constants: { FUNCTIONS_SRC: 'out_functions' },
215-
utils,
216-
})
217-
218-
expect(await pathExists(`${PUBLISH_DIR}/index.html`)).toBeFalsy()
219-
},
220-
)
221-
222202
test('copy files to the publish directory', async () => {
223203
await useFixture('publish_copy_files')
224204
await moveNextDist()

0 commit comments

Comments
 (0)