diff --git a/next.config.js b/next.config.js index 9ee18918..7852092f 100644 --- a/next.config.js +++ b/next.config.js @@ -31,6 +31,9 @@ const nextConfig = { .concat(createRemotePattern(AWS_S3_HOSTNAME)), minimumCacheTTL: 31536000, }, + experimental: { + ppr: true, + }, }; const withBundleAnalyzer = require('@next/bundle-analyzer')({ diff --git a/package.json b/package.json index 52ea1f07..a36af680 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.4", - "next": "14.0.4", + "next": "14.0.5-canary.56", "next-auth": "5.0.0-beta.4", "next-themes": "^0.2.1", "postcss": "8.4.33", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4148d81a..ebd98e42 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,14 +90,14 @@ dependencies: specifier: ^5.0.4 version: 5.0.4 next: - specifier: 14.0.4 - version: 14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.0.5-canary.56 + version: 14.0.5-canary.56(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) next-auth: specifier: 5.0.0-beta.4 - version: 5.0.0-beta.4(next@14.0.4)(react@18.2.0) + version: 5.0.0-beta.4(next@14.0.5-canary.56)(react@18.2.0) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.0.4)(react-dom@18.2.0)(react@18.2.0) + version: 0.2.1(next@14.0.5-canary.56)(react-dom@18.2.0)(react@18.2.0) postcss: specifier: 8.4.33 version: 8.4.33 @@ -1527,8 +1527,8 @@ packages: - utf-8-validate dev: false - /@next/env@14.0.4: - resolution: {integrity: sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==} + /@next/env@14.0.5-canary.56: + resolution: {integrity: sha512-CVGGq09V4t62GT3W7vWxzu92D+hkGLVZRoaxi8/WanvhtTuFsAjtp9UreZjyaPunRSXs/OTTXmKe4gzYtn2AiA==} dev: false /@next/eslint-plugin-next@14.0.4: @@ -1537,8 +1537,8 @@ packages: glob: 7.1.7 dev: false - /@next/swc-darwin-arm64@14.0.4: - resolution: {integrity: sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==} + /@next/swc-darwin-arm64@14.0.5-canary.56: + resolution: {integrity: sha512-q2c0b2qoww+fiKlLxNfx82C/4dIO2ne0L24UKE5RrA/XcCD5BEyiPgDjP/sidkzq98pZo3QOmzO5tGExBECY/g==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -1546,8 +1546,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@14.0.4: - resolution: {integrity: sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==} + /@next/swc-darwin-x64@14.0.5-canary.56: + resolution: {integrity: sha512-Rb5ZtjQ9vPmJMbZz9zVR+g8JMFj9KGbcT2lKGrLtP9+RVAQUaV2kO81jE+tgzGxvM3MlKEUJ92d+5DaXA4i29w==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -1555,8 +1555,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@14.0.4: - resolution: {integrity: sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==} + /@next/swc-linux-arm64-gnu@14.0.5-canary.56: + resolution: {integrity: sha512-cF3tnEFniuwPCxw4A548St2IoSIm2oyp+Vcr2F3JHN3xYJeCErX0TPKB1+3tGsoMSr4KdlNTFuOIb2mzXiS7JQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1564,8 +1564,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@14.0.4: - resolution: {integrity: sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==} + /@next/swc-linux-arm64-musl@14.0.5-canary.56: + resolution: {integrity: sha512-ZQijTP3uBQIdlPDhn+gi+Nw9g69O1rhbP8k/tEc40M3rTefhRUQn840lZxy/19Z9/v9Hh+7JvOv+fbYdu03cAg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1573,8 +1573,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@14.0.4: - resolution: {integrity: sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==} + /@next/swc-linux-x64-gnu@14.0.5-canary.56: + resolution: {integrity: sha512-TtcnuctL8cF/udBB3bFCy76ci+rjRbHoUEw7O08fr7uLDuDP9WpefKqy2i31a1DF9kzZMC82bJIkLmdS6s+gOQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1582,8 +1582,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@14.0.4: - resolution: {integrity: sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==} + /@next/swc-linux-x64-musl@14.0.5-canary.56: + resolution: {integrity: sha512-cxF1QO29mJjBLRr91ztaT4ycZXBpes8z395WQUlAk0kLWKnprudM/pinQcqemG/llk1sTLFHHDFsSVm2INKpcw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1591,8 +1591,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@14.0.4: - resolution: {integrity: sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==} + /@next/swc-win32-arm64-msvc@14.0.5-canary.56: + resolution: {integrity: sha512-U0WBNyv4Uwkbu050GlbgxQjMjNiAiO7gH3J2KeSj7/QbSTxzfUEzQS5hZNpBi1znpgrqyysaD9uh1ncHoTebjA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -1600,8 +1600,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@14.0.4: - resolution: {integrity: sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==} + /@next/swc-win32-ia32-msvc@14.0.5-canary.56: + resolution: {integrity: sha512-UCcbNHJLM4J6BcIjLuFzP98VjR+Yj+sQlTkK84K5a2/hPV02gaD8A/39WxmYARlkYrEqanmH8EXe3klV3oDR+A==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -1609,8 +1609,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@14.0.4: - resolution: {integrity: sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==} + /@next/swc-win32-x64-msvc@14.0.5-canary.56: + resolution: {integrity: sha512-cZmqqyBJO73XpwuYTL/XTUUbSnjcLAmOdiCjEGlFTTTBHI/x6TDO005xICu9X2AqQWIP/N3qIwz41WBK8iveZg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4163,10 +4163,6 @@ packages: is-glob: 4.0.3 dev: false - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: false - /glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -5440,7 +5436,7 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false - /next-auth@5.0.0-beta.4(next@14.0.4)(react@18.2.0): + /next-auth@5.0.0-beta.4(next@14.0.5-canary.56)(react@18.2.0): resolution: {integrity: sha512-vgocjvwPA8gxd/zrIP/vr9lJ/HeNe+C56lPP1D3sdyenHt8KncQV6ro7q0xCsDp1fcOKx7WAWVZH5o8aMxDzgw==} peerDependencies: next: ^14 @@ -5451,24 +5447,24 @@ packages: optional: true dependencies: '@auth/core': 0.18.4 - next: 14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + next: 14.0.5-canary.56(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false - /next-themes@0.2.1(next@14.0.4)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@14.0.5-canary.56)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) + next: 14.0.5-canary.56(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /next@14.0.4(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==} + /next@14.0.5-canary.56(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-7CVdOI+q7rdGcr5flmrOwzjKIb/0sIESp4yUYw55KzrVOYSvhTC+FFMsMhdn9w9LgLfKfjR0eEtXFIUhjoV/7w==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -5482,7 +5478,7 @@ packages: sass: optional: true dependencies: - '@next/env': 14.0.4 + '@next/env': 14.0.5-canary.56 '@swc/helpers': 0.5.2 busboy: 1.6.0 caniuse-lite: 1.0.30001572 @@ -5491,17 +5487,16 @@ packages: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(@babel/core@7.23.7)(react@18.2.0) - watchpack: 2.4.0 optionalDependencies: - '@next/swc-darwin-arm64': 14.0.4 - '@next/swc-darwin-x64': 14.0.4 - '@next/swc-linux-arm64-gnu': 14.0.4 - '@next/swc-linux-arm64-musl': 14.0.4 - '@next/swc-linux-x64-gnu': 14.0.4 - '@next/swc-linux-x64-musl': 14.0.4 - '@next/swc-win32-arm64-msvc': 14.0.4 - '@next/swc-win32-ia32-msvc': 14.0.4 - '@next/swc-win32-x64-msvc': 14.0.4 + '@next/swc-darwin-arm64': 14.0.5-canary.56 + '@next/swc-darwin-x64': 14.0.5-canary.56 + '@next/swc-linux-arm64-gnu': 14.0.5-canary.56 + '@next/swc-linux-arm64-musl': 14.0.5-canary.56 + '@next/swc-linux-x64-gnu': 14.0.5-canary.56 + '@next/swc-linux-x64-musl': 14.0.5-canary.56 + '@next/swc-win32-arm64-msvc': 14.0.5-canary.56 + '@next/swc-win32-ia32-msvc': 14.0.5-canary.56 + '@next/swc-win32-x64-msvc': 14.0.5-canary.56 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -6774,14 +6769,6 @@ packages: makeerror: 1.0.12 dev: false - /watchpack@2.4.0: - resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - dev: false - /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9aeff4bc..a278f0aa 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,7 +2,6 @@ import { Analytics } from '@vercel/analytics/react'; import { SpeedInsights } from '@vercel/speed-insights/react'; import { clsx } from 'clsx/lite'; import { IBM_Plex_Mono } from 'next/font/google'; -import { Metadata } from 'next'; import { BASE_URL, SITE_DESCRIPTION, SITE_TITLE } from '@/site/config'; import StateProvider from '@/state/AppStateProvider'; import ThemeProviderClient from '@/site/ThemeProviderClient'; @@ -13,6 +12,7 @@ import Footer from '@/site/Footer'; import { Suspense } from 'react'; import FooterClient from '@/site/FooterClient'; import NavClient from '@/site/NavClient'; +import { Metadata } from 'next/types'; import '../site/globals.css'; diff --git a/src/app/page.tsx b/src/app/page.tsx index 263ca855..ca38e7ea 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,7 @@ import { getPhotosCached, getPhotosCountCached } from '@/cache'; import { LARGE_PHOTOS_TO_SHOW, generateOgImageMetaForPhotos } from '@/photo'; import PhotosEmptyState from '@/photo/PhotosEmptyState'; -import { Metadata } from 'next'; +import { Metadata } from 'next/types'; import { MAX_PHOTOS_TO_SHOW_OG } from '@/photo/image-response'; import MoreComponents from '@/components/MoreComponents'; import PhotosLarge from '@/photo/PhotosLarge'; diff --git a/src/services/vercel-postgres.ts b/src/services/vercel-postgres.ts index f1cdd690..5e68abf4 100644 --- a/src/services/vercel-postgres.ts +++ b/src/services/vercel-postgres.ts @@ -282,7 +282,11 @@ const safelyQueryPhotos = async (callback: () => Promise): Promise => { try { result = await callback(); } catch (e: any) { - if (/relation "photos" does not exist/i.test(e.message)) { + if (/ppr-caught-error/.test(e.message) && e.sourceError) { + // PPR errors, if caught, must be re-thrown in order to + // postpone rendering + throw e.sourceError; + } else if (/relation "photos" does not exist/i.test(e.message)) { console.log('Creating table "photos" because it did not exist'); await sqlCreatePhotosTable(); result = await callback();