Skip to content

Commit a678571

Browse files
committed
Fix require('next') in production
1 parent 3d60e58 commit a678571

File tree

4 files changed

+30
-8
lines changed

4 files changed

+30
-8
lines changed

helpers/requirePeerDependency.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// In production, Build plugins cannot currently require peer dependencies
2+
// without this hack.
3+
// See https://github.com/netlify/netlify-plugin-nextjs/issues/55
4+
// TODO: remove once https://github.com/netlify/pod-the-builder/issues/102 is solved
5+
const requirePeerDependency = function (IS_LOCAL, modulePath) {
6+
if (!IS_LOCAL) {
7+
return require(require.resolve(modulePath, { paths: ['.'] }))
8+
}
9+
10+
return require(modulePath)
11+
}
12+
13+
module.exports = requirePeerDependency

helpers/validateNextUsage.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
const { lt: ltVersion, gte: gteVersion } = require('semver')
22
const { yellowBright } = require('chalk')
33

4+
const requirePeerDependency = require('./requirePeerDependency')
5+
46
// Ensure Next.js is available.
57
// We use `peerDependencies` instead of `dependencies` so that users can choose
68
// the Next.js version. However, this requires them to install "next" in their
79
// site.
8-
const validateNextUsage = function (failBuild) {
10+
const validateNextUsage = function (failBuild, IS_LOCAL) {
911
if (!hasPackage('next')) {
1012
return failBuild(
1113
'This site does not seem to be using Next.js. Please run "npm install next" or "yarn next" in the repository.',
1214
)
1315
}
1416

1517
// Old Next.js versions are not supported
16-
const { version } = require('next/package.json')
18+
const { version } = requirePeerDependency(IS_LOCAL, 'next/package.json')
1719
if (ltVersion(version, MIN_VERSION)) {
1820
return failBuild(`Please upgrade to Next.js ${MIN_VERSION} or later`)
1921
}

index.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const makeDir = require('make-dir')
77

88
const isStaticExportProject = require('./helpers/isStaticExportProject')
99
const validateNextUsage = require('./helpers/validateNextUsage')
10+
const requirePeerDependency = require('./helpers/requirePeerDependency')
1011

1112
const pWriteFile = util.promisify(fs.writeFile)
1213

@@ -15,10 +16,10 @@ const pWriteFile = util.promisify(fs.writeFile)
1516
// - Between the build and postbuild steps, any functions are bundled
1617

1718
module.exports = {
18-
async onPreBuild({ netlifyConfig, packageJson, utils }) {
19+
async onPreBuild({ netlifyConfig, packageJson, utils, constants: { IS_LOCAL } }) {
1920
const { failBuild } = utils.build
2021

21-
validateNextUsage(failBuild)
22+
validateNextUsage(failBuild, IS_LOCAL)
2223

2324
if (Object.keys(packageJson).length === 0) {
2425
return failBuild(`Could not find a package.json for this project`)
@@ -45,8 +46,8 @@ module.exports = {
4546
if (nextConfigPath !== undefined) {
4647
// We cannot load `next` at the top-level because we validate whether the
4748
// site is using `next` inside `onPreBuild`.
48-
const { PHASE_PRODUCTION_BUILD } = require('next/constants')
49-
const { default: loadConfig } = require('next/dist/next-server/server/config')
49+
const { PHASE_PRODUCTION_BUILD } = requirePeerDependency(IS_LOCAL, 'next/constants')
50+
const { default: loadConfig } = requirePeerDependency(IS_LOCAL, 'next/dist/next-server/server/config')
5051

5152
// If the next config exists, fail build if target isnt in acceptableTargets
5253
const acceptableTargets = ['serverless', 'experimental-serverless-trace']
@@ -66,7 +67,7 @@ module.exports = {
6667
console.log(`** Adding next.config.js with target set to 'serverless' **`)
6768
}
6869
},
69-
async onBuild({ constants: { PUBLISH_DIR, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC } }) {
70+
async onBuild({ constants: { PUBLISH_DIR, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC, IS_LOCAL } }) {
7071
console.log(`** Running Next on Netlify package **`)
7172

7273
await makeDir(PUBLISH_DIR)
@@ -75,7 +76,11 @@ module.exports = {
7576
// top-level because we validate whether the site is using `next`
7677
// inside `onPreBuild`.
7778
const nextOnNetlify = require('next-on-netlify')
78-
nextOnNetlify({ functionsDir: FUNCTIONS_SRC, publishDir: PUBLISH_DIR })
79+
nextOnNetlify({
80+
functionsDir: FUNCTIONS_SRC,
81+
publishDir: PUBLISH_DIR,
82+
requirePeerDependency: requirePeerDependency.bind(undefined, IS_LOCAL),
83+
})
7984
},
8085
}
8186

test/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ describe('preBuild()', () => {
9292
netlifyConfig: {},
9393
packageJson,
9494
utils,
95+
constants: {},
9596
}),
9697
).rejects.toThrow(
9798
`This plugin does not support sites that manually use next-on-netlify. Uninstall next-on-netlify as a dependency to resolve.`,
@@ -107,6 +108,7 @@ describe('preBuild()', () => {
107108
netlifyConfig: {},
108109
packageJson,
109110
utils,
111+
constants: {},
110112
}),
111113
).rejects.toThrow(
112114
`This plugin does not support sites that manually use next-on-netlify. Uninstall next-on-netlify as a dependency to resolve.`,

0 commit comments

Comments
 (0)