diff --git a/CHANGELOG.md b/CHANGELOG.md index 234f90edba0..9b0d5784d68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ - Releases RTDB Emulator v4.11.0: Wire protocol update for `startAfter`, `endBefore`. - Changes `superstatic` dependency to `v8`, addressing Hosting emulator issues on Windows. - Fixes internal library that was not being correctly published. +- Add support for Next.js 13 in firebase deploy. +- Next.js routes with revalidate are now handled by the a backing Cloud Function. - Adds `--disable-triggers` flag to RTDB write commands. - Default enables experiment to skip deploying unmodified functions (#5192) - Default enables experiment to allow parameterized functions codebases (#5192) diff --git a/scripts/webframeworks-deploy-tests/hosting/.gitignore b/scripts/webframeworks-deploy-tests/hosting/.gitignore index c87c9b392c0..4f360c89d2a 100644 --- a/scripts/webframeworks-deploy-tests/hosting/.gitignore +++ b/scripts/webframeworks-deploy-tests/hosting/.gitignore @@ -34,3 +34,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +.vscode diff --git a/scripts/webframeworks-deploy-tests/hosting/app/bar/page.tsx b/scripts/webframeworks-deploy-tests/hosting/app/bar/page.tsx new file mode 100644 index 00000000000..2db606988f1 --- /dev/null +++ b/scripts/webframeworks-deploy-tests/hosting/app/bar/page.tsx @@ -0,0 +1,5 @@ +export const revalidate = 60; + +export default function Bar() { + return <>Bar; +} diff --git a/scripts/webframeworks-deploy-tests/hosting/app/foo/page.tsx b/scripts/webframeworks-deploy-tests/hosting/app/foo/page.tsx new file mode 100644 index 00000000000..3fb4cf4e4dc --- /dev/null +++ b/scripts/webframeworks-deploy-tests/hosting/app/foo/page.tsx @@ -0,0 +1,3 @@ +export default function Foo() { + return <>Foo; +} diff --git a/scripts/webframeworks-deploy-tests/hosting/app/layout.tsx b/scripts/webframeworks-deploy-tests/hosting/app/layout.tsx new file mode 100644 index 00000000000..7b221173feb --- /dev/null +++ b/scripts/webframeworks-deploy-tests/hosting/app/layout.tsx @@ -0,0 +1,8 @@ +export default function RootLayout({ children }: any) { + return ( + + + {children} + + ) +} diff --git a/scripts/webframeworks-deploy-tests/hosting/next.config.js b/scripts/webframeworks-deploy-tests/hosting/next.config.js index ae887958d3c..d3ef77accdd 100644 --- a/scripts/webframeworks-deploy-tests/hosting/next.config.js +++ b/scripts/webframeworks-deploy-tests/hosting/next.config.js @@ -2,6 +2,9 @@ const nextConfig = { reactStrictMode: true, swcMinify: true, + experimental: { + appDir: true + }, } module.exports = nextConfig diff --git a/scripts/webframeworks-deploy-tests/hosting/package-lock.json b/scripts/webframeworks-deploy-tests/hosting/package-lock.json index 5b23704afab..69330694bbc 100644 --- a/scripts/webframeworks-deploy-tests/hosting/package-lock.json +++ b/scripts/webframeworks-deploy-tests/hosting/package-lock.json @@ -8,7 +8,7 @@ "name": "hosting", "version": "0.1.0", "dependencies": { - "next": "12.3.1", + "next": "13.0.0", "react": "18.2.0", "react-dom": "18.2.0" }, @@ -113,9 +113,9 @@ "dev": true }, "node_modules/@next/env": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.1.tgz", - "integrity": "sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==" + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.0.0.tgz", + "integrity": "sha512-65v9BVuah2Mplohm4+efsKEnoEuhmlGm8B2w6vD1geeEP2wXtlSJCvR/cCRJ3fD8wzCQBV41VcMBQeYET6MRkg==" }, "node_modules/@next/eslint-plugin-next": { "version": "12.3.1", @@ -127,9 +127,9 @@ } }, "node_modules/@next/swc-android-arm-eabi": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz", - "integrity": "sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.0.0.tgz", + "integrity": "sha512-+DUQkYF93gxFjWY+CYWE1QDX6gTgnUiWf+W4UqZjM1Jcef8U97fS6xYh+i+8rH4MM0AXHm7OSakvfOMzmjU6VA==", "cpu": [ "arm" ], @@ -142,9 +142,9 @@ } }, "node_modules/@next/swc-android-arm64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz", - "integrity": "sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.0.0.tgz", + "integrity": "sha512-RW9Uy3bMSc0zVGCa11klFuwfP/jdcdkhdruqnrJ7v+7XHm6OFKkSRzX6ee7yGR1rdDZvTnP4GZSRSpzjLv/N0g==", "cpu": [ "arm64" ], @@ -157,9 +157,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz", - "integrity": "sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.0.0.tgz", + "integrity": "sha512-APA26nps1j4qyhOIzkclW/OmgotVHj1jBxebSpMCPw2rXfiNvKNY9FA0TcuwPmUCNqaTnm703h6oW4dvp73A4Q==", "cpu": [ "arm64" ], @@ -172,9 +172,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz", - "integrity": "sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.0.0.tgz", + "integrity": "sha512-qsUhUdoFuRJiaJ7LnvTQ6GZv1QnMDcRXCIjxaN0FNVXwrjkq++U7KjBUaxXkRzLV4C7u0NHLNOp0iZwNNE7ypw==", "cpu": [ "x64" ], @@ -187,9 +187,9 @@ } }, "node_modules/@next/swc-freebsd-x64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz", - "integrity": "sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.0.0.tgz", + "integrity": "sha512-sCdyCbboS7CwdnevKH9J6hkJI76LUw1jVWt4eV7kISuLiPba3JmehZSWm80oa4ADChRVAwzhLAo2zJaYRrInbg==", "cpu": [ "x64" ], @@ -202,9 +202,9 @@ } }, "node_modules/@next/swc-linux-arm-gnueabihf": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz", - "integrity": "sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.0.0.tgz", + "integrity": "sha512-/X/VxfFA41C9jrEv+sUsPLQ5vbDPVIgG0CJrzKvrcc+b+4zIgPgtfsaWq9ockjHFQi3ycvlZK4TALOXO8ovQ6Q==", "cpu": [ "arm" ], @@ -217,9 +217,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz", - "integrity": "sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.0.0.tgz", + "integrity": "sha512-x6Oxr1GIi0ZtNiT6jbw+JVcbEi3UQgF7mMmkrgfL4mfchOwXtWSHKTSSPnwoJWJfXYa0Vy1n8NElWNTGAqoWFw==", "cpu": [ "arm64" ], @@ -232,9 +232,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz", - "integrity": "sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.0.0.tgz", + "integrity": "sha512-SnMH9ngI+ipGh3kqQ8+mDtWunirwmhQnQeZkEq9e/9Xsgjf04OetqrqRHKM1HmJtG2qMUJbyXFJ0F81TPuT+3g==", "cpu": [ "arm64" ], @@ -247,9 +247,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz", - "integrity": "sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.0.0.tgz", + "integrity": "sha512-VSQwTX9EmdbotArtA1J67X8964oQfe0xHb32x4tu+JqTR+wOHyG6wGzPMdXH2oKAp6rdd7BzqxUXXf0J+ypHlw==", "cpu": [ "x64" ], @@ -262,9 +262,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz", - "integrity": "sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.0.0.tgz", + "integrity": "sha512-xBCP0nnpO0q4tsytXkvIwWFINtbFRyVY5gxa1zB0vlFtqYR9lNhrOwH3CBrks3kkeaePOXd611+8sjdUtrLnXA==", "cpu": [ "x64" ], @@ -277,9 +277,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz", - "integrity": "sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.0.0.tgz", + "integrity": "sha512-NutwDafqhGxqPj/eiUixJq9ImS/0sgx6gqlD7jRndCvQ2Q8AvDdu1+xKcGWGNnhcDsNM/n1avf1e62OG1GaqJg==", "cpu": [ "arm64" ], @@ -292,9 +292,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz", - "integrity": "sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.0.0.tgz", + "integrity": "sha512-zNaxaO+Kl/xNz02E9QlcVz0pT4MjkXGDLb25qxtAzyJL15aU0+VjjbIZAYWctG59dvggNIUNDWgoBeVTKB9xLg==", "cpu": [ "ia32" ], @@ -307,9 +307,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz", - "integrity": "sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.0.0.tgz", + "integrity": "sha512-FFOGGWwTCRMu9W7MF496Urefxtuo2lttxF1vwS+1rIRsKvuLrWhVaVTj3T8sf2EBL6gtJbmh4TYlizS+obnGKA==", "cpu": [ "x64" ], @@ -761,6 +761,11 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2195,43 +2200,43 @@ "dev": true }, "node_modules/next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/next/-/next-12.3.1.tgz", - "integrity": "sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/next/-/next-13.0.0.tgz", + "integrity": "sha512-puH1WGM6rGeFOoFdXXYfUxN9Sgi4LMytCV5HkQJvVUOhHfC1DoVqOfvzaEteyp6P04IW+gbtK2Q9pInVSrltPA==", "dependencies": { - "@next/env": "12.3.1", + "@next/env": "13.0.0", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", - "styled-jsx": "5.0.7", + "styled-jsx": "5.1.0", "use-sync-external-store": "1.2.0" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=12.22.0" + "node": ">=14.6.0" }, "optionalDependencies": { - "@next/swc-android-arm-eabi": "12.3.1", - "@next/swc-android-arm64": "12.3.1", - "@next/swc-darwin-arm64": "12.3.1", - "@next/swc-darwin-x64": "12.3.1", - "@next/swc-freebsd-x64": "12.3.1", - "@next/swc-linux-arm-gnueabihf": "12.3.1", - "@next/swc-linux-arm64-gnu": "12.3.1", - "@next/swc-linux-arm64-musl": "12.3.1", - "@next/swc-linux-x64-gnu": "12.3.1", - "@next/swc-linux-x64-musl": "12.3.1", - "@next/swc-win32-arm64-msvc": "12.3.1", - "@next/swc-win32-ia32-msvc": "12.3.1", - "@next/swc-win32-x64-msvc": "12.3.1" + "@next/swc-android-arm-eabi": "13.0.0", + "@next/swc-android-arm64": "13.0.0", + "@next/swc-darwin-arm64": "13.0.0", + "@next/swc-darwin-x64": "13.0.0", + "@next/swc-freebsd-x64": "13.0.0", + "@next/swc-linux-arm-gnueabihf": "13.0.0", + "@next/swc-linux-arm64-gnu": "13.0.0", + "@next/swc-linux-arm64-musl": "13.0.0", + "@next/swc-linux-x64-gnu": "13.0.0", + "@next/swc-linux-x64-musl": "13.0.0", + "@next/swc-win32-arm64-msvc": "13.0.0", + "@next/swc-win32-ia32-msvc": "13.0.0", + "@next/swc-win32-x64-msvc": "13.0.0" }, "peerDependencies": { "fibers": ">= 3.1.0", "node-sass": "^6.0.0 || ^7.0.0", - "react": "^17.0.2 || ^18.0.0-0", - "react-dom": "^17.0.2 || ^18.0.0-0", + "react": "^18.0.0-0", + "react-dom": "^18.0.0-0", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -2859,9 +2864,12 @@ } }, "node_modules/styled-jsx": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.0.tgz", + "integrity": "sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==", + "dependencies": { + "client-only": "0.0.1" + }, "engines": { "node": ">= 12.0.0" }, @@ -3158,9 +3166,9 @@ "dev": true }, "@next/env": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.1.tgz", - "integrity": "sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==" + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.0.0.tgz", + "integrity": "sha512-65v9BVuah2Mplohm4+efsKEnoEuhmlGm8B2w6vD1geeEP2wXtlSJCvR/cCRJ3fD8wzCQBV41VcMBQeYET6MRkg==" }, "@next/eslint-plugin-next": { "version": "12.3.1", @@ -3172,81 +3180,81 @@ } }, "@next/swc-android-arm-eabi": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz", - "integrity": "sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.0.0.tgz", + "integrity": "sha512-+DUQkYF93gxFjWY+CYWE1QDX6gTgnUiWf+W4UqZjM1Jcef8U97fS6xYh+i+8rH4MM0AXHm7OSakvfOMzmjU6VA==", "optional": true }, "@next/swc-android-arm64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz", - "integrity": "sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-13.0.0.tgz", + "integrity": "sha512-RW9Uy3bMSc0zVGCa11klFuwfP/jdcdkhdruqnrJ7v+7XHm6OFKkSRzX6ee7yGR1rdDZvTnP4GZSRSpzjLv/N0g==", "optional": true }, "@next/swc-darwin-arm64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz", - "integrity": "sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.0.0.tgz", + "integrity": "sha512-APA26nps1j4qyhOIzkclW/OmgotVHj1jBxebSpMCPw2rXfiNvKNY9FA0TcuwPmUCNqaTnm703h6oW4dvp73A4Q==", "optional": true }, "@next/swc-darwin-x64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz", - "integrity": "sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.0.0.tgz", + "integrity": "sha512-qsUhUdoFuRJiaJ7LnvTQ6GZv1QnMDcRXCIjxaN0FNVXwrjkq++U7KjBUaxXkRzLV4C7u0NHLNOp0iZwNNE7ypw==", "optional": true }, "@next/swc-freebsd-x64": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz", - "integrity": "sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.0.0.tgz", + "integrity": "sha512-sCdyCbboS7CwdnevKH9J6hkJI76LUw1jVWt4eV7kISuLiPba3JmehZSWm80oa4ADChRVAwzhLAo2zJaYRrInbg==", "optional": true }, "@next/swc-linux-arm-gnueabihf": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz", - "integrity": "sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.0.0.tgz", + "integrity": "sha512-/X/VxfFA41C9jrEv+sUsPLQ5vbDPVIgG0CJrzKvrcc+b+4zIgPgtfsaWq9ockjHFQi3ycvlZK4TALOXO8ovQ6Q==", "optional": true }, "@next/swc-linux-arm64-gnu": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz", - "integrity": "sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.0.0.tgz", + "integrity": "sha512-x6Oxr1GIi0ZtNiT6jbw+JVcbEi3UQgF7mMmkrgfL4mfchOwXtWSHKTSSPnwoJWJfXYa0Vy1n8NElWNTGAqoWFw==", "optional": true }, "@next/swc-linux-arm64-musl": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz", - "integrity": "sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.0.0.tgz", + "integrity": "sha512-SnMH9ngI+ipGh3kqQ8+mDtWunirwmhQnQeZkEq9e/9Xsgjf04OetqrqRHKM1HmJtG2qMUJbyXFJ0F81TPuT+3g==", "optional": true }, "@next/swc-linux-x64-gnu": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz", - "integrity": "sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.0.0.tgz", + "integrity": "sha512-VSQwTX9EmdbotArtA1J67X8964oQfe0xHb32x4tu+JqTR+wOHyG6wGzPMdXH2oKAp6rdd7BzqxUXXf0J+ypHlw==", "optional": true }, "@next/swc-linux-x64-musl": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz", - "integrity": "sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.0.0.tgz", + "integrity": "sha512-xBCP0nnpO0q4tsytXkvIwWFINtbFRyVY5gxa1zB0vlFtqYR9lNhrOwH3CBrks3kkeaePOXd611+8sjdUtrLnXA==", "optional": true }, "@next/swc-win32-arm64-msvc": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz", - "integrity": "sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.0.0.tgz", + "integrity": "sha512-NutwDafqhGxqPj/eiUixJq9ImS/0sgx6gqlD7jRndCvQ2Q8AvDdu1+xKcGWGNnhcDsNM/n1avf1e62OG1GaqJg==", "optional": true }, "@next/swc-win32-ia32-msvc": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz", - "integrity": "sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.0.0.tgz", + "integrity": "sha512-zNaxaO+Kl/xNz02E9QlcVz0pT4MjkXGDLb25qxtAzyJL15aU0+VjjbIZAYWctG59dvggNIUNDWgoBeVTKB9xLg==", "optional": true }, "@next/swc-win32-x64-msvc": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz", - "integrity": "sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.0.0.tgz", + "integrity": "sha512-FFOGGWwTCRMu9W7MF496Urefxtuo2lttxF1vwS+1rIRsKvuLrWhVaVTj3T8sf2EBL6gtJbmh4TYlizS+obnGKA==", "optional": true }, "@nodelib/fs.scandir": { @@ -3559,6 +3567,11 @@ "supports-color": "^7.1.0" } }, + "client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4637,28 +4650,28 @@ "dev": true }, "next": { - "version": "12.3.1", - "resolved": "https://registry.npmjs.org/next/-/next-12.3.1.tgz", - "integrity": "sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/next/-/next-13.0.0.tgz", + "integrity": "sha512-puH1WGM6rGeFOoFdXXYfUxN9Sgi4LMytCV5HkQJvVUOhHfC1DoVqOfvzaEteyp6P04IW+gbtK2Q9pInVSrltPA==", "requires": { - "@next/env": "12.3.1", - "@next/swc-android-arm-eabi": "12.3.1", - "@next/swc-android-arm64": "12.3.1", - "@next/swc-darwin-arm64": "12.3.1", - "@next/swc-darwin-x64": "12.3.1", - "@next/swc-freebsd-x64": "12.3.1", - "@next/swc-linux-arm-gnueabihf": "12.3.1", - "@next/swc-linux-arm64-gnu": "12.3.1", - "@next/swc-linux-arm64-musl": "12.3.1", - "@next/swc-linux-x64-gnu": "12.3.1", - "@next/swc-linux-x64-musl": "12.3.1", - "@next/swc-win32-arm64-msvc": "12.3.1", - "@next/swc-win32-ia32-msvc": "12.3.1", - "@next/swc-win32-x64-msvc": "12.3.1", + "@next/env": "13.0.0", + "@next/swc-android-arm-eabi": "13.0.0", + "@next/swc-android-arm64": "13.0.0", + "@next/swc-darwin-arm64": "13.0.0", + "@next/swc-darwin-x64": "13.0.0", + "@next/swc-freebsd-x64": "13.0.0", + "@next/swc-linux-arm-gnueabihf": "13.0.0", + "@next/swc-linux-arm64-gnu": "13.0.0", + "@next/swc-linux-arm64-musl": "13.0.0", + "@next/swc-linux-x64-gnu": "13.0.0", + "@next/swc-linux-x64-musl": "13.0.0", + "@next/swc-win32-arm64-msvc": "13.0.0", + "@next/swc-win32-ia32-msvc": "13.0.0", + "@next/swc-win32-x64-msvc": "13.0.0", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", - "styled-jsx": "5.0.7", + "styled-jsx": "5.1.0", "use-sync-external-store": "1.2.0" } }, @@ -5077,10 +5090,12 @@ "dev": true }, "styled-jsx": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", - "requires": {} + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.0.tgz", + "integrity": "sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==", + "requires": { + "client-only": "0.0.1" + } }, "supports-color": { "version": "7.2.0", diff --git a/scripts/webframeworks-deploy-tests/hosting/package.json b/scripts/webframeworks-deploy-tests/hosting/package.json index 767c471e2fb..337edffd67c 100644 --- a/scripts/webframeworks-deploy-tests/hosting/package.json +++ b/scripts/webframeworks-deploy-tests/hosting/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "next": "12.3.1", + "next": "13.0.0", "react": "18.2.0", "react-dom": "18.2.0" }, diff --git a/scripts/webframeworks-deploy-tests/hosting/tsconfig.json b/scripts/webframeworks-deploy-tests/hosting/tsconfig.json index 99710e85787..b25c4f834cb 100644 --- a/scripts/webframeworks-deploy-tests/hosting/tsconfig.json +++ b/scripts/webframeworks-deploy-tests/hosting/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -13,8 +17,20 @@ "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", - "incremental": true + "incremental": true, + "plugins": [ + { + "name": "next" + } + ] }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } diff --git a/scripts/webframeworks-deploy-tests/tests.ts b/scripts/webframeworks-deploy-tests/tests.ts index 120bfad0074..84341796168 100644 --- a/scripts/webframeworks-deploy-tests/tests.ts +++ b/scripts/webframeworks-deploy-tests/tests.ts @@ -45,7 +45,7 @@ describe("webframeworks deploy", function (this) { const result = await setOptsAndDeploy(); expect(result.stdout, "deploy result").to.match(/file upload complete/); - expect(result.stdout, "deploy result").to.match(/found 16 files/); + expect(result.stdout, "deploy result").to.match(/found 20 files/); expect(result.stdout, "deploy result").to.match(/Deploy complete!/); }); }); diff --git a/src/frameworks/next/index.ts b/src/frameworks/next/index.ts index b79c5a0510f..e13ba65b00e 100644 --- a/src/frameworks/next/index.ts +++ b/src/frameworks/next/index.ts @@ -1,11 +1,12 @@ import { execSync } from "child_process"; -import { readFile, mkdir, copyFile, stat } from "fs/promises"; -import { dirname, extname, join } from "path"; +import { readFile, mkdir, copyFile } from "fs/promises"; +import { dirname, join } from "path"; import type { Header, Rewrite, Redirect } from "next/dist/lib/load-custom-routes"; import type { NextConfig } from "next"; import { copy, mkdirp, pathExists } from "fs-extra"; import { pathToFileURL, parse } from "url"; import { existsSync } from "fs"; + import { BuildResult, createServerResponseProxy, @@ -20,6 +21,7 @@ import { gte } from "semver"; import { IncomingMessage, ServerResponse } from "http"; import { logger } from "../../logger"; import { FirebaseError } from "../../error"; +import { fileExistsSync } from "../../fsutils"; // Next.js's exposed interface is incomplete here // TODO see if there's a better way to grab this @@ -47,10 +49,14 @@ export const name = "Next.js"; export const support = SupportLevel.Experimental; export const type = FrameworkType.MetaFramework; -function getNextVersion(cwd: string) { +function getNextVersion(cwd: string): string | undefined { return findDependency("next", { cwd, depth: 0, omitDev: false })?.version; } +function getReactVersion(cwd: string): string | undefined { + return findDependency("react-dom", { cwd, omitDev: false })?.version; +} + /** * Returns whether this codebase is a Next.js backend. */ @@ -67,6 +73,12 @@ export async function discover(dir: string) { export async function build(dir: string): Promise { const { default: nextBuild } = relativeRequire(dir, "next/dist/build"); + const reactVersion = getReactVersion(dir); + if (reactVersion && gte(reactVersion, "18.0.0")) { + // This needs to be set for Next build to succeed with React 18 + process.env.__NEXT_REACT_ROOT = "true"; + } + await nextBuild(dir, null, false, false, true).catch((e) => { // Err on the side of displaying this error, since this is likely a bug in // the developer's code that we want to display immediately @@ -89,6 +101,10 @@ export async function build(dir: string): Promise { const exportDetailBuffer = exportDetailExists ? await readFile(exportDetailPath) : undefined; const exportDetailJson = exportDetailBuffer && JSON.parse(exportDetailBuffer.toString()); if (exportDetailJson?.success) { + const appPathRoutesManifestPath = join(dir, distDir, "app-path-routes-manifest.json"); + const appPathRoutesManifestJSON = fileExistsSync(appPathRoutesManifestPath) + ? await readFile(appPathRoutesManifestPath).then((it) => JSON.parse(it.toString())) + : {}; const prerenderManifestJSON = await readFile( join(dir, distDir, "prerender-manifest.json") ).then((it) => JSON.parse(it.toString())); @@ -100,10 +116,15 @@ export async function build(dir: string): Promise { ).then((it) => JSON.parse(it.toString())); const prerenderedRoutes = Object.keys(prerenderManifestJSON.routes); const dynamicRoutes = Object.keys(prerenderManifestJSON.dynamicRoutes); - const unrenderedPages = Object.keys(pagesManifestJSON).filter( + const unrenderedPages = [ + ...Object.keys(pagesManifestJSON), + // TODO flush out fully rendered detection with a app directory (Next 13) + // we shouldn't go too crazy here yet, as this is currently an expiriment + ...Object.values(appPathRoutesManifestJSON), + ].filter( (it) => !( - ["/_app", "/_error", "/_document", "/404"].includes(it) || + ["/_app", "/", "/_error", "/_document", "/404"].includes(it) || prerenderedRoutes.includes(it) || dynamicRoutes.includes(it) ) @@ -150,7 +171,7 @@ export async function init(setup: any) { choices: ["JavaScript", "TypeScript"], }); execSync( - `npx --yes create-next-app@latest -e hello-world ${setup.hosting.source} ${ + `npx --yes create-next-app@latest -e hello-world ${setup.hosting.source} --use-npm ${ language === "TypeScript" ? "--ts" : "" }`, { stdio: "inherit" } @@ -176,25 +197,37 @@ export async function ɵcodegenPublicDirectory(sourceDir: string, destDir: strin } await copy(join(sourceDir, distDir, "static"), join(destDir, "_next", "static")); - const serverPagesDir = join(sourceDir, distDir, "server", "pages"); - await copy(serverPagesDir, destDir, { - filter: async (filename) => { - const status = await stat(filename); - if (status.isDirectory()) return true; - return extname(filename) === ".html"; - }, - }); + // Copy over the default html files + for (const file of ["index.html", "404.html", "500.html"]) { + const pagesPath = join(sourceDir, distDir, "server", "pages", file); + if (await pathExists(pagesPath)) { + await copyFile(pagesPath, join(destDir, file)); + continue; + } + const appPath = join(sourceDir, distDir, "server", "app", file); + if (await pathExists(appPath)) { + await copyFile(appPath, join(destDir, file)); + } + } const prerenderManifestBuffer = await readFile( join(sourceDir, distDir, "prerender-manifest.json") ); const prerenderManifest = JSON.parse(prerenderManifestBuffer.toString()); - // TODO drop from hosting if revalidate - for (const route in prerenderManifest.routes) { - if (prerenderManifest.routes[route]) { + for (const path in prerenderManifest.routes) { + if (prerenderManifest.routes[path]) { + // Skip ISR in the deploy to hosting + const { initialRevalidateSeconds } = prerenderManifest.routes[path]; + if (initialRevalidateSeconds) { + continue; + } + + // TODO(jamesdaniels) explore oppertunity to simplify this now that we + // are defaulting cleanURLs to true for frameworks + // / => index.json => index.html => index.html // /foo => foo.json => foo.html - const parts = route + const parts = path .split("/") .slice(1) .filter((it) => !!it); @@ -202,16 +235,26 @@ export async function ɵcodegenPublicDirectory(sourceDir: string, destDir: strin const dataPath = `${join(...partsOrIndex)}.json`; const htmlPath = `${join(...partsOrIndex)}.html`; await mkdir(join(destDir, dirname(htmlPath)), { recursive: true }); - await copyFile( - join(sourceDir, distDir, "server", "pages", htmlPath), - join(destDir, htmlPath) - ); - const dataRoute = prerenderManifest.routes[route].dataRoute; + const pagesHtmlPath = join(sourceDir, distDir, "server", "pages", htmlPath); + if (await pathExists(pagesHtmlPath)) { + await copyFile(pagesHtmlPath, join(destDir, htmlPath)); + } else { + const appHtmlPath = join(sourceDir, distDir, "server", "app", htmlPath); + if (await pathExists(appHtmlPath)) { + await copyFile(appHtmlPath, join(destDir, htmlPath)); + } + } + const dataRoute = prerenderManifest.routes[path].dataRoute; await mkdir(join(destDir, dirname(dataRoute)), { recursive: true }); - await copyFile( - join(sourceDir, distDir, "server", "pages", dataPath), - join(destDir, dataRoute) - ); + const pagesDataPath = join(sourceDir, distDir, "server", "pages", dataPath); + if (await pathExists(pagesDataPath)) { + await copyFile(pagesDataPath, join(destDir, dataRoute)); + } else { + const appDataPath = join(sourceDir, distDir, "server", "app", dataPath); + if (await pathExists(appDataPath)) { + await copyFile(appDataPath, join(destDir, dataRoute)); + } + } } } }