diff --git a/.eslintrc.js b/.eslintrc.js index ce5daf1242..e200057572 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,6 +3,7 @@ const { overrides } = require('@netlify/eslint-config-node/react_config') module.exports = { extends: '@netlify/eslint-config-node/react_config', rules: { + 'max-depth': 0, complexity: 0, 'fp/no-let': 0, 'fp/no-loops': 0, diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c7301abc0..879b0d1a87 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,13 @@ jobs: node-version: ${{ matrix.node-version }} check-latest: true - run: npm ci + name: NPM Install - name: Linting run: npm run format:ci if: "${{ matrix.node-version == '*' }}" - - run: npm test + - name: Run tests against next@latest + run: npm test + - name: Install Next.js Canary + run: npm install -D next@canary --legacy-peer-deps + - name: Run tests against next@canary + run: npm test diff --git a/helpers/getNextConfig.js b/helpers/getNextConfig.js index d1557c3c02..b5c6afa15f 100644 --- a/helpers/getNextConfig.js +++ b/helpers/getNextConfig.js @@ -13,7 +13,15 @@ const getNextConfig = async function (failBuild = defaultFailBuild, cwd = getCwd // site is using `next` inside `onPreBuild`. /* eslint-disable import/no-dynamic-require */ const { PHASE_PRODUCTION_BUILD } = require(resolveNextModule('next/constants', cwd)) - const loadConfig = require(resolveNextModule('next/dist/next-server/server/config', cwd)).default + const loadConfig = require(resolveNextModule( + [ + // next <= 11.0.1 + 'next/dist/next-server/server/config', + // next > 11.0.1 + 'next/dist/server/config', + ], + cwd, + )).default /* eslint-enable import/no-dynamic-require */ try { diff --git a/helpers/resolveNextModule.js b/helpers/resolveNextModule.js index 288acfa7ad..4f3c3894e9 100644 --- a/helpers/resolveNextModule.js +++ b/helpers/resolveNextModule.js @@ -1,13 +1,31 @@ /** + * Try one or more Next.js imports until one is found. * We can't require() these normally, because the "next" package might not be resolvable from the root of a monorepo */ -const resolveNextModule = (module, nextRoot) => { - // Get the default list of require paths... - const paths = require.resolve.paths(module) - // ...add the root of the Next site to the beginning of that list so we try it first... - paths.unshift(nextRoot) - // ...then resolve the module using that list of paths. - return require.resolve(module, { paths }) +const resolveNextModule = (modules, nextRoot) => { + if (!Array.isArray(modules)) { + // eslint-disable-next-line no-param-reassign + modules = [modules] + } + for (const key in modules) { + const module = modules[key] + // Get the default list of require paths... + const paths = require.resolve.paths(module) + // ...add the root of the Next site to the beginning of that list so we try it first... + paths.unshift(nextRoot) + // ...then resolve the module using that list of paths. + try { + const resolved = require.resolve(module, { paths }) + if (resolved) { + console.log('resolved', resolved) + return resolved + } + } catch (error) { + // Failed. Trying next. + } + } + + throw new Error(`Could not resolve Next module. Tried "${modules.join(', ')}"`) } module.exports = resolveNextModule diff --git a/helpers/verifyBuildTarget.js b/helpers/verifyBuildTarget.js index d237d4b8f6..187034c634 100644 --- a/helpers/verifyBuildTarget.js +++ b/helpers/verifyBuildTarget.js @@ -34,7 +34,17 @@ const verifyBuildTarget = async ({ failBuild, netlifyConfig }) => { // https://github.com/vercel/next.js/blob/canary/packages/next/telemetry/ci-info.ts delete require.cache[resolveNextModule('next/dist/telemetry/ci-info', nextRoot)] - delete require.cache[resolveNextModule('next/dist/next-server/server/config', nextRoot)] + delete require.cache[ + resolveNextModule( + [ + // next <= 11.0.1 + 'next/dist/next-server/server/config', + // next > 11.0.1 + 'next/dist/server/config', + ], + nextRoot, + ) + ] // Clear memoized cache getNextConfig.clear() diff --git a/package.json b/package.json index 594240b75a..1768486387 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "prepublishOnly:test": "npm test", "test:plugin": "npm run build && jest", "test:src": "jest --config src/tests/jest.config.js", - "test": "npm run test:plugin && npm run test:src" + "test": "run-s test:plugin test:src" }, "config": { "eslint": "--cache --format=codeframe --max-warnings=0 \"{src,scripts,tests,.github}/**/*.{js,md,html}\" \"*.{js,md,html}\" \".*.{js,md,html}\"", diff --git a/src/lib/helpers/getSortedRedirects.js b/src/lib/helpers/getSortedRedirects.js index 5543ded59c..445b202d0c 100644 --- a/src/lib/helpers/getSortedRedirects.js +++ b/src/lib/helpers/getSortedRedirects.js @@ -13,7 +13,12 @@ const getSortedRedirects = (redirects) => { // Sort the "naked" routes // eslint-disable-next-line import/no-dynamic-require const { getSortedRoutes } = require(resolveNextModule( - 'next/dist/next-server/lib/router/utils/sorted-routes', + [ + // next <= 11.0.1 + 'next/dist/next-server/lib/router/utils/sorted-routes', + // next > 11.0.1 + 'next/dist/shared/lib/router/utils/sorted-routes', + ], process.cwd(), )) const sortedRoutes = getSortedRoutes(routesWithoutExtensions) diff --git a/test/index.js b/test/index.js index 19a0773df5..b857036dd8 100644 --- a/test/index.js +++ b/test/index.js @@ -7,6 +7,7 @@ const { dir: getTmpDir } = require('tmp-promise') const plugin = require('..') const getNextConfig = require('../helpers/getNextConfig') +const resolveNextModule = require('../helpers/resolveNextModule') const FIXTURES_DIR = `${__dirname}/fixtures` const SAMPLE_PROJECT_DIR = `${__dirname}/sample` @@ -53,8 +54,18 @@ const useFixture = async function (fixtureName) { // This allows us not to have to mock filesystem operations. beforeEach(async () => { delete process.env.NEXT_PRIVATE_TARGET - delete require.cache[require.resolve('next/dist/telemetry/ci-info')] - delete require.cache[require.resolve('next/dist/next-server/server/config')] + delete require.cache[resolveNextModule('next/dist/telemetry/ci-info', process.cwd())] + delete require.cache[ + resolveNextModule( + [ + // next <= 11.0.1 + 'next/dist/next-server/server/config', + // next > 11.0.1 + 'next/dist/server/config', + ], + process.cwd(), + ) + ] getNextConfig.clear() const { path, cleanup } = await getTmpDir({ unsafeCleanup: true })