diff --git a/helpers/doesNotNeedPlugin.js b/helpers/doesNotNeedPlugin.js index fd5889c9c8..dfb911467e 100644 --- a/helpers/doesNotNeedPlugin.js +++ b/helpers/doesNotNeedPlugin.js @@ -13,7 +13,7 @@ const doesNotNeedPlugin = async ({ netlifyConfig, packageJson, utils }) => { return ( isStaticExportProject({ build, scripts }) || doesSiteUseNextOnNetlify({ packageJson }) || - !hasCorrectNextConfig({ nextConfigPath, failBuild: utils.build.failBuild }) + !(await hasCorrectNextConfig({ nextConfigPath, failBuild: utils.build.failBuild })) ) } diff --git a/helpers/hasCorrectNextConfig.js b/helpers/hasCorrectNextConfig.js index 64de96fd75..14fb04f1a0 100644 --- a/helpers/hasCorrectNextConfig.js +++ b/helpers/hasCorrectNextConfig.js @@ -1,7 +1,7 @@ const path = require('path') // Checks if site has the correct next.cofig.js -const hasCorrectNextConfig = ({ nextConfigPath, failBuild }) => { +const hasCorrectNextConfig = async ({ nextConfigPath, failBuild }) => { // In the plugin's case, no config is valid because we'll make it ourselves if (nextConfigPath === undefined) return true @@ -14,7 +14,7 @@ const hasCorrectNextConfig = ({ nextConfigPath, failBuild }) => { const acceptableTargets = ['serverless', 'experimental-serverless-trace'] let nextConfig try { - nextConfig = loadConfig(PHASE_PRODUCTION_BUILD, path.resolve('.')) + nextConfig = await loadConfig(PHASE_PRODUCTION_BUILD, path.resolve('.')) } catch (error) { return failBuild('Error loading your next.config.js.', { error }) } diff --git a/index.js b/index.js index 218d0c07e5..36f13074b9 100644 --- a/index.js +++ b/index.js @@ -54,7 +54,7 @@ module.exports = { await makeDir(PUBLISH_DIR) - nextOnNetlify({ functionsDir: FUNCTIONS_SRC, publishDir: PUBLISH_DIR }) + await nextOnNetlify({ functionsDir: FUNCTIONS_SRC, publishDir: PUBLISH_DIR }) }, } diff --git a/package-lock.json b/package-lock.json index 38d15fbe23..b92642e5ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3657,21 +3657,21 @@ } }, "@next/env": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@next/env/-/env-10.0.7.tgz", - "integrity": "sha512-/vnz2SL/mk3Tei58WfRtVnvz5xHmAqcBmZL5sTBEy1CZG6OtZGNx0qAFCjtVkeJ5m1Bh4Ut+WFh/RF333wx8Sg==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@next/env/-/env-10.0.8.tgz", + "integrity": "sha512-vWdxAHD6gJn52tN5bxj1VoRgu5lNtRPc/HyYf7V014k2GZ9eKhqoFQGSSMNGHB7WgdUxLVw75+o9Ek9ClOOAjw==", "dev": true }, "@next/polyfill-module": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-10.0.7.tgz", - "integrity": "sha512-HxqzRpoSgmZP0kRIWwH+e0SgtAXqJ0VkYtwWcsQFED8+xF4Eqn+7Twyp4uE6hutC8gr8IFSFqH+DEYhRtg1ltQ==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-10.0.8.tgz", + "integrity": "sha512-JCUGB4/SKQ4LXniv7LKGrpW+W2DGH/CLkrgXgSo/Ze+EJdMDLxC/VFhiuW+TgAaAWLE4gryoswlZBNyHtkPGQA==", "dev": true }, "@next/react-dev-overlay": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-10.0.7.tgz", - "integrity": "sha512-yq71MDHVqN2N+IqOvZDiFsMpQrBcymrdpTx1ShhAADX7cWQvW4dhcIir4BbfrS10vS1LLz/3a8uKZkGdNoJj3w==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-10.0.8.tgz", + "integrity": "sha512-ygVsvkzYTYIuME+dUUSjCxbNjrJ+Up9Y+CrWEmSSk6HuxajUvrB9vN6RT+PeAzEOQ5er1sWxmVHVdPknQPVWyQ==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", @@ -3765,9 +3765,9 @@ } }, "@next/react-refresh-utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.0.7.tgz", - "integrity": "sha512-d/71vtQglv6m7sh4W1O9drc2hYti7UnAdEXfBLZAS354g2S80lvCRGIhbDrMx4w0rpShoxBIZboE2++LihAESg==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.0.8.tgz", + "integrity": "sha512-ZMO77Xs2ioGV/nZB4GRDHgsNT2jhOp+cZIh6c7wf0xw9o/1KoTWN8nxWzwU/laAtkoSS+E6YdhuR4Mw3Ar3CSg==", "dev": true }, "@nodelib/fs.scandir": { @@ -9971,13 +9971,6 @@ } } }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "optional": true - }, "expect": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", @@ -10844,6 +10837,15 @@ "has-symbols": "^1.0.1" } }, + "get-orientation": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-orientation/-/get-orientation-1.1.2.tgz", + "integrity": "sha512-/pViTfifW+gBbh/RnlFYHINvELT9Znt+SYyDKAUL6uV6By019AK/s+i9XP4jSwq7lwP38Fd8HVeTxym3+hkwmQ==", + "dev": true, + "requires": { + "stream-parser": "^0.3.1" + } + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -10952,13 +10954,6 @@ "ini": "^1.3.2" } }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true, - "optional": true - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -14521,13 +14516,6 @@ "minimist": "^1.2.5" } }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "optional": true - }, "module-definition": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-3.3.1.tgz", @@ -14690,13 +14678,6 @@ "to-regex": "^3.0.1" } }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true, - "optional": true - }, "native-url": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/native-url/-/native-url-0.3.4.tgz", @@ -15192,17 +15173,17 @@ "dev": true }, "next": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/next/-/next-10.0.7.tgz", - "integrity": "sha512-We0utmwwfkvO12eLyUZd3tX9VLDE3FPpOaHpH3kqKdUTxJzUKt8FLBXCTm0mwsTKW5XColWG8mJvz2OLu3+3QA==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/next/-/next-10.0.8.tgz", + "integrity": "sha512-iDY65ce4Prn/9EnQpJGFMb5QJvtGWzZPk6KQqT7vDNu4D+jkivkk9NaAs/k1hR73pXdJHmhHer1s0YxLSghAKQ==", "dev": true, "requires": { "@babel/runtime": "7.12.5", "@hapi/accept": "5.0.1", - "@next/env": "10.0.7", - "@next/polyfill-module": "10.0.7", - "@next/react-dev-overlay": "10.0.7", - "@next/react-refresh-utils": "10.0.7", + "@next/env": "10.0.8", + "@next/polyfill-module": "10.0.8", + "@next/react-dev-overlay": "10.0.8", + "@next/react-refresh-utils": "10.0.8", "@opentelemetry/api": "0.14.0", "ast-types": "0.13.2", "browserslist": "4.16.1", @@ -15214,6 +15195,7 @@ "cssnano-simple": "1.2.2", "etag": "1.8.1", "find-cache-dir": "3.3.1", + "get-orientation": "1.1.2", "jest-worker": "24.9.0", "native-url": "0.3.4", "node-fetch": "2.6.1", @@ -15228,12 +15210,11 @@ "raw-body": "2.4.1", "react-is": "16.13.1", "react-refresh": "0.8.3", - "sharp": "0.26.3", "stream-browserify": "3.0.0", "styled-jsx": "3.3.2", "use-subscription": "1.5.1", "vm-browserify": "1.1.2", - "watchpack": "2.0.0-beta.13" + "watchpack": "2.1.1" }, "dependencies": { "@babel/runtime": { @@ -15380,32 +15361,6 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-abi": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.20.0.tgz", - "integrity": "sha512-6ldtfVR5l3RS8D0aT+lj/uM2Vv/PGEkeWzt2tl8DFBsGY/IuVnAIHl+dG6C14NlWClVv7Rn2+ZDvox+35Hx2Kg==", - "dev": true, - "optional": true, - "requires": { - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "optional": true - } - } - }, - "node-addon-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", - "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==", - "dev": true, - "optional": true - }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -15561,13 +15516,6 @@ "@babel/parser": "^7.0.0" } }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "dev": true, - "optional": true - }, "noop2": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/noop2/-/noop2-2.0.0.tgz", @@ -16689,61 +16637,6 @@ "uniq": "^1.0.1" } }, - "prebuild-install": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.1.tgz", - "integrity": "sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.7.0", - "noop-logger": "^0.1.1", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0", - "which-pm-runs": "^1.0.0" - }, - "dependencies": { - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "optional": true, - "requires": { - "mimic-response": "^2.0.0" - } - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true, - "optional": true - }, - "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, - "optional": true, - "requires": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - } - } - }, "precinct": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/precinct/-/precinct-6.3.1.tgz", @@ -18332,62 +18225,6 @@ "safe-buffer": "^5.0.1" } }, - "sharp": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.3.tgz", - "integrity": "sha512-NdEJ9S6AMr8Px0zgtFo1TJjMK/ROMU92MkDtYn2BBrDjIx3YfH9TUyGdzPC+I/L619GeYQc690Vbaxc5FPCCWg==", - "dev": true, - "optional": true, - "requires": { - "array-flatten": "^3.0.0", - "color": "^3.1.3", - "detect-libc": "^1.0.3", - "node-addon-api": "^3.0.2", - "npmlog": "^4.1.2", - "prebuild-install": "^6.0.0", - "semver": "^7.3.2", - "simple-get": "^4.0.0", - "tar-fs": "^2.1.1", - "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "array-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", - "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", - "dev": true, - "optional": true - }, - "color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", - "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.4" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "optional": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true, - "optional": true - } - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -18430,44 +18267,6 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "optional": true - }, - "simple-get": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz", - "integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==", - "dev": true, - "optional": true, - "requires": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - }, - "dependencies": { - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "optional": true, - "requires": { - "mimic-response": "^3.1.0" - } - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "optional": true - } - } - }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -18990,6 +18789,32 @@ "xtend": "^4.0.0" } }, + "stream-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", + "integrity": "sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=", + "dev": true, + "requires": { + "debug": "2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -19320,19 +19145,6 @@ "yallist": "^3.0.3" } }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, "tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -20373,9 +20185,9 @@ } }, "watchpack": { - "version": "2.0.0-beta.13", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.0.0-beta.13.tgz", - "integrity": "sha512-ZEFq2mx/k5qgQwgi6NOm+2ImICb8ngAkA/rZ6oyXZ7SgPn3pncf+nfhYTCrs3lmHwOxnPtGLTOuFLfpSMh1VMA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", + "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", diff --git a/package.json b/package.json index 9612cf43f5..1cead53b5d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "scripts": { "format": "prettier --write .", "build": "next build test/sample", - "test": "npm run build && jest && jest --config src/tests/jest.config.js", + "test:plugin": "npm run build && jest", + "test:src": "jest --config src/tests/jest.config.js", + "test": "npm run test:plugin && npm run test:src", "cypress:local": "env CYPRESS_DEPLOY=local cypress run --project ./src --config-file false --config video=false", "cypress:netlify": "env CYPRESS_DEPLOY=netlify cypress run --project ./src --config-file false --config video=false", "cypress:local:testonly": "env CYPRESS_SKIP_DEPLOY=true npm run cypress:local", @@ -54,7 +56,7 @@ "husky": "^4.3.0", "jest": "^26.6.1", "netlify-cli": "^3.10.2", - "next": "^10.0.6", + "next": "^10.0.8", "path-exists": "^4.0.0", "prettier": "^2.1.2", "react": "^17.0.1", diff --git a/src/index.js b/src/index.js index 2abdbf5516..7a06d9373d 100644 --- a/src/index.js +++ b/src/index.js @@ -14,7 +14,7 @@ const setupRedirects = require('./lib/steps/setupRedirects') const setupHeaders = require('./lib/steps/setupHeaders') const { NETLIFY_PUBLISH_PATH, NETLIFY_FUNCTIONS_PATH, SRC_FILES } = require('./lib/config') -const build = (functionsPath, publishPath) => { +const build = async (functionsPath, publishPath) => { const trackNextOnNetlifyFiles = prepareFolders({ functionsPath, publishPath, @@ -22,13 +22,13 @@ const build = (functionsPath, publishPath) => { copyPublicFiles(publishPath) - copyNextAssets(publishPath) + await copyNextAssets(publishPath) - setupPages({ functionsPath, publishPath }) + await setupPages({ functionsPath, publishPath }) setupImageFunction(functionsPath) - setupRedirects(publishPath) + await setupRedirects(publishPath) setupHeaders(publishPath) @@ -41,10 +41,10 @@ const watch = (functionsPath, publishPath) => { logTitle(`👀 Watching source code for changes`) const runBuild = debounceFn( - () => { + async () => { try { execa.sync('next', ['build'], { stdio: 'inherit' }) - build(functionsPath, publishPath) + await build(functionsPath, publishPath) } catch (e) { console.log(e) } @@ -65,11 +65,15 @@ const watch = (functionsPath, publishPath) => { * } */ -const nextOnNetlify = (options = {}) => { +const nextOnNetlify = async (options = {}) => { const functionsPath = normalize(options.functionsDir || NETLIFY_FUNCTIONS_PATH) const publishPath = normalize(options.publishDir || NETLIFY_PUBLISH_PATH) - options.watch ? watch(functionsPath, publishPath) : build(functionsPath, publishPath) + if (options.watch) { + watch(functionsPath, publishPath) + } else { + await build(functionsPath, publishPath) + } } module.exports = nextOnNetlify diff --git a/src/lib/config.js b/src/lib/config.js index d4bbe4a010..24a2e59cce 100644 --- a/src/lib/config.js +++ b/src/lib/config.js @@ -17,9 +17,6 @@ const PUBLIC_PATH = join('.', 'public/') // This is the file where NextJS can be configured const NEXT_CONFIG_PATH = join('.', 'next.config.js') -// This is the folder that NextJS builds to; default is .next -const NEXT_DIST_DIR = getNextDistDir() - const NEXT_SRC_DIRS = getNextSrcDirs() // This is the folder with templates for Netlify Functions @@ -45,7 +42,6 @@ module.exports = { NETLIFY_FUNCTIONS_PATH, PUBLIC_PATH, NEXT_CONFIG_PATH, - NEXT_DIST_DIR, TEMPLATES_DIR, FUNCTION_TEMPLATE_PATH, CUSTOM_REDIRECTS_PATH, diff --git a/src/lib/helpers/addDefaultLocaleRedirect.js b/src/lib/helpers/addDefaultLocaleRedirect.js index 543bcd4532..f643937456 100644 --- a/src/lib/helpers/addDefaultLocaleRedirect.js +++ b/src/lib/helpers/addDefaultLocaleRedirect.js @@ -1,11 +1,12 @@ -const i18n = require('./getI18n')() -const { defaultLocale } = i18n - +const getI18n = require('./getI18n') // In i18n projects, we need to create redirects from the "naked" route // to the defaultLocale-prepended route i.e. /static -> /en/static // Note: there can only one defaultLocale, but we put it in an array to simplify // logic in redirects.js files via concatenation -const addDefaultLocaleRedirect = (redirects) => (route, target, additionalParams) => { +const addDefaultLocaleRedirect = async (redirects, route, target, additionalParams) => { + const i18n = await getI18n() + const { defaultLocale } = i18n + // If no i18n, skip if (!defaultLocale) return diff --git a/src/lib/helpers/addLocaleRedirects.js b/src/lib/helpers/addLocaleRedirects.js index 05b4dedc9e..e9d4b2d562 100644 --- a/src/lib/helpers/addLocaleRedirects.js +++ b/src/lib/helpers/addLocaleRedirects.js @@ -1,14 +1,16 @@ -const i18n = require('./getI18n')() +const getI18n = require('./getI18n') const getDataRouteForRoute = require('./getDataRouteForRoute') +const asyncForEach = require('./asyncForEach') -const addLocaleRedirects = (redirects) => (route, target) => { - i18n.locales.forEach((locale) => { +const addLocaleRedirects = async (redirects, route, target) => { + const i18n = await getI18n() + await asyncForEach(i18n.locales, async (locale) => { redirects.push({ route: `/${locale}${route === '/' ? '' : route}`, target, }) redirects.push({ - route: getDataRouteForRoute(route, locale), + route: await getDataRouteForRoute(route, locale), target, }) }) diff --git a/src/lib/helpers/asyncForEach.js b/src/lib/helpers/asyncForEach.js new file mode 100644 index 0000000000..d1903d10d2 --- /dev/null +++ b/src/lib/helpers/asyncForEach.js @@ -0,0 +1,7 @@ +const asyncForEach = async (arr, callback) => { + for (let i = 0; i < arr.length; i++) { + await callback(arr[i], i, arr) + } +} + +module.exports = asyncForEach diff --git a/src/lib/helpers/copyDynamicImportChunks.js b/src/lib/helpers/copyDynamicImportChunks.js index fb7b827276..42fae0cc46 100644 --- a/src/lib/helpers/copyDynamicImportChunks.js +++ b/src/lib/helpers/copyDynamicImportChunks.js @@ -1,11 +1,12 @@ const { join } = require('path') const { copySync, readdirSync } = require('fs-extra') const { logTitle } = require('../helpers/logger') -const { NEXT_DIST_DIR } = require('../config') +const getNextDistDir = require('./getNextDistDir') // Check if there are dynamic import chunks and copy to the necessary function dir -const copyDynamicImportChunks = (functionPath) => { - const chunksPath = join(NEXT_DIST_DIR, 'serverless') +const copyDynamicImportChunks = async (functionPath) => { + const nextDistDir = await getNextDistDir() + const chunksPath = join(nextDistDir, 'serverless') const files = readdirSync(chunksPath) const chunkRegex = new RegExp(/^(\.?[-_$~A-Z0-9a-z]+){1,}\.js$/g) const excludeFiles = ['init-server.js.js', 'on-error-server.js.js'] diff --git a/src/lib/helpers/getDataRouteForRoute.js b/src/lib/helpers/getDataRouteForRoute.js index 402ae3e3cf..90ffedd30f 100644 --- a/src/lib/helpers/getDataRouteForRoute.js +++ b/src/lib/helpers/getDataRouteForRoute.js @@ -1,26 +1,28 @@ const { join } = require('path') const { readFileSync } = require('fs-extra') -const { NEXT_DIST_DIR } = require('../config') const getFilePathForRoute = require('./getFilePathForRoute') +const getNextDistDir = require('./getNextDistDir') -// Get build ID that is used for data routes, e.g. /_next/data/BUILD_ID/... -const fileContents = readFileSync(join(NEXT_DIST_DIR, 'BUILD_ID')) -const buildId = fileContents.toString() - -const getPlainDataRoute = (route) => { +const getPlainDataRoute = (route, buildId) => { const filePath = getFilePathForRoute(route, 'json') return `/_next/data/${buildId}${filePath}` } -const getI18nDataRoute = (route, locale) => { +const getI18nDataRoute = (route, locale, buildId) => { const filePath = getFilePathForRoute(route, 'json') - return route === '/' ? getPlainDataRoute(`/${locale}`) : `/_next/data/${buildId}/${locale}${filePath}` + return route === '/' ? getPlainDataRoute(`/${locale}`, buildId) : `/_next/data/${buildId}/${locale}${filePath}` } // Return the data route for the given route -const getDataRouteForRoute = (route, locale) => { - if (locale) return getI18nDataRoute(route, locale) - return getPlainDataRoute(route) +const getDataRouteForRoute = async (route, locale) => { + const nextDistDir = await getNextDistDir() + + // Get build ID that is used for data routes, e.g. /_next/data/BUILD_ID/... + const fileContents = readFileSync(join(nextDistDir, 'BUILD_ID')) + const buildId = fileContents.toString() + + if (locale) return getI18nDataRoute(route, locale, buildId) + return getPlainDataRoute(route, buildId) } module.exports = getDataRouteForRoute diff --git a/src/lib/helpers/getI18n.js b/src/lib/helpers/getI18n.js index fd202b7bc9..80878268d4 100644 --- a/src/lib/helpers/getI18n.js +++ b/src/lib/helpers/getI18n.js @@ -1,8 +1,8 @@ // Get the i1i8n details specified in next.config.js, if any const getNextConfig = require('./getNextConfig') -const getI18n = () => { - const nextConfig = getNextConfig() +const getI18n = async () => { + const nextConfig = await getNextConfig() return nextConfig.i18n || { locales: [] } } diff --git a/src/lib/helpers/getNextConfig.js b/src/lib/helpers/getNextConfig.js index a9d7d09214..0a34fffee9 100644 --- a/src/lib/helpers/getNextConfig.js +++ b/src/lib/helpers/getNextConfig.js @@ -3,10 +3,13 @@ const { PHASE_PRODUCTION_BUILD } = require('next/constants') const { default: loadConfig } = require('next/dist/next-server/server/config') const { resolve } = require('path') -const getNextConfig = () => { +let nextConfig + +const getNextConfig = async () => { // Load next.config.js // Use same code as https://github.com/vercel/next.js/blob/25488f4a03db30cade4d086ba49cd9a50a2ac02e/packages/next/build/index.ts#L114 - return loadConfig(PHASE_PRODUCTION_BUILD, resolve('.')) + nextConfig = nextConfig || (await loadConfig(PHASE_PRODUCTION_BUILD, resolve('.'))) + return nextConfig } module.exports = getNextConfig diff --git a/src/lib/helpers/getNextDistDir.js b/src/lib/helpers/getNextDistDir.js index e21ee41e6a..f5b9b5603b 100644 --- a/src/lib/helpers/getNextDistDir.js +++ b/src/lib/helpers/getNextDistDir.js @@ -2,8 +2,8 @@ const { join } = require('path') const getNextConfig = require('./getNextConfig') -const getNextDistDir = () => { - const nextConfig = getNextConfig() +const getNextDistDir = async () => { + const nextConfig = await getNextConfig() return join('.', nextConfig.distDir) } diff --git a/src/lib/helpers/getPagesManifest.js b/src/lib/helpers/getPagesManifest.js index 6b8857d397..3c398ada25 100644 --- a/src/lib/helpers/getPagesManifest.js +++ b/src/lib/helpers/getPagesManifest.js @@ -1,9 +1,10 @@ const { join } = require('path') const { existsSync, readJSONSync } = require('fs-extra') -const { NEXT_DIST_DIR } = require('../config') +const getNextDistDir = require('./getNextDistDir') -const getPagesManifest = () => { - const manifestPath = join(NEXT_DIST_DIR, 'serverless', 'pages-manifest.json') +const getPagesManifest = async () => { + const nextDistDir = await getNextDistDir() + const manifestPath = join(nextDistDir, 'serverless', 'pages-manifest.json') if (!existsSync(manifestPath)) return {} const contents = readJSONSync(manifestPath) // Next.js mistakenly puts backslashes in certain paths on Windows, replace diff --git a/src/lib/helpers/getPrerenderManifest.js b/src/lib/helpers/getPrerenderManifest.js index b82c810aa4..b480d11467 100644 --- a/src/lib/helpers/getPrerenderManifest.js +++ b/src/lib/helpers/getPrerenderManifest.js @@ -1,14 +1,14 @@ const { join } = require('path') const { readJSONSync } = require('fs-extra') -const { NEXT_DIST_DIR } = require('../config') -const nextConfig = require('./getNextConfig')() +const getNextConfig = require('./getNextConfig') +const getNextDistDir = require('./getNextDistDir') const getDataRouteForRoute = require('./getDataRouteForRoute') +const asyncForEach = require('./asyncForEach') -const transformManifestForI18n = (manifest) => { +const transformManifestForI18n = async (manifest) => { const { routes } = manifest - const { defaultLocale, locales } = nextConfig.i18n const newRoutes = {} - Object.entries(routes).forEach(([route, { dataRoute, srcRoute, ...params }]) => { + await asyncForEach(Object.entries(routes), async ([route, { dataRoute, srcRoute, ...params }]) => { const isDynamicRoute = !!srcRoute if (isDynamicRoute) { newRoutes[route] = routes[route] @@ -16,7 +16,7 @@ const transformManifestForI18n = (manifest) => { const locale = route.split('/')[1] const routeWithoutLocale = `/${route.split('/').slice(2, route.split('/').length).join('/')}` newRoutes[route] = { - dataRoute: getDataRouteForRoute(routeWithoutLocale, locale), + dataRoute: await getDataRouteForRoute(routeWithoutLocale, locale), srcRoute: routeWithoutLocale, ...params, } @@ -26,9 +26,11 @@ const transformManifestForI18n = (manifest) => { return { ...manifest, routes: newRoutes } } -const getPrerenderManifest = () => { - const manifest = readJSONSync(join(NEXT_DIST_DIR, 'prerender-manifest.json')) - if (nextConfig.i18n) return transformManifestForI18n(manifest) +const getPrerenderManifest = async () => { + const nextConfig = await getNextConfig() + const nextDistDir = await getNextDistDir() + const manifest = readJSONSync(join(nextDistDir, 'prerender-manifest.json')) + if (nextConfig.i18n) return await transformManifestForI18n(manifest) return manifest } diff --git a/src/lib/helpers/getRoutesManifest.js b/src/lib/helpers/getRoutesManifest.js index 80826f9f97..7bc764d8d2 100644 --- a/src/lib/helpers/getRoutesManifest.js +++ b/src/lib/helpers/getRoutesManifest.js @@ -1,9 +1,10 @@ const { join } = require('path') const { readJSONSync } = require('fs-extra') -const { NEXT_DIST_DIR } = require('../config') +const getNextDistDir = require('./getNextDistDir') -const getRoutesManifest = () => { - return readJSONSync(join(NEXT_DIST_DIR, 'routes-manifest.json')) +const getRoutesManifest = async () => { + const nextDistDir = await getNextDistDir() + return readJSONSync(join(nextDistDir, 'routes-manifest.json')) } module.exports = getRoutesManifest diff --git a/src/lib/helpers/isRouteInPrerenderManifest.js b/src/lib/helpers/isRouteInPrerenderManifest.js index 6cf6694b2b..71a85abcf5 100644 --- a/src/lib/helpers/isRouteInPrerenderManifest.js +++ b/src/lib/helpers/isRouteInPrerenderManifest.js @@ -1,20 +1,21 @@ const getPrerenderManifest = require('./getPrerenderManifest') -const i18n = require('./getI18n')() +const getI18n = require('./getI18n') -const { routes, dynamicRoutes } = getPrerenderManifest() -const { defaultLocale, locales } = i18n +// Return true if the route is defined in the prerender manifest +const isRouteInPrerenderManifest = async (route) => { + const i18n = await getI18n() + const { defaultLocale, locales } = i18n + const { routes, dynamicRoutes } = await getPrerenderManifest() -const isRouteInManifestWithI18n = (route) => { - let isStaticRoute = false - Object.entries(routes).forEach(([staticRoute, { srcRoute }]) => { - // This is because in i18n we set the nakedRoute to be the srcRoute in the manifest - if (route === srcRoute) isStaticRoute = true - }) - return isStaticRoute || route in dynamicRoutes -} + const isRouteInManifestWithI18n = () => { + let isStaticRoute = false + Object.entries(routes).forEach(([staticRoute, { srcRoute }]) => { + // This is because in i18n we set the nakedRoute to be the srcRoute in the manifest + if (route === srcRoute) isStaticRoute = true + }) + return isStaticRoute || route in dynamicRoutes + } -// Return true if the route is defined in the prerender manifest -const isRouteInPrerenderManifest = (route) => { if (i18n.defaultLocale) return isRouteInManifestWithI18n(route) return route in routes || route in dynamicRoutes } diff --git a/src/lib/helpers/isRouteWithDataRoute.js b/src/lib/helpers/isRouteWithDataRoute.js index de87324656..3b99a81577 100644 --- a/src/lib/helpers/isRouteWithDataRoute.js +++ b/src/lib/helpers/isRouteWithDataRoute.js @@ -1,9 +1,9 @@ const getRoutesManifest = require('./getRoutesManifest') -const { dataRoutes } = getRoutesManifest() - // Return true if the route has a data route in the routes manifest -const isRouteWithDataRoute = (route) => { +const isRouteWithDataRoute = async (route) => { + const { dataRoutes } = await getRoutesManifest() + // If no data routes exist, return false if (dataRoutes == null) return false diff --git a/src/lib/helpers/isRouteWithFallback.js b/src/lib/helpers/isRouteWithFallback.js index 0f73a50a40..8f7631d2e1 100644 --- a/src/lib/helpers/isRouteWithFallback.js +++ b/src/lib/helpers/isRouteWithFallback.js @@ -1,8 +1,8 @@ const getPrerenderManifest = require('./getPrerenderManifest') -const { dynamicRoutes } = getPrerenderManifest() +const isRouteWithFallback = async (route) => { + const { dynamicRoutes } = await getPrerenderManifest() -const isRouteWithFallback = (route) => { // Fallback "blocking" routes will have fallback: null in manifest return dynamicRoutes[route] && dynamicRoutes[route].fallback !== false } diff --git a/src/lib/helpers/setupNetlifyFunctionForPage.js b/src/lib/helpers/setupNetlifyFunctionForPage.js index 823718e2b7..d7affc3849 100644 --- a/src/lib/helpers/setupNetlifyFunctionForPage.js +++ b/src/lib/helpers/setupNetlifyFunctionForPage.js @@ -1,12 +1,13 @@ const { copySync } = require('fs-extra') const { join } = require('path') -const { NEXT_DIST_DIR, TEMPLATES_DIR, FUNCTION_TEMPLATE_PATH } = require('../config') +const { TEMPLATES_DIR, FUNCTION_TEMPLATE_PATH } = require('../config') +const getNextDistDir = require('./getNextDistDir') const getNetlifyFunctionName = require('./getNetlifyFunctionName') const copyDynamicImportChunks = require('./copyDynamicImportChunks') const { logItem } = require('./logger') // Create a Netlify Function for the page with the given file path -const setupNetlifyFunctionForPage = ({ filePath, functionsPath, isApiPage }) => { +const setupNetlifyFunctionForPage = async ({ filePath, functionsPath, isApiPage }) => { // Set function name based on file path const functionName = getNetlifyFunctionName(filePath, isApiPage) const functionDirectory = join(functionsPath, functionName) @@ -32,11 +33,12 @@ const setupNetlifyFunctionForPage = ({ filePath, functionsPath, isApiPage }) => }) // Copy any dynamic import chunks - copyDynamicImportChunks(functionDirectory) + await copyDynamicImportChunks(functionDirectory) // Copy page const nextPageCopyPath = join(functionDirectory, 'nextPage', 'index.js') - copySync(join(NEXT_DIST_DIR, 'serverless', filePath), nextPageCopyPath, { + const nextDistDir = await getNextDistDir() + copySync(join(nextDistDir, 'serverless', filePath), nextPageCopyPath, { overwrite: false, errorOnExist: true, }) diff --git a/src/lib/helpers/setupStaticFileForPage.js b/src/lib/helpers/setupStaticFileForPage.js index d48459ae3e..9f4c299621 100644 --- a/src/lib/helpers/setupStaticFileForPage.js +++ b/src/lib/helpers/setupStaticFileForPage.js @@ -1,14 +1,16 @@ const { copySync } = require('fs-extra') const { join } = require('path') -const { NEXT_DIST_DIR } = require('../config') +const getNextDistDir = require('./getNextDistDir') // Copy the static asset from pages/inputPath to out_publish/outputPath -const setupStaticFileForPage = ({ inputPath, outputPath = null, publishPath }) => { +const setupStaticFileForPage = async ({ inputPath, outputPath = null, publishPath }) => { // If no outputPath is set, default to the same as inputPath outputPath = outputPath || inputPath + const nextDistDir = await getNextDistDir() + // Perform copy operation - copySync(join(NEXT_DIST_DIR, 'serverless', 'pages', inputPath), join(publishPath, outputPath), { + copySync(join(nextDistDir, 'serverless', 'pages', inputPath), join(publishPath, outputPath), { overwrite: false, errorOnExist: true, }) diff --git a/src/lib/pages/api/pages.js b/src/lib/pages/api/pages.js index b01f91a6ef..c6101a183e 100644 --- a/src/lib/pages/api/pages.js +++ b/src/lib/pages/api/pages.js @@ -1,19 +1,22 @@ const getPagesManifest = require('../../helpers/getPagesManifest') const isApiRoute = require('../../helpers/isApiRoute') -// Collect pages -const pages = [] +const getPages = async () => { + // Get HTML and SSR pages and API endpoints from the NextJS pages manifest + const pagesManifest = await getPagesManifest() -// Get HTML and SSR pages and API endpoints from the NextJS pages manifest -const pagesManifest = getPagesManifest() + // Collect pages + const pages = [] -// Parse pages -Object.entries(pagesManifest).forEach(([route, filePath]) => { - // Skip non-API endpoints - if (!isApiRoute(route)) return + // Parse pages + Object.entries(pagesManifest).forEach(([route, filePath]) => { + // Skip non-API endpoints + if (!isApiRoute(route)) return - // Add page - pages.push({ route, filePath }) -}) + // Add page + pages.push({ route, filePath }) + }) + return pages +} -module.exports = pages +module.exports = getPages diff --git a/src/lib/pages/api/redirects.js b/src/lib/pages/api/redirects.js index 30753ea56c..3bb5a143fb 100644 --- a/src/lib/pages/api/redirects.js +++ b/src/lib/pages/api/redirects.js @@ -1,9 +1,12 @@ const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName') -const pages = require('./pages') +const getPages = require('./pages') -const redirects = pages.map(({ route, filePath }) => ({ - route, - target: `/.netlify/functions/${getNetlifyFunctionName(filePath, true)}`, -})) +const getRedirects = async () => { + const pages = await getPages() + return pages.map(({ route, filePath }) => ({ + route, + target: `/.netlify/functions/${getNetlifyFunctionName(filePath, true)}`, + })) +} -module.exports = redirects +module.exports = getRedirects diff --git a/src/lib/pages/api/setup.js b/src/lib/pages/api/setup.js index 4cc3d1a338..5620622898 100644 --- a/src/lib/pages/api/setup.js +++ b/src/lib/pages/api/setup.js @@ -1,15 +1,18 @@ const { logTitle, logItem } = require('../../helpers/logger') const setupNetlifyFunctionForPage = require('../../helpers/setupNetlifyFunctionForPage') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') // Create a Netlify Function for every API endpoint -const setup = (functionsPath) => { +const setup = async (functionsPath) => { logTitle('💫 Setting up API endpoints as Netlify Functions in', functionsPath) + const pages = await getPages() + // Create Netlify Function for every page - pages.forEach(({ filePath }) => { + await asyncForEach(pages, async ({ filePath }) => { logItem(filePath) - setupNetlifyFunctionForPage({ filePath, functionsPath, isApiPage: true }) + await setupNetlifyFunctionForPage({ filePath, functionsPath, isApiPage: true }) }) } diff --git a/src/lib/pages/getInitialProps/pages.js b/src/lib/pages/getInitialProps/pages.js index b6b0abb289..af17b345d9 100644 --- a/src/lib/pages/getInitialProps/pages.js +++ b/src/lib/pages/getInitialProps/pages.js @@ -4,33 +4,37 @@ const isFrameworkRoute = require('../../helpers/isFrameworkRoute') const isApiRoute = require('../../helpers/isApiRoute') const isRouteInPrerenderManifest = require('../../helpers/isRouteInPrerenderManifest') const isRouteWithDataRoute = require('../../helpers/isRouteWithDataRoute') +const asyncForEach = require('../../helpers/asyncForEach') -// Collect pages -const pages = [] +const getPages = async () => { + // Get HTML and SSR pages and API endpoints from the NextJS pages manifest + const pagesManifest = await getPagesManifest() -// Get HTML and SSR pages and API endpoints from the NextJS pages manifest -const pagesManifest = getPagesManifest() + // Collect pages + const pages = [] -// Parse pages -Object.entries(pagesManifest).forEach(([route, filePath]) => { - // Ignore HTML files - if (isHtmlFile(filePath)) return + // Parse pages + await asyncForEach(Object.entries(pagesManifest), async ([route, filePath]) => { + // Ignore HTML files + if (isHtmlFile(filePath)) return - // Skip framework pages, such as _app and _error - if (isFrameworkRoute(route)) return + // Skip framework pages, such as _app and _error + if (isFrameworkRoute(route)) return - // Skip API endpoints - if (isApiRoute(route)) return + // Skip API endpoints + if (isApiRoute(route)) return - // Skip page if it is actually used with getStaticProps - if (isRouteInPrerenderManifest(route)) return + // Skip page if it is actually used with getStaticProps + if (await isRouteInPrerenderManifest(route)) return - // Skip page if it has a data route (because then it is a page with - // getServerSideProps) - if (isRouteWithDataRoute(route)) return + // Skip page if it has a data route (because then it is a page with + // getServerSideProps) + if (await isRouteWithDataRoute(route)) return - // Add page - pages.push({ route, filePath }) -}) + // Add page + pages.push({ route, filePath }) + }) + return pages +} -module.exports = pages +module.exports = getPages diff --git a/src/lib/pages/getInitialProps/redirects.js b/src/lib/pages/getInitialProps/redirects.js index ada246d086..a9d6c06a44 100644 --- a/src/lib/pages/getInitialProps/redirects.js +++ b/src/lib/pages/getInitialProps/redirects.js @@ -1,19 +1,25 @@ const addLocaleRedirects = require('../../helpers/addLocaleRedirects') const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') -const redirects = [] +const getRedirects = async () => { + const redirects = [] + const pages = await getPages() -pages.forEach(({ route, filePath }) => { - const functionName = getNetlifyFunctionName(filePath) - const target = `/.netlify/functions/${functionName}` + await asyncForEach(pages, async ({ route, filePath }) => { + const functionName = getNetlifyFunctionName(filePath) + const target = `/.netlify/functions/${functionName}` - addLocaleRedirects(redirects)(route, target) + await addLocaleRedirects(redirects, route, target) - redirects.push({ - route, - target, + redirects.push({ + route, + target, + }) }) -}) -module.exports = redirects + return redirects +} + +module.exports = getRedirects diff --git a/src/lib/pages/getInitialProps/setup.js b/src/lib/pages/getInitialProps/setup.js index 440fd1f1e8..0cb472b8b4 100644 --- a/src/lib/pages/getInitialProps/setup.js +++ b/src/lib/pages/getInitialProps/setup.js @@ -1,15 +1,18 @@ const { logTitle, logItem } = require('../../helpers/logger') const setupNetlifyFunctionForPage = require('../../helpers/setupNetlifyFunctionForPage') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') // Create a Netlify Function for every page with getInitialProps -const setup = (functionsPath) => { +const setup = async (functionsPath) => { logTitle('💫 Setting up pages with getInitialProps as Netlify Functions in', functionsPath) + const pages = await getPages() + // Create Netlify Function for every page - pages.forEach(({ filePath }) => { + await asyncForEach(pages, async ({ filePath }) => { logItem(filePath) - setupNetlifyFunctionForPage({ filePath, functionsPath }) + await setupNetlifyFunctionForPage({ filePath, functionsPath }) }) } diff --git a/src/lib/pages/getServerSideProps/pages.js b/src/lib/pages/getServerSideProps/pages.js index f8b1c44fba..ab296d0242 100644 --- a/src/lib/pages/getServerSideProps/pages.js +++ b/src/lib/pages/getServerSideProps/pages.js @@ -1,36 +1,43 @@ const getPagesManifest = require('../../helpers/getPagesManifest') +const asyncForEach = require('../../helpers/asyncForEach') const isHtmlFile = require('../../helpers/isHtmlFile') const isFrameworkRoute = require('../../helpers/isFrameworkRoute') const isApiRoute = require('../../helpers/isApiRoute') const isRouteInPrerenderManifest = require('../../helpers/isRouteInPrerenderManifest') const isRouteWithDataRoute = require('../../helpers/isRouteWithDataRoute') -// Collect pages -const pages = [] +const getPages = async () => { + // Collect pages + const pages = [] -// Get HTML and SSR pages and API endpoints from the NextJS pages manifest -const pagesManifest = getPagesManifest() + // Get HTML and SSR pages and API endpoints from the NextJS pages manifest + const pagesManifest = await getPagesManifest() -// Parse pages -Object.entries(pagesManifest).forEach(([route, filePath]) => { - // Ignore HTML files - if (isHtmlFile(filePath)) return + // Parse pages + await asyncForEach(Object.entries(pagesManifest), async ([route, filePath]) => { + // Ignore HTML files + if (isHtmlFile(filePath)) return - // Skip framework pages, such as _app and _error - if (isFrameworkRoute(route)) return + // Skip framework pages, such as _app and _error + if (isFrameworkRoute(route)) return - // Skip API endpoints - if (isApiRoute(route)) return + // Skip API endpoints + if (isApiRoute(route)) return - // Skip page if it is actually used with getStaticProps - if (isRouteInPrerenderManifest(route)) return + // Skip page if it is actually used with getStaticProps + const isInPrerenderManifest = await isRouteInPrerenderManifest(route) + if (isInPrerenderManifest) return - // Skip page if it has no data route (because then it is a page with - // getInitialProps) - if (!isRouteWithDataRoute(route)) return + // Skip page if it has no data route (because then it is a page with + // getInitialProps) + const hasDataRoute = await isRouteWithDataRoute(route) + if (!hasDataRoute) return - // Add page - pages.push({ route, filePath }) -}) + // Add page + pages.push({ route, filePath }) + }) -module.exports = pages + return pages +} + +module.exports = getPages diff --git a/src/lib/pages/getServerSideProps/redirects.js b/src/lib/pages/getServerSideProps/redirects.js index d0cc4d35f5..da960e1478 100644 --- a/src/lib/pages/getServerSideProps/redirects.js +++ b/src/lib/pages/getServerSideProps/redirects.js @@ -1,9 +1,8 @@ const addLocaleRedirects = require('../../helpers/addLocaleRedirects') const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName') const getDataRouteForRoute = require('../../helpers/getDataRouteForRoute') -const pages = require('./pages') - -const redirects = [] +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') /** getServerSideProps pages * @@ -13,26 +12,32 @@ const redirects = [] * } **/ -pages.forEach(({ route, filePath }) => { - const functionName = getNetlifyFunctionName(filePath) - const target = `/.netlify/functions/${functionName}` +const getRedirects = async () => { + const redirects = [] + const pages = await getPages() - addLocaleRedirects(redirects)(route, target) + await asyncForEach(pages, async ({ route, filePath }) => { + const functionName = getNetlifyFunctionName(filePath) + const target = `/.netlify/functions/${functionName}` - // Add one redirect for the naked route - // i.e. /ssr - redirects.push({ - route, - target, - }) + await addLocaleRedirects(redirects, route, target) + + // Add one redirect for the naked route + // i.e. /ssr + redirects.push({ + route, + target, + }) - // Add one redirect for the data route; - // pages-manifest doesn't provide the dataRoute for us so we - // construct it ourselves with getDataRouteForRoute - redirects.push({ - route: getDataRouteForRoute(route), - target, + // Add one redirect for the data route; + // pages-manifest doesn't provide the dataRoute for us so we + // construct it ourselves with getDataRouteForRoute + redirects.push({ + route: await getDataRouteForRoute(route), + target, + }) }) -}) + return redirects +} -module.exports = redirects +module.exports = getRedirects diff --git a/src/lib/pages/getServerSideProps/setup.js b/src/lib/pages/getServerSideProps/setup.js index 8e193e856f..8a7827da74 100644 --- a/src/lib/pages/getServerSideProps/setup.js +++ b/src/lib/pages/getServerSideProps/setup.js @@ -1,15 +1,18 @@ const { logTitle, logItem } = require('../../helpers/logger') const setupNetlifyFunctionForPage = require('../../helpers/setupNetlifyFunctionForPage') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') // Create a Netlify Function for every page with getServerSideProps -const setup = (functionsPath) => { +const setup = async (functionsPath) => { logTitle('💫 Setting up pages with getServerSideProps as Netlify Functions in', functionsPath) + const pages = await getPages() + // Create Netlify Function for every page - pages.forEach(({ filePath }) => { + await asyncForEach(pages, async ({ filePath }) => { logItem(filePath) - setupNetlifyFunctionForPage({ filePath, functionsPath }) + await setupNetlifyFunctionForPage({ filePath, functionsPath }) }) } diff --git a/src/lib/pages/getStaticProps/pages.js b/src/lib/pages/getStaticProps/pages.js index 057d399b29..b091c4ed9f 100644 --- a/src/lib/pages/getStaticProps/pages.js +++ b/src/lib/pages/getStaticProps/pages.js @@ -1,21 +1,23 @@ const getPrerenderManifest = require('../../helpers/getPrerenderManifest') -// Collect pages -const pages = [] - // Get pages using getStaticProps -const { routes } = getPrerenderManifest() +const getPages = async () => { + const { routes } = await getPrerenderManifest() + + // Collect pages + const pages = [] -// Parse static pages -Object.entries(routes).forEach(([route, { dataRoute, initialRevalidateSeconds, srcRoute }]) => { - // Ignore pages with revalidate, these will need to be SSRed - if (initialRevalidateSeconds) return + Object.entries(routes).forEach(([route, { dataRoute, initialRevalidateSeconds, srcRoute }]) => { + // Ignore pages with revalidate, these will need to be SSRed + if (initialRevalidateSeconds) return - pages.push({ - route, - dataRoute, - srcRoute, + pages.push({ + route, + dataRoute, + srcRoute, + }) }) -}) + return pages +} -module.exports = pages +module.exports = getPages diff --git a/src/lib/pages/getStaticProps/redirects.js b/src/lib/pages/getStaticProps/redirects.js index 696e8d6443..a22fb5bed7 100644 --- a/src/lib/pages/getStaticProps/redirects.js +++ b/src/lib/pages/getStaticProps/redirects.js @@ -1,13 +1,9 @@ const { join } = require('path') const addDefaultLocaleRedirect = require('../../helpers/addDefaultLocaleRedirect') const getFilePathForRoute = require('../../helpers/getFilePathForRoute') -const getDataRouteForRoute = require('../../helpers/getDataRouteForRoute') const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName') -const pages = require('./pages') - -// Pages with getStaticProps (without fallback or revalidation) only need -// redirects for i18n and handling preview mode -const redirects = [] +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') /** getStaticProps pages * @@ -25,31 +21,40 @@ const redirects = [] * **/ -pages.forEach(({ route, dataRoute, srcRoute }) => { - const relativePath = getFilePathForRoute(srcRoute || route, 'js') - const filePath = join('pages', relativePath) - const functionName = getNetlifyFunctionName(filePath) - - // Preview mode conditions - const conditions = ['Cookie=__prerender_bypass,__next_preview_data'] - const target = `/.netlify/functions/${functionName}` - const previewModeRedirect = { conditions, force: true, target } - - // Add a preview mode redirect for the standard route - redirects.push({ - route, - ...previewModeRedirect, - }) - - // Add a preview mode redirect for the data route, same conditions - redirects.push({ - route: dataRoute, - ...previewModeRedirect, +// Pages with getStaticProps (without fallback or revalidation) only need +// redirects for i18n and handling preview mode +const getRedirects = async () => { + const redirects = [] + const pages = await getPages() + + await asyncForEach(pages, async ({ route, dataRoute, srcRoute }) => { + const relativePath = getFilePathForRoute(srcRoute || route, 'js') + const filePath = join('pages', relativePath) + const functionName = getNetlifyFunctionName(filePath) + + // Preview mode conditions + const conditions = ['Cookie=__prerender_bypass,__next_preview_data'] + const target = `/.netlify/functions/${functionName}` + const previewModeRedirect = { conditions, force: true, target } + + // Add a preview mode redirect for the standard route + redirects.push({ + route, + ...previewModeRedirect, + }) + + // Add a preview mode redirect for the data route, same conditions + redirects.push({ + route: dataRoute, + ...previewModeRedirect, + }) + + // Preview mode default locale redirect must precede normal default locale redirect + await addDefaultLocaleRedirect(redirects, route, target, previewModeRedirect) + await addDefaultLocaleRedirect(redirects, route) }) - // Preview mode default locale redirect must precede normal default locale redirect - addDefaultLocaleRedirect(redirects)(route, target, previewModeRedirect) - addDefaultLocaleRedirect(redirects)(route) -}) + return redirects +} -module.exports = redirects +module.exports = getRedirects diff --git a/src/lib/pages/getStaticProps/setup.js b/src/lib/pages/getStaticProps/setup.js index dac0dc28b8..13f47a6459 100644 --- a/src/lib/pages/getStaticProps/setup.js +++ b/src/lib/pages/getStaticProps/setup.js @@ -1,31 +1,32 @@ const { join } = require('path') const { logTitle, logItem } = require('../../helpers/logger') +const asyncForEach = require('../../helpers/asyncForEach') const getFilePathForRoute = require('../../helpers/getFilePathForRoute') -const getDataRouteForRoute = require('../../helpers/getDataRouteForRoute') -const i18n = require('../../helpers/getI18n')() const isRouteWithFallback = require('../../helpers/isRouteWithFallback') const setupStaticFileForPage = require('../../helpers/setupStaticFileForPage') const setupNetlifyFunctionForPage = require('../../helpers/setupNetlifyFunctionForPage') -const pages = require('./pages') +const getPages = require('./pages') // Copy pre-rendered SSG pages -const setup = ({ functionsPath, publishPath }) => { +const setup = async ({ functionsPath, publishPath }) => { logTitle('🔥 Copying pre-rendered pages with getStaticProps and JSON data to', publishPath) // Keep track of the functions that have been set up, so that we do not set up // a function for the same file path twice const filePathsDone = [] - pages.forEach(({ route, dataRoute, srcRoute }) => { + const pages = await getPages() + + await asyncForEach(pages, async ({ route, dataRoute, srcRoute }) => { logItem(route) // Copy pre-rendered HTML page const htmlPath = getFilePathForRoute(route, 'html') - setupStaticFileForPage({ inputPath: htmlPath, publishPath }) + await setupStaticFileForPage({ inputPath: htmlPath, publishPath }) // Copy page's JSON data const jsonPath = getFilePathForRoute(route, 'json') - setupStaticFileForPage({ + await setupStaticFileForPage({ inputPath: jsonPath, outputPath: dataRoute, publishPath, @@ -40,7 +41,7 @@ const setup = ({ functionsPath, publishPath }) => { if (filePathsDone.includes(filePath) || isRouteWithFallback(srcRoute)) return logItem(filePath) - setupNetlifyFunctionForPage({ filePath, functionsPath }) + await setupNetlifyFunctionForPage({ filePath, functionsPath }) filePathsDone.push(filePath) }) } diff --git a/src/lib/pages/getStaticPropsWithFallback/pages.js b/src/lib/pages/getStaticPropsWithFallback/pages.js index 1fc88241e1..34e223e45b 100644 --- a/src/lib/pages/getStaticPropsWithFallback/pages.js +++ b/src/lib/pages/getStaticPropsWithFallback/pages.js @@ -1,21 +1,24 @@ const getPrerenderManifest = require('../../helpers/getPrerenderManifest') -// Collect pages -const pages = [] - // Get pages using getStaticProps -const { dynamicRoutes } = getPrerenderManifest() +const getPages = async () => { + const { dynamicRoutes } = await getPrerenderManifest() + + // Collect pages + const pages = [] -// Parse pages -Object.entries(dynamicRoutes).forEach(([route, { dataRoute, fallback }]) => { - // Skip pages without fallback - if (fallback === false) return + Object.entries(dynamicRoutes).forEach(([route, { dataRoute, fallback }]) => { + // Skip pages without fallback + if (fallback === false) return - // Add the page - pages.push({ - route, - dataRoute, + // Add the page + pages.push({ + route, + dataRoute, + }) }) -}) -module.exports = pages + return pages +} + +module.exports = getPages diff --git a/src/lib/pages/getStaticPropsWithFallback/redirects.js b/src/lib/pages/getStaticPropsWithFallback/redirects.js index 15d6a67c0d..d1bb375ca0 100644 --- a/src/lib/pages/getStaticPropsWithFallback/redirects.js +++ b/src/lib/pages/getStaticPropsWithFallback/redirects.js @@ -2,29 +2,34 @@ const { join } = require('path') const addLocaleRedirects = require('../../helpers/addLocaleRedirects') const getFilePathForRoute = require('../../helpers/getFilePathForRoute') const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName') -const pages = require('./pages') +const getPages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') -const redirects = [] +const getRedirects = async () => { + const redirects = [] + const pages = await getPages() -pages.forEach(({ route, dataRoute }) => { - const relativePath = getFilePathForRoute(route, 'js') - const filePath = join('pages', relativePath) - const functionName = getNetlifyFunctionName(filePath) - const target = `/.netlify/functions/${functionName}` + await asyncForEach(pages, async ({ route, dataRoute }) => { + const relativePath = getFilePathForRoute(route, 'js') + const filePath = join('pages', relativePath) + const functionName = getNetlifyFunctionName(filePath) + const target = `/.netlify/functions/${functionName}` - addLocaleRedirects(redirects)(route, target) + await addLocaleRedirects(redirects, route, target) - // Add one redirect for the page - redirects.push({ - route, - target, - }) + // Add one redirect for the page + redirects.push({ + route, + target, + }) - // Add one redirect for the data route - redirects.push({ - route: dataRoute, - target, + // Add one redirect for the data route + redirects.push({ + route: dataRoute, + target, + }) }) -}) + return redirects +} -module.exports = redirects +module.exports = getRedirects diff --git a/src/lib/pages/getStaticPropsWithFallback/setup.js b/src/lib/pages/getStaticPropsWithFallback/setup.js index e66013ac22..394164c972 100644 --- a/src/lib/pages/getStaticPropsWithFallback/setup.js +++ b/src/lib/pages/getStaticPropsWithFallback/setup.js @@ -2,18 +2,21 @@ const { join } = require('path') const { logTitle, logItem } = require('../../helpers/logger') const getFilePathForRoute = require('../../helpers/getFilePathForRoute') const setupNetlifyFunctionForPage = require('../../helpers/setupNetlifyFunctionForPage') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') // Create a Netlify Function for every page with getStaticProps and fallback -const setup = (functionsPath) => { +const setup = async (functionsPath) => { logTitle('💫 Setting up pages with getStaticProps and fallback: true', 'as Netlify Functions in', functionsPath) + const pages = await getPages() + // Create Netlify Function for every page - pages.forEach(({ route }) => { + await asyncForEach(pages, async ({ route }) => { const relativePath = getFilePathForRoute(route, 'js') const filePath = join('pages', relativePath) logItem(filePath) - setupNetlifyFunctionForPage({ filePath, functionsPath }) + await setupNetlifyFunctionForPage({ filePath, functionsPath }) }) } diff --git a/src/lib/pages/getStaticPropsWithRevalidate/pages.js b/src/lib/pages/getStaticPropsWithRevalidate/pages.js index 99a9f88ec1..3f22eceacf 100644 --- a/src/lib/pages/getStaticPropsWithRevalidate/pages.js +++ b/src/lib/pages/getStaticPropsWithRevalidate/pages.js @@ -1,27 +1,30 @@ const isRouteWithFallback = require('../../helpers/isRouteWithFallback') const getPrerenderManifest = require('../../helpers/getPrerenderManifest') - -// Collect pages -const pages = [] +const asyncForEach = require('../../helpers/asyncForEach') // Get pages using getStaticProps -const { routes } = getPrerenderManifest() +const getPages = async () => { + const { routes } = await getPrerenderManifest() + + // Collect pages + const pages = [] -// Parse pages -Object.entries(routes).forEach(([route, { dataRoute, srcRoute, initialRevalidateSeconds }]) => { - // Skip pages without revalidate, these are handled by getStaticProps/pages - if (!initialRevalidateSeconds) return + await asyncForEach(Object.entries(routes), async ([route, { dataRoute, srcRoute, initialRevalidateSeconds }]) => { + // Skip pages without revalidate, these are handled by getStaticProps/pages + if (!initialRevalidateSeconds) return - // Skip pages with fallback, these are handled by - // getStaticPropsWithFallback/pages - if (isRouteWithFallback(srcRoute)) return + // Skip pages with fallback, these are handled by + // getStaticPropsWithFallback/pages + if (await isRouteWithFallback(srcRoute)) return - // Add the page - pages.push({ - route, - srcRoute, - dataRoute, + // Add the page + pages.push({ + route, + srcRoute, + dataRoute, + }) }) -}) + return pages +} -module.exports = pages +module.exports = getPages diff --git a/src/lib/pages/getStaticPropsWithRevalidate/redirects.js b/src/lib/pages/getStaticPropsWithRevalidate/redirects.js index 4e1de3009d..8e2d0db5c0 100644 --- a/src/lib/pages/getStaticPropsWithRevalidate/redirects.js +++ b/src/lib/pages/getStaticPropsWithRevalidate/redirects.js @@ -2,9 +2,8 @@ const { join } = require('path') const addDefaultLocaleRedirect = require('../../helpers/addDefaultLocaleRedirect') const getFilePathForRoute = require('../../helpers/getFilePathForRoute') const getNetlifyFunctionName = require('../../helpers/getNetlifyFunctionName') -const pages = require('./pages') - -const redirects = [] +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') /** getStaticProps with revalidate pages * @@ -21,25 +20,32 @@ const redirects = [] * } **/ -pages.forEach(({ route, srcRoute, dataRoute }) => { - const relativePath = getFilePathForRoute(srcRoute || route, 'js') - const filePath = join('pages', relativePath) - const functionName = getNetlifyFunctionName(filePath) - const target = `/.netlify/functions/${functionName}` +const getRedirects = async () => { + const redirects = [] + const pages = await getPages() - // Add one redirect for the page - redirects.push({ - route, - target, - }) + await asyncForEach(pages, async ({ route, srcRoute, dataRoute }) => { + const relativePath = getFilePathForRoute(srcRoute || route, 'js') + const filePath = join('pages', relativePath) + const functionName = getNetlifyFunctionName(filePath) + const target = `/.netlify/functions/${functionName}` + + // Add one redirect for the page + redirects.push({ + route, + target, + }) + + // Add one redirect for the data route + redirects.push({ + route: dataRoute, + target, + }) - // Add one redirect for the data route - redirects.push({ - route: dataRoute, - target, + await addDefaultLocaleRedirect(redirects, route, target) }) - addDefaultLocaleRedirect(redirects)(route, target) -}) + return redirects +} -module.exports = redirects +module.exports = getRedirects diff --git a/src/lib/pages/getStaticPropsWithRevalidate/setup.js b/src/lib/pages/getStaticPropsWithRevalidate/setup.js index f4ba710855..5ced1397b8 100644 --- a/src/lib/pages/getStaticPropsWithRevalidate/setup.js +++ b/src/lib/pages/getStaticPropsWithRevalidate/setup.js @@ -2,10 +2,11 @@ const { join } = require('path') const { logTitle, logItem } = require('../../helpers/logger') const getFilePathForRoute = require('../../helpers/getFilePathForRoute') const setupNetlifyFunctionForPage = require('../../helpers/setupNetlifyFunctionForPage') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') // Create a Netlify Function for every page with getStaticProps and revalidate -const setup = (functionsPath) => { +const setup = async (functionsPath) => { logTitle( '💫 Setting up pages with getStaticProps and revalidation interval', 'as Netlify Functions in', @@ -16,8 +17,10 @@ const setup = (functionsPath) => { // a function for the same file path twice const filePathsDone = [] + const pages = await getPages() + // Create Netlify Function for every page - pages.forEach(({ route, srcRoute }) => { + await asyncForEach(pages, async ({ route, srcRoute }) => { const relativePath = getFilePathForRoute(srcRoute || route, 'js') const filePath = join('pages', relativePath) @@ -26,7 +29,7 @@ const setup = (functionsPath) => { // Set up the function logItem(filePath) - setupNetlifyFunctionForPage({ filePath, functionsPath }) + await setupNetlifyFunctionForPage({ filePath, functionsPath }) filePathsDone.push(filePath) }) } diff --git a/src/lib/pages/withoutProps/pages.js b/src/lib/pages/withoutProps/pages.js index bccb7cb30d..27fe9e066d 100644 --- a/src/lib/pages/withoutProps/pages.js +++ b/src/lib/pages/withoutProps/pages.js @@ -1,23 +1,27 @@ const getPagesManifest = require('../../helpers/getPagesManifest') const isHtmlFile = require('../../helpers/isHtmlFile') const isRouteInPrerenderManifest = require('../../helpers/isRouteInPrerenderManifest') +const asyncForEach = require('../../helpers/asyncForEach') // Collect pages -const pages = [] +const getPages = async () => { + const pages = [] -// Get HTML and SSR pages and API endpoints from the NextJS pages manifest -const pagesManifest = getPagesManifest() + // Get HTML and SSR pages and API endpoints from the NextJS pages manifest + const pagesManifest = await getPagesManifest() -// Parse HTML pages -Object.entries(pagesManifest).forEach(([route, filePath]) => { - // Ignore non-HTML files - if (!isHtmlFile(filePath)) return + // Parse HTML pages + await asyncForEach(Object.entries(pagesManifest), async ([route, filePath]) => { + // Ignore non-HTML files + if (!isHtmlFile(filePath)) return - // Skip page if it is actually used with getStaticProps - if (isRouteInPrerenderManifest(route)) return + // Skip page if it is actually used with getStaticProps + if (await isRouteInPrerenderManifest(route)) return - // Add the HTML page - pages.push({ route, filePath }) -}) + // Add the HTML page + pages.push({ route, filePath }) + }) + return pages +} -module.exports = pages +module.exports = getPages diff --git a/src/lib/pages/withoutProps/redirects.js b/src/lib/pages/withoutProps/redirects.js index ee2278cf5a..8114bf92f6 100644 --- a/src/lib/pages/withoutProps/redirects.js +++ b/src/lib/pages/withoutProps/redirects.js @@ -1,8 +1,7 @@ const addDefaultLocaleRedirect = require('../../helpers/addDefaultLocaleRedirect') const isDynamicRoute = require('../../helpers/isDynamicRoute') -const pages = require('./pages') - -let redirects = [] +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') /** withoutProps pages * @@ -17,18 +16,24 @@ let redirects = [] * } **/ -pages.forEach(({ route, filePath }) => { - const target = filePath.replace(/pages/, '') +const getRedirects = async () => { + const redirects = [] + const pages = await getPages() + + await asyncForEach(pages, async ({ route, filePath }) => { + const target = filePath.replace(/pages/, '') - addDefaultLocaleRedirect(redirects)(route, target) + await addDefaultLocaleRedirect(redirects, route, target) - // Only create normal redirects for pages with dynamic routing - if (!isDynamicRoute(route)) return + // Only create normal redirects for pages with dynamic routing + if (!isDynamicRoute(route)) return - redirects.push({ - route, - target: filePath.replace(/pages/, ''), + redirects.push({ + route, + target: filePath.replace(/pages/, ''), + }) }) -}) + return redirects +} -module.exports = redirects +module.exports = getRedirects diff --git a/src/lib/pages/withoutProps/setup.js b/src/lib/pages/withoutProps/setup.js index cfe4175943..13ea8ce21e 100644 --- a/src/lib/pages/withoutProps/setup.js +++ b/src/lib/pages/withoutProps/setup.js @@ -1,28 +1,33 @@ const { join, relative } = require('path') const { copySync } = require('fs-extra') const { logTitle, logItem } = require('../../helpers/logger') -const { NEXT_DIST_DIR } = require('../../config') -const i18n = require('../../helpers/getI18n')() +const getNextDistDir = require('../../helpers/getNextDistDir') +const getI18n = require('../../helpers/getI18n') const setupStaticFileForPage = require('../../helpers/setupStaticFileForPage') -const pages = require('./pages') +const asyncForEach = require('../../helpers/asyncForEach') +const getPages = require('./pages') // Identify all pages that have been pre-rendered and copy each one to the // Netlify publish directory. -const setup = (publishPath) => { +const setup = async (publishPath) => { logTitle('🔥 Copying pre-rendered pages without props to', publishPath) + const i18n = await getI18n() + const nextDistDir = await getNextDistDir() + const pages = await getPages() + // Copy each page to the Netlify publish directory - pages.forEach(({ filePath }) => { + await asyncForEach(pages, async ({ filePath }) => { logItem(filePath) // HACK: If i18n, 404.html needs to be at the top level of the publish directory if (i18n.defaultLocale && filePath === `pages/${i18n.defaultLocale}/404.html`) { - copySync(join(NEXT_DIST_DIR, 'serverless', filePath), join(publishPath, '404.html')) + copySync(join(nextDistDir, 'serverless', filePath), join(publishPath, '404.html')) } // The path to the file, relative to the pages directory const relativePath = relative('pages', filePath) - setupStaticFileForPage({ inputPath: relativePath, publishPath }) + await setupStaticFileForPage({ inputPath: relativePath, publishPath }) }) } diff --git a/src/lib/steps/copyNextAssets.js b/src/lib/steps/copyNextAssets.js index 1409ba020d..c49a99b17e 100644 --- a/src/lib/steps/copyNextAssets.js +++ b/src/lib/steps/copyNextAssets.js @@ -1,12 +1,13 @@ const { join } = require('path') const { copySync, existsSync } = require('fs-extra') const { logTitle } = require('../helpers/logger') -const { NEXT_DIST_DIR } = require('../config') +const getNextDistDir = require('../helpers/getNextDistDir') // Copy the NextJS' static assets from NextJS distDir to Netlify publish folder. // These need to be available for NextJS to work. -const copyNextAssets = (publishPath) => { - const staticAssetsPath = join(NEXT_DIST_DIR, 'static') +const copyNextAssets = async (publishPath) => { + const nextDistDir = await getNextDistDir() + const staticAssetsPath = join(nextDistDir, 'static') if (!existsSync(staticAssetsPath)) { throw new Error( 'No static assets found in .next dist (aka no /.next/static). Please check your project configuration. Your next.config.js must be one of `serverless` or `experimental-serverless-trace`. Your build command should include `next build`.', diff --git a/src/lib/steps/setupPages.js b/src/lib/steps/setupPages.js index 20917a457a..94ca4a5564 100644 --- a/src/lib/steps/setupPages.js +++ b/src/lib/steps/setupPages.js @@ -1,12 +1,20 @@ +const apiSetup = require('../pages/api/setup') +const getInitialPropsSetup = require('../pages/getInitialProps/setup') +const getServerSidePropsSetup = require('../pages/getServerSideProps/setup') +const getStaticPropsSetup = require('../pages/getStaticProps/setup') +const getSPFallbackSetup = require('../pages/getStaticPropsWithFallback/setup') +const getSPRevalidateSetup = require('../pages/getStaticPropsWithRevalidate/setup') +const withoutPropsSetup = require('../pages/withoutProps/setup') + // Set up all our NextJS pages according to the recipes defined in pages/ -const setupPages = ({ functionsPath, publishPath }) => { - require('../pages/api/setup')(functionsPath) - require('../pages/getInitialProps/setup')(functionsPath) - require('../pages/getServerSideProps/setup')(functionsPath) - require('../pages/getStaticProps/setup')({ functionsPath, publishPath }) - require('../pages/getStaticPropsWithFallback/setup')(functionsPath) - require('../pages/getStaticPropsWithRevalidate/setup')(functionsPath) - require('../pages/withoutProps/setup')(publishPath) +const setupPages = async ({ functionsPath, publishPath }) => { + await apiSetup(functionsPath) + await getInitialPropsSetup(functionsPath) + await getServerSidePropsSetup(functionsPath) + await getStaticPropsSetup({ functionsPath, publishPath }) + await getSPFallbackSetup(functionsPath) + await getSPRevalidateSetup(functionsPath) + await withoutPropsSetup(publishPath) } module.exports = setupPages diff --git a/src/lib/steps/setupRedirects.js b/src/lib/steps/setupRedirects.js index 63178005b4..877941c575 100644 --- a/src/lib/steps/setupRedirects.js +++ b/src/lib/steps/setupRedirects.js @@ -10,7 +10,7 @@ const removeFileExtension = require('../helpers/removeFileExtension') // Setup _redirects file that routes all requests to the appropriate location, // such as one of the Netlify functions or one of the static files. -const setupRedirects = (publishPath) => { +const setupRedirects = async (publishPath) => { logTitle('🔀 Setting up redirects') // Collect custom redirects defined by the user @@ -21,14 +21,22 @@ const setupRedirects = (publishPath) => { } // Collect redirects for NextJS pages + const getApiRedirects = require('../pages/api/redirects') + const getInitialPropsRedirects = require('../pages/getInitialProps/redirects') + const getServerSidePropsRedirects = require('../pages/getServerSideProps/redirects') + const getStaticPropsRedirects = require('../pages/getStaticProps/redirects') + const getSPFallbackRedirects = require('../pages/getStaticPropsWithFallback/redirects') + const getSPRevalidateRedirects = require('../pages/getStaticPropsWithRevalidate/redirects') + const getWithoutPropsRedirects = require('../pages/withoutProps/redirects') + const nextRedirects = [ - ...require('../pages/api/redirects'), - ...require('../pages/getInitialProps/redirects'), - ...require('../pages/getServerSideProps/redirects'), - ...require('../pages/getStaticProps/redirects'), - ...require('../pages/getStaticPropsWithFallback/redirects'), - ...require('../pages/getStaticPropsWithRevalidate/redirects'), - ...require('../pages/withoutProps/redirects'), + ...(await getApiRedirects()), + ...(await getInitialPropsRedirects()), + ...(await getServerSidePropsRedirects()), + ...(await getStaticPropsRedirects()), + ...(await getSPFallbackRedirects()), + ...(await getSPRevalidateRedirects()), + ...(await getWithoutPropsRedirects()), ] // Add _redirect section heading diff --git a/src/next-on-netlify.js b/src/next-on-netlify.js index e3693d5446..9ae2626fcc 100644 --- a/src/next-on-netlify.js +++ b/src/next-on-netlify.js @@ -8,15 +8,15 @@ program.option('--max-log-lines [number]', 'lines of build output to show for ea program .command('watch') .description('re-runs next-on-netlify on changes') - .action(() => { - nextOnNetlify({ watch: true }) + .action(async () => { + await nextOnNetlify({ watch: true }) }) program .command('build', { isDefault: true }) .description('runs next-on-netlify') - .action(() => { - nextOnNetlify() + .action(async () => { + await nextOnNetlify() }) program.parse(process.argv) diff --git a/src/tests/__snapshots__/i18n.test.js.snap b/src/tests/__snapshots__/i18n.test.js.snap index e4910485d4..72c1edbeb2 100644 --- a/src/tests/__snapshots__/i18n.test.js.snap +++ b/src/tests/__snapshots__/i18n.test.js.snap @@ -4,6 +4,7 @@ exports[`Routing creates Netlify redirects 1`] = ` "# Next-on-Netlify Redirects / /.netlify/functions/next_index 200 /404 /en/404.html 200 +/500 /en/500.html 200 /_next/data/%BUILD_ID%/en.json /.netlify/functions/next_index 200 /_next/data/%BUILD_ID%/en/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200 /_next/data/%BUILD_ID%/en/getStaticProps/1.json /.netlify/functions/next_getStaticProps_id 200! Cookie=__prerender_bypass,__next_preview_data diff --git a/src/tests/helpers/buildNextApp.js b/src/tests/helpers/buildNextApp.js index 35bd3df190..470d59429e 100644 --- a/src/tests/helpers/buildNextApp.js +++ b/src/tests/helpers/buildNextApp.js @@ -103,7 +103,7 @@ class NextAppBuilder { // Run next-on-netlify as an imported module const nextOnNetlify = require('../..') - nextOnNetlify({ + await nextOnNetlify({ functionsDir: join(this.__appPath, options.functionsDir), publishDir: join(this.__appPath, options.publishDir), }) diff --git a/test/index.js b/test/index.js index 72ee795e13..a1fb8d5926 100644 --- a/test/index.js +++ b/test/index.js @@ -24,7 +24,9 @@ const utils = { const changeCwd = function (cwd) { const originalCwd = process.cwd() process.chdir(cwd) - return process.chdir.bind(process, originalCwd) + return () => { + process.chdir(originalCwd) + } } // Move .next from sample project to current directory