From f5680fd685e6625a5f96219018936d48c0ade18c Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 27 Apr 2024 23:48:13 -0500 Subject: [PATCH 1/8] Add basic ppr settings --- README.md | 1 + next.config.js | 10 + package.json | 2 +- pnpm-lock.yaml | 390 ++++++++++++++++++++++++++----- src/app/loading.tsx | 1 + src/app/p/[photoId]/layout.tsx | 13 ++ src/photo/index.ts | 2 + src/site/SiteChecklistClient.tsx | 12 + src/site/config.ts | 4 + 9 files changed, 370 insertions(+), 65 deletions(-) create mode 100644 src/app/loading.tsx diff --git a/README.md b/README.md index be4000dc..eda4fcd4 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ _⚠️ READ BEFORE PROCEEDING_ Application behavior can be changed by configuring the following environment variables: - `NEXT_PUBLIC_PRO_MODE = 1` enables higher quality image storage (results in increased storage usage) +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE = 1` enables PPR and static optimization, i.e., building pages ahead of time (results in increased storage usage)—⚠️ _Experimental_ - `NEXT_PUBLIC_BLUR_DISABLED = 1` prevents image blur data being stored and displayed (potentially useful for limiting Postgres usage) - `NEXT_PUBLIC_GEO_PRIVACY = 1` disables collection/display of location-based data - `NEXT_PUBLIC_IGNORE_PRIORITY_ORDER = 1` prevents `priority_order` field affecting photo order diff --git a/next.config.js b/next.config.js index f0ff1b30..4520e734 100644 --- a/next.config.js +++ b/next.config.js @@ -35,6 +35,16 @@ const nextConfig = { .concat(createRemotePattern(HOSTNAME_AWS_S3)), minimumCacheTTL: 31536000, }, + ...process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE === '1' && { + experimental: { ppr: true }, + }, + webpack: (config) => { + config.optimization ??= {}; + if (process.env.NODE_ENV !== 'production') { + config.optimization.minimize = false; + } + return config; + }, }; const withBundleAnalyzer = require('@next/bundle-analyzer')({ diff --git a/package.json b/package.json index 22c5f368..a088a2d2 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.7", - "next": "^14.2.3", + "next": "14.3.0-canary.29", "next-auth": "5.0.0-beta.15", "next-themes": "^0.3.0", "openai": "^4.38.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49a72494..d485f9cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,7 +55,7 @@ importers: version: 1.1.3 '@vercel/analytics': specifier: ^1.2.2 - version: 1.2.2(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 1.2.2(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@vercel/blob': specifier: ^0.23.2 version: 0.23.2 @@ -67,7 +67,7 @@ importers: version: 0.8.0 '@vercel/speed-insights': specifier: ^1.0.10 - version: 1.0.10(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5)) + version: 1.0.10(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5)) ai: specifier: ^3.0.34 version: 3.0.34(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))(zod@3.23.4) @@ -108,11 +108,11 @@ importers: specifier: ^5.0.7 version: 5.0.7 next: - specifier: ^14.2.3 - version: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 14.3.0-canary.29 + version: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-auth: specifier: 5.0.0-beta.15 - version: 5.0.0-beta.15(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 5.0.0-beta.15(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -540,6 +540,9 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} + '@emnapi/runtime@1.1.1': + resolution: {integrity: sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ==} + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -588,6 +591,119 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + '@img/sharp-darwin-arm64@0.33.3': + resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.3': + resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.2': + resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} + engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.2': + resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} + engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.2': + resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.2': + resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.2': + resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.2': + resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.3': + resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.3': + resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.3': + resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.3': + resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.3': + resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.3': + resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.3': + resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.3': + resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.3': + resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [win32] + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -690,62 +806,62 @@ packages: '@next/bundle-analyzer@14.2.3': resolution: {integrity: sha512-Z88hbbngMs7njZKI8kTJIlpdLKYfMSLwnsqYe54AP4aLmgL70/Ynx/J201DQ+q2Lr6FxFw1uCeLGImDrHOl2ZA==} - '@next/env@14.2.3': - resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} + '@next/env@14.3.0-canary.29': + resolution: {integrity: sha512-h5It2nnx97Y+VjVIEP+gLrQ/byTN34bAtHhdQui1fkdlsaBD/B7sjt6BITSJK4zk1IPztdoPHHaI8sMONVbeeg==} '@next/eslint-plugin-next@14.2.3': resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} - '@next/swc-darwin-arm64@14.2.3': - resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} + '@next/swc-darwin-arm64@14.3.0-canary.29': + resolution: {integrity: sha512-ePqJ/d/7dYgdf+7YefmAdW08m5jysGw6PtB309fZbpm0BIUTLfSdShJKG+t6Ivft2jzYIwcfp3LoFHotG8XZTg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@14.2.3': - resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==} + '@next/swc-darwin-x64@14.3.0-canary.29': + resolution: {integrity: sha512-H/Ese4aLROI3V65DpzKDUUEPtyQir+oNAdrZM1PPFPTRDRMpHz2LvbdcsxQ/aeIkYfRAc+foj5unnFjpIdyFIg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@14.2.3': - resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==} + '@next/swc-linux-arm64-gnu@14.3.0-canary.29': + resolution: {integrity: sha512-hW1DOdQAw4oOV6rAwBZh4R1i24xYwjoXgAKHbz5BlVq9QFEW5Zku0srzSl4eDPG2VEgZWcFCkmMamqR+gZheJA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@14.2.3': - resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} + '@next/swc-linux-arm64-musl@14.3.0-canary.29': + resolution: {integrity: sha512-tn2OT3NUyd/B2q5jnwtbM2pta/r+eizQFgM8ZMxhGHsl0Md3qmCE8TqR6PjiTTipcrG7KP7qElxwWkyYiEGYIg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@14.2.3': - resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} + '@next/swc-linux-x64-gnu@14.3.0-canary.29': + resolution: {integrity: sha512-S2EfPr1qbU2y/+dJPdnr3aJIOxS0vsYz+VDAccUdbmXhzM3RSdsaE0okZWztih8AmKiiCS69MFWo6hUKnlOL4A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@14.2.3': - resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} + '@next/swc-linux-x64-musl@14.3.0-canary.29': + resolution: {integrity: sha512-DfTjNpx1Szk82LEHRq1u57tSjGBrg3+kgIfM5/O0OUdU+6ESEOdaLlf7YrD1gIu3k4lDfn37b4S7R/BmPme0tg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@14.2.3': - resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} + '@next/swc-win32-arm64-msvc@14.3.0-canary.29': + resolution: {integrity: sha512-C9Igll3rnPoRFgUUFCJMOQkmAFEDiQnVPO2tfxRyleXQP9jpSYY55PYpHGFOp6L0iNy8zc/PuznmR3pcS3E2fQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@14.2.3': - resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==} + '@next/swc-win32-ia32-msvc@14.3.0-canary.29': + resolution: {integrity: sha512-5ItF8rCzPMFhG9mlcPl5YpccUyhj3G5ElkjacRJYnqok2GQVmXtu6Ot5+LEGT86TCpizzTx+NkkY/lBSu28RRw==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@next/swc-win32-x64-msvc@14.2.3': - resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==} + '@next/swc-win32-x64-msvc@14.3.0-canary.29': + resolution: {integrity: sha512-Bjd22hlcK4Kf4/jqPz6GyRiZ+h2Oa/h64RnZFrAvFJJfpBBMIQlihYLoS6HRwdS+bAXPrlf6cOz4TLVdFnum4w==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1245,11 +1361,8 @@ packages: resolution: {integrity: sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA==} engines: {node: '>=14.0.0'} - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/helpers@0.5.5': - resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + '@swc/helpers@0.5.11': + resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} '@tailwindcss/container-queries@0.1.1': resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==} @@ -1907,6 +2020,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2042,6 +2162,10 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -2579,6 +2703,9 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -3133,8 +3260,8 @@ packages: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 - next@14.2.3: - resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} + next@14.3.0-canary.29: + resolution: {integrity: sha512-+4mx9dCIVBcW5jMs67jQ2ZCnb3VQ6AQPNBW6t8j17T+9Mp+h0c1XLzrCbfRETpDfdE0nfID2ilUYpQY/8oairg==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -3630,6 +3757,10 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + sharp@0.33.3: + resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} + engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -3649,6 +3780,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} @@ -4939,6 +5073,11 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} + '@emnapi/runtime@1.1.1': + dependencies: + tslib: 2.6.2 + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -4993,6 +5132,81 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@img/sharp-darwin-arm64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.2 + optional: true + + '@img/sharp-darwin-x64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.2 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.2': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.2': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + optional: true + + '@img/sharp-linux-arm64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.2 + optional: true + + '@img/sharp-linux-arm@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.2 + optional: true + + '@img/sharp-linux-s390x@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.2 + optional: true + + '@img/sharp-linux-x64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.2 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + optional: true + + '@img/sharp-wasm32@0.33.3': + dependencies: + '@emnapi/runtime': 1.1.1 + optional: true + + '@img/sharp-win32-ia32@0.33.3': + optional: true + + '@img/sharp-win32-x64@0.33.3': + optional: true + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -5202,37 +5416,37 @@ snapshots: - bufferutil - utf-8-validate - '@next/env@14.2.3': {} + '@next/env@14.3.0-canary.29': {} '@next/eslint-plugin-next@14.2.3': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@14.2.3': + '@next/swc-darwin-arm64@14.3.0-canary.29': optional: true - '@next/swc-darwin-x64@14.2.3': + '@next/swc-darwin-x64@14.3.0-canary.29': optional: true - '@next/swc-linux-arm64-gnu@14.2.3': + '@next/swc-linux-arm64-gnu@14.3.0-canary.29': optional: true - '@next/swc-linux-arm64-musl@14.2.3': + '@next/swc-linux-arm64-musl@14.3.0-canary.29': optional: true - '@next/swc-linux-x64-gnu@14.2.3': + '@next/swc-linux-x64-gnu@14.3.0-canary.29': optional: true - '@next/swc-linux-x64-musl@14.2.3': + '@next/swc-linux-x64-musl@14.3.0-canary.29': optional: true - '@next/swc-win32-arm64-msvc@14.2.3': + '@next/swc-win32-arm64-msvc@14.3.0-canary.29': optional: true - '@next/swc-win32-ia32-msvc@14.2.3': + '@next/swc-win32-ia32-msvc@14.3.0-canary.29': optional: true - '@next/swc-win32-x64-msvc@14.2.3': + '@next/swc-win32-x64-msvc@14.3.0-canary.29': optional: true '@nodelib/fs.scandir@2.1.5': @@ -5861,11 +6075,8 @@ snapshots: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@swc/counter@0.1.3': {} - - '@swc/helpers@0.5.5': + '@swc/helpers@0.5.11': dependencies: - '@swc/counter': 0.1.3 tslib: 2.6.2 '@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.3)': @@ -6157,11 +6368,11 @@ snapshots: dependencies: crypto-js: 4.2.0 - '@vercel/analytics@1.2.2(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@vercel/analytics@1.2.2(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: server-only: 0.0.1 optionalDependencies: - next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 '@vercel/blob@0.23.2': @@ -6182,9 +6393,9 @@ snapshots: utf-8-validate: 6.0.3 ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3) - '@vercel/speed-insights@1.0.10(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))': + '@vercel/speed-insights@1.0.10(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))': optionalDependencies: - next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 svelte: 4.2.15 vue: 3.4.25(typescript@5.4.5) @@ -6650,6 +6861,18 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + optional: true + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + optional: true + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -6768,6 +6991,9 @@ snapshots: dequal@2.0.3: {} + detect-libc@2.0.3: + optional: true + detect-newline@3.1.0: {} detect-node-es@1.1.0: {} @@ -7456,6 +7682,9 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: + optional: true + is-async-function@2.0.0: dependencies: has-tostringtag: 1.0.2 @@ -8152,10 +8381,10 @@ snapshots: natural-compare@1.4.0: {} - next-auth@5.0.0-beta.15(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + next-auth@5.0.0-beta.15(next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@auth/core': 0.28.0 - next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -8163,10 +8392,10 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.3.0-canary.29(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 14.2.3 - '@swc/helpers': 0.5.5 + '@next/env': 14.3.0-canary.29 + '@swc/helpers': 0.5.11 busboy: 1.6.0 caniuse-lite: 1.0.30001612 graceful-fs: 4.2.11 @@ -8175,15 +8404,16 @@ snapshots: react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.1(@babel/core@7.24.4)(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 14.2.3 - '@next/swc-darwin-x64': 14.2.3 - '@next/swc-linux-arm64-gnu': 14.2.3 - '@next/swc-linux-arm64-musl': 14.2.3 - '@next/swc-linux-x64-gnu': 14.2.3 - '@next/swc-linux-x64-musl': 14.2.3 - '@next/swc-win32-arm64-msvc': 14.2.3 - '@next/swc-win32-ia32-msvc': 14.2.3 - '@next/swc-win32-x64-msvc': 14.2.3 + '@next/swc-darwin-arm64': 14.3.0-canary.29 + '@next/swc-darwin-x64': 14.3.0-canary.29 + '@next/swc-linux-arm64-gnu': 14.3.0-canary.29 + '@next/swc-linux-arm64-musl': 14.3.0-canary.29 + '@next/swc-linux-x64-gnu': 14.3.0-canary.29 + '@next/swc-linux-x64-musl': 14.3.0-canary.29 + '@next/swc-win32-arm64-msvc': 14.3.0-canary.29 + '@next/swc-win32-ia32-msvc': 14.3.0-canary.29 + '@next/swc-win32-x64-msvc': 14.3.0-canary.29 + sharp: 0.33.3 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -8646,6 +8876,33 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + sharp@0.33.3: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.0 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.3 + '@img/sharp-darwin-x64': 0.33.3 + '@img/sharp-libvips-darwin-arm64': 1.0.2 + '@img/sharp-libvips-darwin-x64': 1.0.2 + '@img/sharp-libvips-linux-arm': 1.0.2 + '@img/sharp-libvips-linux-arm64': 1.0.2 + '@img/sharp-libvips-linux-s390x': 1.0.2 + '@img/sharp-libvips-linux-x64': 1.0.2 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + '@img/sharp-linux-arm': 0.33.3 + '@img/sharp-linux-arm64': 0.33.3 + '@img/sharp-linux-s390x': 0.33.3 + '@img/sharp-linux-x64': 0.33.3 + '@img/sharp-linuxmusl-arm64': 0.33.3 + '@img/sharp-linuxmusl-x64': 0.33.3 + '@img/sharp-wasm32': 0.33.3 + '@img/sharp-win32-ia32': 0.33.3 + '@img/sharp-win32-x64': 0.33.3 + optional: true + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -8663,6 +8920,11 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + optional: true + sirv@2.0.4: dependencies: '@polka/url': 1.0.0-next.25 diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 00000000..1ae6b757 --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1 @@ +export { default } from '@/components/PageSpinner'; diff --git a/src/app/p/[photoId]/layout.tsx b/src/app/p/[photoId]/layout.tsx index 4167b64c..a346eeab 100644 --- a/src/app/p/[photoId]/layout.tsx +++ b/src/app/p/[photoId]/layout.tsx @@ -1,4 +1,5 @@ import { + GENERATE_STATIC_PARAMS_LIMIT, GRID_THUMBNAILS_TO_SHOW_MAX, descriptionForPhoto, titleForPhoto, @@ -12,6 +13,18 @@ import { } from '@/site/paths'; import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotosNearIdCachedCached } from '@/photo/cache'; +import { STATICALLY_OPTIMIZED } from '@/site/config'; +import { getPhotoIds } from '@/services/vercel-postgres'; + +export let generateStaticParams: + (() => Promise<{ photoId: string }[]>) | undefined = undefined; + +if (STATICALLY_OPTIMIZED) { + generateStaticParams = async () => { + const photos = await getPhotoIds({ limit: GENERATE_STATIC_PARAMS_LIMIT }); + return photos.map(photoId => ({ photoId })); + }; +} interface PhotoProps { params: { photoId: string } diff --git a/src/photo/index.ts b/src/photo/index.ts index 2af0a08f..0c94abd5 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -13,6 +13,8 @@ import { import camelcaseKeys from 'camelcase-keys'; import type { Metadata } from 'next'; +export const GENERATE_STATIC_PARAMS_LIMIT = 1000; + // ROOT PAGE export const INFINITE_SCROLL_INITIAL_HOME = process.env.NODE_ENV === 'development' ? 2 : 12; diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index c5f876e5..fea161ea 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -39,6 +39,7 @@ export default function SiteChecklistClient({ showFilmSimulations, showExifInfo, isProModeEnabled, + isStaticallyOptimized, isBlurEnabled, isGeoPrivacyEnabled, isPriorityOrderEnabled, @@ -333,6 +334,17 @@ export default function SiteChecklistClient({ higher quality image storage: {renderEnvVars(['NEXT_PUBLIC_PRO_MODE'])} + + Set environment variable to {'"1"'} to enable PPR + and static optimization, i.e., build pages ahead of time: + {renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE'])} + Date: Mon, 29 Apr 2024 10:55:02 -0500 Subject: [PATCH 2/8] Force public API to be dynamic --- src/app/api/route.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/api/route.ts b/src/app/api/route.ts index 19484bd4..a3c74dc5 100644 --- a/src/app/api/route.ts +++ b/src/app/api/route.ts @@ -6,6 +6,8 @@ import { SITE_TITLE, } from '@/site/config'; +export const dynamic = 'force-dynamic'; + export async function GET() { if (PUBLIC_API_ENABLED) { const photos = await getPhotosCached({ limit: API_PHOTO_REQUEST_LIMIT }); From 3570e10e9fe842799d0964a69b22052c50e82be3 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Mon, 29 Apr 2024 14:33:47 -0500 Subject: [PATCH 3/8] Statically generate og images --- src/app/p/[photoId]/image/route.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/app/p/[photoId]/image/route.tsx b/src/app/p/[photoId]/image/route.tsx index 965db7df..63ca0ff6 100644 --- a/src/app/p/[photoId]/image/route.tsx +++ b/src/app/p/[photoId]/image/route.tsx @@ -4,6 +4,19 @@ import PhotoImageResponse from '@/image-response/PhotoImageResponse'; import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; +import { STATICALLY_OPTIMIZED } from '@/site/config'; +import { getPhotoIds } from '@/services/vercel-postgres'; +import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo'; + +export let generateStaticParams: + (() => Promise<{ photoId: string }[]>) | undefined = undefined; + +if (STATICALLY_OPTIMIZED) { + generateStaticParams = async () => { + const photos = await getPhotoIds({ limit: GENERATE_STATIC_PARAMS_LIMIT }); + return photos.map(photoId => ({ photoId })); + }; +} export async function GET( _: Request, From 9a35d2817f532d23bb5149e0d2d0552b031cfa14 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Fri, 3 May 2024 09:27:56 -0500 Subject: [PATCH 4/8] Fix vercel-postgres imports --- src/app/p/[photoId]/image/route.tsx | 2 +- src/app/p/[photoId]/layout.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/p/[photoId]/image/route.tsx b/src/app/p/[photoId]/image/route.tsx index 63ca0ff6..af686752 100644 --- a/src/app/p/[photoId]/image/route.tsx +++ b/src/app/p/[photoId]/image/route.tsx @@ -5,7 +5,7 @@ import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; import { STATICALLY_OPTIMIZED } from '@/site/config'; -import { getPhotoIds } from '@/services/vercel-postgres'; +import { getPhotoIds } from '@/photo/db'; import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo'; export let generateStaticParams: diff --git a/src/app/p/[photoId]/layout.tsx b/src/app/p/[photoId]/layout.tsx index a346eeab..de54ef41 100644 --- a/src/app/p/[photoId]/layout.tsx +++ b/src/app/p/[photoId]/layout.tsx @@ -14,7 +14,7 @@ import { import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotosNearIdCachedCached } from '@/photo/cache'; import { STATICALLY_OPTIMIZED } from '@/site/config'; -import { getPhotoIds } from '@/services/vercel-postgres'; +import { getPhotoIds } from '@/photo/db'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; From aeba8d02c54c5c97579b0702fd0c03239ed40452 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Wed, 8 May 2024 11:36:20 -0500 Subject: [PATCH 5/8] Separate PPR from static optimization --- README.md | 2 +- next.config.js | 10 --- package.json | 2 +- pnpm-lock.yaml | 123 +++++++++++++++------------- src/app/loading.tsx | 1 - src/app/p/[photoId]/image/route.tsx | 3 +- src/app/p/[photoId]/layout.tsx | 3 +- src/auth/cache.ts | 4 +- src/photo/db.ts | 4 +- src/photo/index.ts | 2 - src/services/storage/index.ts | 7 +- src/site/SiteChecklistClient.tsx | 4 +- src/utility/ppr.ts | 21 ----- 13 files changed, 76 insertions(+), 110 deletions(-) delete mode 100644 src/app/loading.tsx delete mode 100644 src/utility/ppr.ts diff --git a/README.md b/README.md index 857594d3..35fe9df4 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ _⚠️ READ BEFORE PROCEEDING_ Application behavior can be changed by configuring the following environment variables: - `NEXT_PUBLIC_PRO_MODE = 1` enables higher quality image storage (results in increased storage usage) -- `NEXT_PUBLIC_STATICALLY_OPTIMIZE = 1` enables PPR and static optimization, i.e., building pages ahead of time (results in increased storage usage)—⚠️ _Experimental_ +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE = 1` enables static optimization, i.e., renders pages and images at build time (results in increased project usage)—⚠️ _Experimental_ - `NEXT_PUBLIC_BLUR_DISABLED = 1` prevents image blur data being stored and displayed (potentially useful for limiting Postgres usage) - `NEXT_PUBLIC_GEO_PRIVACY = 1` disables collection/display of location-based data - `NEXT_PUBLIC_IGNORE_PRIORITY_ORDER = 1` prevents `priority_order` field affecting photo order diff --git a/next.config.js b/next.config.js index 4520e734..f0ff1b30 100644 --- a/next.config.js +++ b/next.config.js @@ -35,16 +35,6 @@ const nextConfig = { .concat(createRemotePattern(HOSTNAME_AWS_S3)), minimumCacheTTL: 31536000, }, - ...process.env.NEXT_PUBLIC_STATICALLY_OPTIMIZE === '1' && { - experimental: { ppr: true }, - }, - webpack: (config) => { - config.optimization ??= {}; - if (process.env.NODE_ENV !== 'production') { - config.optimization.minimize = false; - } - return config; - }, }; const withBundleAnalyzer = require('@next/bundle-analyzer')({ diff --git a/package.json b/package.json index 8a0d7541..36948280 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.7", - "next": "14.3.0-canary.44", + "next": "^14.2.3", "next-auth": "5.0.0-beta.15", "next-themes": "^0.3.0", "openai": "^4.38.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86345a66..60a7bd31 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,7 +58,7 @@ importers: version: 1.1.3 '@vercel/analytics': specifier: ^1.2.2 - version: 1.2.2(next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 1.2.2(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@vercel/blob': specifier: ^0.23.2 version: 0.23.2 @@ -67,7 +67,7 @@ importers: version: 1.0.1 '@vercel/speed-insights': specifier: ^1.0.10 - version: 1.0.10(next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5)) + version: 1.0.10(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5)) ai: specifier: ^3.0.34 version: 3.0.34(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))(zod@3.23.4) @@ -108,11 +108,11 @@ importers: specifier: ^5.0.7 version: 5.0.7 next: - specifier: 14.3.0-canary.44 - version: 14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^14.2.3 + version: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-auth: specifier: 5.0.0-beta.15 - version: 5.0.0-beta.15(next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 5.0.0-beta.15(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -809,62 +809,62 @@ packages: '@next/bundle-analyzer@14.2.3': resolution: {integrity: sha512-Z88hbbngMs7njZKI8kTJIlpdLKYfMSLwnsqYe54AP4aLmgL70/Ynx/J201DQ+q2Lr6FxFw1uCeLGImDrHOl2ZA==} - '@next/env@14.3.0-canary.44': - resolution: {integrity: sha512-n7E0UKB5tAcEEVO9iLuWVdx5nf+39GEHBo4mrRrC9zqXdP9Jxve4nFWFeDTU5EBSzuH3Zy4DmoVNHUOspHLmyQ==} + '@next/env@14.2.3': + resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} '@next/eslint-plugin-next@14.2.3': resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} - '@next/swc-darwin-arm64@14.3.0-canary.44': - resolution: {integrity: sha512-gooP4KXsw3DDZAlvjEJNyQsSacwPRJJ5f5wkrws1J17L/heUgZHX6G7vHnQgkAejyvfa5BhW2c9rlcPxOHNQqw==} + '@next/swc-darwin-arm64@14.2.3': + resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@14.3.0-canary.44': - resolution: {integrity: sha512-NbtsRFYzs8sU2VCMzqGjb4tdzhkQt1KcMB/ZqnHX5pPw5xtXqPXzBGLM0z3wHr5/vWlL4V22j8E7AGchE2TeXg==} + '@next/swc-darwin-x64@14.2.3': + resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@14.3.0-canary.44': - resolution: {integrity: sha512-ctGyGeHy/07TH82ZYuA74Xy0t8Zcq1xrMLTI9RUA8Dh4khf37RI7r9SHzAeqKmPGZJAPRyE6pwXtAlCg/TstjA==} + '@next/swc-linux-arm64-gnu@14.2.3': + resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@14.3.0-canary.44': - resolution: {integrity: sha512-cX/jD3EnhIphZwRBureGSPV4GlQ7ueUKmne+5N2BsO6tHih0cnveyssropX1dTupU7aGti+22kPorPDY7BYNfQ==} + '@next/swc-linux-arm64-musl@14.2.3': + resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@14.3.0-canary.44': - resolution: {integrity: sha512-2HPcwOxXBQj3WD5ezz78o/SJXXz9D4U5H7Mc4e0cTUMy/GGW4ysg2Ullwus+FVOmm2z8GAcNbEeqh71D/lAtww==} + '@next/swc-linux-x64-gnu@14.2.3': + resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@14.3.0-canary.44': - resolution: {integrity: sha512-UV9HUQenKZkrqbhRsB59X5KrMKaPUnXkbZmwLkjD2IieUgm5CswfXJ2+7JneopviwaR3k8eJMA2KV9uyA/3LpQ==} + '@next/swc-linux-x64-musl@14.2.3': + resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@14.3.0-canary.44': - resolution: {integrity: sha512-Swrl7I7q4sw7iS6O2j5v/c5bLgHP+i4/z79XTzU2LDubMP7gL3eUqLhN1GAOO35q/j49Ysbsr3VUM14JCtGOkg==} + '@next/swc-win32-arm64-msvc@14.2.3': + resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@14.3.0-canary.44': - resolution: {integrity: sha512-3KKbNG6EDMpAY9PP/Bv32ildjljC9vUwRbLrhBLa6l3TkD6n8xtlObNf9DMD0Fsa79VKHZKIkY1EvCn/7xlj5A==} + '@next/swc-win32-ia32-msvc@14.2.3': + resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@next/swc-win32-x64-msvc@14.3.0-canary.44': - resolution: {integrity: sha512-pDD9g/tTI/ihOP4c8wy5E0dRz8QUy2/7uAVyW11MIkroA4A4/cWa58PQNW5ByhvySPTcf9trnlaVPa2mdxBMMA==} + '@next/swc-win32-x64-msvc@14.2.3': + resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1364,8 +1364,11 @@ packages: resolution: {integrity: sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA==} engines: {node: '>=14.0.0'} - '@swc/helpers@0.5.11': - resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.5': + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} '@tailwindcss/container-queries@0.1.1': resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==} @@ -3259,8 +3262,8 @@ packages: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 - next@14.3.0-canary.44: - resolution: {integrity: sha512-iYJmuiARcldXjN27N0Yo8gWyy6vWl+FoUNcEaL2GGh3sA/rc4hcbZD89ZUXoVFsPAI7ze6sKM60Znct9RwCbKQ==} + next@14.2.3: + resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -5452,37 +5455,37 @@ snapshots: - bufferutil - utf-8-validate - '@next/env@14.3.0-canary.44': {} + '@next/env@14.2.3': {} '@next/eslint-plugin-next@14.2.3': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@14.3.0-canary.44': + '@next/swc-darwin-arm64@14.2.3': optional: true - '@next/swc-darwin-x64@14.3.0-canary.44': + '@next/swc-darwin-x64@14.2.3': optional: true - '@next/swc-linux-arm64-gnu@14.3.0-canary.44': + '@next/swc-linux-arm64-gnu@14.2.3': optional: true - '@next/swc-linux-arm64-musl@14.3.0-canary.44': + '@next/swc-linux-arm64-musl@14.2.3': optional: true - '@next/swc-linux-x64-gnu@14.3.0-canary.44': + '@next/swc-linux-x64-gnu@14.2.3': optional: true - '@next/swc-linux-x64-musl@14.3.0-canary.44': + '@next/swc-linux-x64-musl@14.2.3': optional: true - '@next/swc-win32-arm64-msvc@14.3.0-canary.44': + '@next/swc-win32-arm64-msvc@14.2.3': optional: true - '@next/swc-win32-ia32-msvc@14.3.0-canary.44': + '@next/swc-win32-ia32-msvc@14.2.3': optional: true - '@next/swc-win32-x64-msvc@14.3.0-canary.44': + '@next/swc-win32-x64-msvc@14.2.3': optional: true '@nodelib/fs.scandir@2.1.5': @@ -6111,8 +6114,11 @@ snapshots: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@swc/helpers@0.5.11': + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.5': dependencies: + '@swc/counter': 0.1.3 tslib: 2.6.2 '@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.3)': @@ -6404,11 +6410,11 @@ snapshots: dependencies: crypto-js: 4.2.0 - '@vercel/analytics@1.2.2(next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@vercel/analytics@1.2.2(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: server-only: 0.0.1 optionalDependencies: - next: 14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 '@vercel/blob@0.23.2': @@ -6422,9 +6428,9 @@ snapshots: dependencies: '@upstash/redis': 1.25.1 - '@vercel/speed-insights@1.0.10(next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))': + '@vercel/speed-insights@1.0.10(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.15)(vue@3.4.25(typescript@5.4.5))': optionalDependencies: - next: 14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 svelte: 4.2.15 vue: 3.4.25(typescript@5.4.5) @@ -8407,10 +8413,10 @@ snapshots: natural-compare@1.4.0: {} - next-auth@5.0.0-beta.15(next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + next-auth@5.0.0-beta.15(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@auth/core': 0.28.0 - next: 14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -8418,10 +8424,10 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.3.0-canary.44(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 14.3.0-canary.44 - '@swc/helpers': 0.5.11 + '@next/env': 14.2.3 + '@swc/helpers': 0.5.5 busboy: 1.6.0 caniuse-lite: 1.0.30001612 graceful-fs: 4.2.11 @@ -8430,16 +8436,15 @@ snapshots: react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.1(@babel/core@7.24.4)(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 14.3.0-canary.44 - '@next/swc-darwin-x64': 14.3.0-canary.44 - '@next/swc-linux-arm64-gnu': 14.3.0-canary.44 - '@next/swc-linux-arm64-musl': 14.3.0-canary.44 - '@next/swc-linux-x64-gnu': 14.3.0-canary.44 - '@next/swc-linux-x64-musl': 14.3.0-canary.44 - '@next/swc-win32-arm64-msvc': 14.3.0-canary.44 - '@next/swc-win32-ia32-msvc': 14.3.0-canary.44 - '@next/swc-win32-x64-msvc': 14.3.0-canary.44 - sharp: 0.33.3 + '@next/swc-darwin-arm64': 14.2.3 + '@next/swc-darwin-x64': 14.2.3 + '@next/swc-linux-arm64-gnu': 14.2.3 + '@next/swc-linux-arm64-musl': 14.2.3 + '@next/swc-linux-x64-gnu': 14.2.3 + '@next/swc-linux-x64-musl': 14.2.3 + '@next/swc-win32-arm64-msvc': 14.2.3 + '@next/swc-win32-ia32-msvc': 14.2.3 + '@next/swc-win32-x64-msvc': 14.2.3 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros diff --git a/src/app/loading.tsx b/src/app/loading.tsx deleted file mode 100644 index 1ae6b757..00000000 --- a/src/app/loading.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@/components/PageSpinner'; diff --git a/src/app/p/[photoId]/image/route.tsx b/src/app/p/[photoId]/image/route.tsx index af686752..2e87c567 100644 --- a/src/app/p/[photoId]/image/route.tsx +++ b/src/app/p/[photoId]/image/route.tsx @@ -5,8 +5,7 @@ import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; import { STATICALLY_OPTIMIZED } from '@/site/config'; -import { getPhotoIds } from '@/photo/db'; -import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo'; +import { GENERATE_STATIC_PARAMS_LIMIT, getPhotoIds } from '@/photo/db'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; diff --git a/src/app/p/[photoId]/layout.tsx b/src/app/p/[photoId]/layout.tsx index de54ef41..e4c0c630 100644 --- a/src/app/p/[photoId]/layout.tsx +++ b/src/app/p/[photoId]/layout.tsx @@ -1,5 +1,4 @@ import { - GENERATE_STATIC_PARAMS_LIMIT, GRID_THUMBNAILS_TO_SHOW_MAX, descriptionForPhoto, titleForPhoto, @@ -14,7 +13,7 @@ import { import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotosNearIdCachedCached } from '@/photo/cache'; import { STATICALLY_OPTIMIZED } from '@/site/config'; -import { getPhotoIds } from '@/photo/db'; +import { GENERATE_STATIC_PARAMS_LIMIT, getPhotoIds } from '@/photo/db'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; diff --git a/src/auth/cache.ts b/src/auth/cache.ts index 84ac9f5d..e1079046 100644 --- a/src/auth/cache.ts +++ b/src/auth/cache.ts @@ -1,6 +1,4 @@ import { cache } from 'react'; import { auth } from '@/auth'; -import { screenForPPR } from '@/utility/ppr'; -export const authCachedSafe = cache(() => auth() - .catch(e => screenForPPR(e, null, 'auth'))); +export const authCachedSafe = cache(() => auth().catch(() => null)); diff --git a/src/photo/db.ts b/src/photo/db.ts index 49e4ffb4..7bca89f7 100644 --- a/src/photo/db.ts +++ b/src/photo/db.ts @@ -16,7 +16,8 @@ import { parameterize } from '@/utility/string'; import { TagsWithMeta } from '@/tag'; import { FilmSimulation, FilmSimulations } from '@/simulation'; import { SHOULD_DEBUG_SQL, PRIORITY_ORDER_ENABLED } from '@/site/config'; -import { screenForPPR } from '@/utility/ppr'; + +export const GENERATE_STATIC_PARAMS_LIMIT = 1000; const PHOTO_DEFAULT_LIMIT = 100; @@ -310,7 +311,6 @@ const safelyQueryPhotos = async ( try { result = await callback(); } catch (e: any) { - screenForPPR(e, undefined, 'neon postgres'); if (MIGRATION_FIELDS_01.some(field => new RegExp( `column "${field}" of relation "photos" does not exist`, 'i', diff --git a/src/photo/index.ts b/src/photo/index.ts index 122b5b63..903fb8bd 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -14,8 +14,6 @@ import camelcaseKeys from 'camelcase-keys'; import { isBefore } from 'date-fns'; import type { Metadata } from 'next'; -export const GENERATE_STATIC_PARAMS_LIMIT = 1000; - // ROOT PAGE export const INFINITE_SCROLL_INITIAL_HOME = process.env.NODE_ENV === 'development' ? 2 : 12; diff --git a/src/services/storage/index.ts b/src/services/storage/index.ts index 2a37576c..0f3e008e 100644 --- a/src/services/storage/index.ts +++ b/src/services/storage/index.ts @@ -27,7 +27,6 @@ import { isUrlFromCloudflareR2, } from './cloudflare-r2'; import { PATH_API_PRESIGNED_URL } from '@/site/paths'; -import { screenForPPR } from '@/utility/ppr'; export const generateStorageId = () => generateNanoid(16); @@ -193,15 +192,15 @@ const getStorageUrlsForPrefix = async (prefix = '') => { if (HAS_VERCEL_BLOB_STORAGE) { urls.push(...await vercelBlobList(prefix) - .catch(e => screenForPPR(e, [], 'vercel blob'))); + .catch(() => [])); } if (HAS_AWS_S3_STORAGE) { urls.push(...await awsS3List(prefix) - .catch(e => screenForPPR(e, [], 'aws blob'))); + .catch(() => [])); } if (HAS_CLOUDFLARE_R2_STORAGE) { urls.push(...await cloudflareR2List(prefix) - .catch(e => screenForPPR(e, [], 'cloudflare blob'))); + .catch(() => [])); } return urls diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index 7e6ea602..5201a3fc 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -358,8 +358,8 @@ export default function SiteChecklistClient({ optional experimental > - Set environment variable to {'"1"'} to enable PPR - and static optimization, i.e., build pages ahead of time: + Set environment variable to {'"1"'} to enable static optimization, + i.e., rendering pages and images at build time: {renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE'])} ( - error: any, - fallback: T, - sourceToLog?: string, - debug?: boolean -): T => { - // PPR errors, if caught, must be re-thrown in order to - // postpone rendering - if (error.sourceError?.message?.includes('ppr-caught-error')) { - if (debug) { - console.log(`${sourceToLog}: throwing error.sourceError`); - } - throw error.sourceError; - } else if (error.message?.includes('ppr-caught-error')) { - if (debug) { - console.log(`${sourceToLog}: throwing error`); - } - throw error; - } - return fallback; -}; From 1763d7c0639e3ca9f249ce971692c4ccd38d97f1 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Wed, 8 May 2024 11:37:39 -0500 Subject: [PATCH 6/8] Disable SQL logging --- src/site/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/config.ts b/src/site/config.ts index b1d3da1f..2f426de5 100644 --- a/src/site/config.ts +++ b/src/site/config.ts @@ -5,7 +5,7 @@ import { makeUrlAbsolute, shortenUrl } from '@/utility/url'; // HARD-CODED GLOBAL CONFIGURATION export const SHOULD_PREFETCH_ALL_LINKS: boolean | undefined = undefined; -export const SHOULD_DEBUG_SQL = true; +export const SHOULD_DEBUG_SQL = false; // META / DOMAINS From 583df5698e2a6a0a8678faa6ef2b39b8d0d18bdc Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Wed, 8 May 2024 11:47:20 -0500 Subject: [PATCH 7/8] Make og image access resilient on first deploy --- src/app/p/[photoId]/image/route.tsx | 13 ++++++++++++- src/image-response/PhotoImageResponse.tsx | 4 +++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/app/p/[photoId]/image/route.tsx b/src/app/p/[photoId]/image/route.tsx index 2e87c567..ac9a761d 100644 --- a/src/app/p/[photoId]/image/route.tsx +++ b/src/app/p/[photoId]/image/route.tsx @@ -6,6 +6,7 @@ import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; import { STATICALLY_OPTIMIZED } from '@/site/config'; import { GENERATE_STATIC_PARAMS_LIMIT, getPhotoIds } from '@/photo/db'; +import { isNextImageReadyBasedOnPhotos } from '@/photo'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; @@ -34,9 +35,19 @@ export async function GET( if (!photo) { return new Response('Photo not found', { status: 404 }); } const { width, height } = IMAGE_OG_DIMENSION; + + // Make sure next/image can be reached from absolute urls, + // which may not exist on first pre-render + const isNextImageReady = await isNextImageReadyBasedOnPhotos([photo]); return new ImageResponse( - , + , { width, height, fonts, headers }, ); } diff --git a/src/image-response/PhotoImageResponse.tsx b/src/image-response/PhotoImageResponse.tsx index f633e513..2175add2 100644 --- a/src/image-response/PhotoImageResponse.tsx +++ b/src/image-response/PhotoImageResponse.tsx @@ -12,11 +12,13 @@ export default function PhotoImageResponse({ width, height, fontFamily, + isNextImageReady = true, }: { photo: Photo width: NextImageSize height: number fontFamily: string + isNextImageReady: boolean }) { const model = photo.model ? formatCameraModelTextShort(cameraFromPhoto(photo)) @@ -25,7 +27,7 @@ export default function PhotoImageResponse({ return ( Date: Wed, 8 May 2024 12:29:57 -0500 Subject: [PATCH 8/8] Split static optimization config into pages + images --- README.md | 3 ++- src/app/p/[photoId]/image/route.tsx | 4 ++-- src/app/p/[photoId]/layout.tsx | 4 ++-- src/components/ExperimentalBadge.tsx | 1 + src/site/SiteChecklistClient.tsx | 23 +++++++++++++++++++---- src/site/config.ts | 18 +++++++++++++----- 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 35fe9df4..c11b56ca 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,8 @@ _⚠️ READ BEFORE PROCEEDING_ Application behavior can be changed by configuring the following environment variables: - `NEXT_PUBLIC_PRO_MODE = 1` enables higher quality image storage (results in increased storage usage) -- `NEXT_PUBLIC_STATICALLY_OPTIMIZE = 1` enables static optimization, i.e., renders pages and images at build time (results in increased project usage)—⚠️ _Experimental_ +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES = 1` enables static optimization for pages, i.e., renders pages at build time (results in increased project usage)—⚠️ _Experimental_ +- `NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES = 1` enables static optimization for OG images, i.e., renders images at build time (results in increased project usage)—⚠️ _Experimental_ - `NEXT_PUBLIC_BLUR_DISABLED = 1` prevents image blur data being stored and displayed (potentially useful for limiting Postgres usage) - `NEXT_PUBLIC_GEO_PRIVACY = 1` disables collection/display of location-based data - `NEXT_PUBLIC_IGNORE_PRIORITY_ORDER = 1` prevents `priority_order` field affecting photo order diff --git a/src/app/p/[photoId]/image/route.tsx b/src/app/p/[photoId]/image/route.tsx index ac9a761d..9ff57e29 100644 --- a/src/app/p/[photoId]/image/route.tsx +++ b/src/app/p/[photoId]/image/route.tsx @@ -4,14 +4,14 @@ import PhotoImageResponse from '@/image-response/PhotoImageResponse'; import { getIBMPlexMonoMedium } from '@/site/font'; import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; -import { STATICALLY_OPTIMIZED } from '@/site/config'; +import { STATICALLY_OPTIMIZED_OG_IMAGES } from '@/site/config'; import { GENERATE_STATIC_PARAMS_LIMIT, getPhotoIds } from '@/photo/db'; import { isNextImageReadyBasedOnPhotos } from '@/photo'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; -if (STATICALLY_OPTIMIZED) { +if (STATICALLY_OPTIMIZED_OG_IMAGES) { generateStaticParams = async () => { const photos = await getPhotoIds({ limit: GENERATE_STATIC_PARAMS_LIMIT }); return photos.map(photoId => ({ photoId })); diff --git a/src/app/p/[photoId]/layout.tsx b/src/app/p/[photoId]/layout.tsx index e4c0c630..20380d6e 100644 --- a/src/app/p/[photoId]/layout.tsx +++ b/src/app/p/[photoId]/layout.tsx @@ -12,13 +12,13 @@ import { } from '@/site/paths'; import PhotoDetailPage from '@/photo/PhotoDetailPage'; import { getPhotosNearIdCachedCached } from '@/photo/cache'; -import { STATICALLY_OPTIMIZED } from '@/site/config'; +import { STATICALLY_OPTIMIZED_PAGES } from '@/site/config'; import { GENERATE_STATIC_PARAMS_LIMIT, getPhotoIds } from '@/photo/db'; export let generateStaticParams: (() => Promise<{ photoId: string }[]>) | undefined = undefined; -if (STATICALLY_OPTIMIZED) { +if (STATICALLY_OPTIMIZED_PAGES) { generateStaticParams = async () => { const photos = await getPhotoIds({ limit: GENERATE_STATIC_PARAMS_LIMIT }); return photos.map(photoId => ({ photoId })); diff --git a/src/components/ExperimentalBadge.tsx b/src/components/ExperimentalBadge.tsx index 0e4b60d9..d3d51a0d 100644 --- a/src/components/ExperimentalBadge.tsx +++ b/src/components/ExperimentalBadge.tsx @@ -12,6 +12,7 @@ export default function ExperimentalBadge({ className={clsx( 'text-pink-500 dark:text-white', 'bg-pink-100 dark:bg-pink-600', + 'pt-0.5', className, )}> Experimental diff --git a/src/site/SiteChecklistClient.tsx b/src/site/SiteChecklistClient.tsx index 5201a3fc..546ce113 100644 --- a/src/site/SiteChecklistClient.tsx +++ b/src/site/SiteChecklistClient.tsx @@ -42,6 +42,8 @@ export default function SiteChecklistClient({ showExifInfo, isProModeEnabled, isStaticallyOptimized, + arePagesStaticallyOptimized, + areOGImagesStaticallyOptimized, isBlurEnabled, isGeoPrivacyEnabled, isPriorityOrderEnabled, @@ -120,7 +122,8 @@ export default function SiteChecklistClient({ > @@ -138,10 +141,13 @@ export default function SiteChecklistClient({ const renderSubStatus = ( type: ComponentProps['type'], label: ReactNode, + iconClassName?: string, ) =>
- - + + + + {label}
; @@ -360,7 +366,16 @@ export default function SiteChecklistClient({ > Set environment variable to {'"1"'} to enable static optimization, i.e., rendering pages and images at build time: - {renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE'])} + {renderSubStatus( + arePagesStaticallyOptimized ? 'checked' : 'optional', + renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE_PAGES']), + 'translate-y-[4.5px]', + )} + {renderSubStatus( + areOGImagesStaticallyOptimized ? 'checked' : 'optional', + renderEnvVars(['NEXT_PUBLIC_STATICALLY_OPTIMIZE_OG_IMAGES']), + 'translate-y-[4.5px]', + )}
0, @@ -162,7 +165,12 @@ export const CONFIG_CHECKLIST_STATUS = { showFilmSimulations: SHOW_FILM_SIMULATIONS, showExifInfo: SHOW_EXIF_DATA, isProModeEnabled: PRO_MODE_ENABLED, - isStaticallyOptimized: STATICALLY_OPTIMIZED, + isStaticallyOptimized: ( + STATICALLY_OPTIMIZED_PAGES || + STATICALLY_OPTIMIZED_OG_IMAGES + ), + arePagesStaticallyOptimized: STATICALLY_OPTIMIZED_PAGES, + areOGImagesStaticallyOptimized: STATICALLY_OPTIMIZED_OG_IMAGES, isBlurEnabled: BLUR_ENABLED, isGeoPrivacyEnabled: GEO_PRIVACY_ENABLED, isAiTextGenerationEnabled: AI_TEXT_GENERATION_ENABLED,