From 419b9b1303d91fd2936eb753b814cc90cf67691f Mon Sep 17 00:00:00 2001 From: Mitchel C Date: Thu, 27 Jun 2024 14:24:49 -0400 Subject: [PATCH 1/7] bump to latest nextJS, remove output: export --- next.config.mjs | 2 +- package.json | 2 +- yarn.lock | 160 +++++++++++++++++++++++++++--------------------- 3 files changed, 93 insertions(+), 71 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index 49610a0..72e509b 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,6 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - output: "export", + // output: "export", /** assetPrefix: "/out", basePath: "/out", USE THIS WHEN BUILDING THE STATIC PAGE diff --git a/package.json b/package.json index 0cf4971..d20499e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "next": "14.1.4", + "next": "14.2.4", "react": "^18", "react-dom": "^18" }, diff --git a/yarn.lock b/yarn.lock index 6950aa8..cd7902b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -114,10 +114,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@next/env@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.4.tgz#432e80651733fbd67230bf262aee28be65252674" - integrity sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ== +"@next/env@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.4.tgz#5546813dc4f809884a37d257b254a5ce1b0248d7" + integrity sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg== "@next/eslint-plugin-next@14.1.4": version "14.1.4" @@ -126,50 +126,50 @@ dependencies: glob "10.3.10" -"@next/swc-darwin-arm64@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz#a3bca0dc4393ac4cf3169bbf24df63441de66bb7" - integrity sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg== - -"@next/swc-darwin-x64@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz#ba3683d4e2d30099f3f2864dd7349a4d9f440140" - integrity sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ== - -"@next/swc-linux-arm64-gnu@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz#3519969293f16379954b7e196deb0c1eecbb2f8b" - integrity sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA== - -"@next/swc-linux-arm64-musl@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz#4bb3196bd402b3f84cf5373ff1021f547264d62f" - integrity sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g== - -"@next/swc-linux-x64-gnu@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz#1b3372c98c83dcdab946cdb4ee06e068b8139ba3" - integrity sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw== - -"@next/swc-linux-x64-musl@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.4.tgz#8459088bdc872648ff78f121db596f2533df5808" - integrity sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg== - -"@next/swc-win32-arm64-msvc@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz#84280a08c00cc3be24ddd3a12f4617b108e6dea6" - integrity sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag== - -"@next/swc-win32-ia32-msvc@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz#23ff7f4bd0a27177428669ef6fa5c3923c738031" - integrity sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw== - -"@next/swc-win32-x64-msvc@14.1.4": - version "14.1.4" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz#bccf5beccfde66d6c66fa4e2509118c796385eda" - integrity sha512-4Rto21sPfw555sZ/XNLqfxDUNeLhNYGO2dlPqsnuCg8N8a2a9u1ltqBOPQ4vj1Gf7eJC0W2hHG2eYUHuiXgY2w== +"@next/swc-darwin-arm64@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz#da9f04c34a3d5f0b8401ed745768420e4a604036" + integrity sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg== + +"@next/swc-darwin-x64@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz#46dedb29ec5503bf171a72a3ecb8aac6e738e9d6" + integrity sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg== + +"@next/swc-linux-arm64-gnu@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz#c9697ab9eb422bd1d7ffd0eb0779cc2aefa9d4a1" + integrity sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ== + +"@next/swc-linux-arm64-musl@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz#cbbceb2008571c743b5a310a488d2e166d200a75" + integrity sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A== + +"@next/swc-linux-x64-gnu@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz#d79184223f857bacffb92f643cb2943a43632568" + integrity sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q== + +"@next/swc-linux-x64-musl@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz#6b6c3e5ac02ca5e63394d280ec8ee607491902df" + integrity sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ== + +"@next/swc-win32-arm64-msvc@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz#dbad3906e870dba84c5883d9d4c4838472e0697f" + integrity sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A== + +"@next/swc-win32-ia32-msvc@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz#6074529b91ba49132922ce89a2e16d25d2ec235d" + integrity sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag== + +"@next/swc-win32-x64-msvc@14.2.4": + version "14.2.4" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz#e65a1c6539a671f97bb86d5183d6e3a1733c29c7" + integrity sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -207,11 +207,17 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.9.0.tgz#6a3b23e6702de1480557f75b7f450d1d0f496519" integrity sha512-AAWymnpvHbGty1BmgbdfbqQDboXs6xN6h2yAacO4yKVyyUUBnpYkp+P9jjPrV9zrAGw7JVVriRtGOHPInnfjZQ== -"@swc/helpers@0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d" - integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw== +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" + integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== dependencies: + "@swc/counter" "^0.1.3" tslib "^2.4.0" "@types/json5@^0.0.29": @@ -1845,28 +1851,28 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@14.1.4: - version "14.1.4" - resolved "https://registry.yarnpkg.com/next/-/next-14.1.4.tgz#203310f7310578563fd5c961f0db4729ce7a502d" - integrity sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ== +next@14.2.4: + version "14.2.4" + resolved "https://registry.yarnpkg.com/next/-/next-14.2.4.tgz#ef66c39c71e2d8ad0a3caa0383c8933f4663e4d1" + integrity sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ== dependencies: - "@next/env" "14.1.4" - "@swc/helpers" "0.5.2" + "@next/env" "14.2.4" + "@swc/helpers" "0.5.5" busboy "1.6.0" caniuse-lite "^1.0.30001579" graceful-fs "^4.2.11" postcss "8.4.31" styled-jsx "5.1.1" optionalDependencies: - "@next/swc-darwin-arm64" "14.1.4" - "@next/swc-darwin-x64" "14.1.4" - "@next/swc-linux-arm64-gnu" "14.1.4" - "@next/swc-linux-arm64-musl" "14.1.4" - "@next/swc-linux-x64-gnu" "14.1.4" - "@next/swc-linux-x64-musl" "14.1.4" - "@next/swc-win32-arm64-msvc" "14.1.4" - "@next/swc-win32-ia32-msvc" "14.1.4" - "@next/swc-win32-x64-msvc" "14.1.4" + "@next/swc-darwin-arm64" "14.2.4" + "@next/swc-darwin-x64" "14.2.4" + "@next/swc-linux-arm64-gnu" "14.2.4" + "@next/swc-linux-arm64-musl" "14.2.4" + "@next/swc-linux-x64-gnu" "14.2.4" + "@next/swc-linux-x64-musl" "14.2.4" + "@next/swc-win32-arm64-msvc" "14.2.4" + "@next/swc-win32-ia32-msvc" "14.2.4" + "@next/swc-win32-x64-msvc" "14.2.4" node-releases@^2.0.14: version "2.0.14" @@ -2371,7 +2377,16 @@ streamsearch@^1.1.0: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2435,7 +2450,14 @@ string.prototype.trimstart@^1.0.7: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== From 2130d3ce9cb36b4a033eeffdce29f26907661753 Mon Sep 17 00:00:00 2001 From: Mitchel C Date: Thu, 27 Jun 2024 14:36:13 -0400 Subject: [PATCH 2/7] Add top level not-found --- src/app/not-found.tsx | 14 ++++++++++++++ src/app/page.tsx | 8 ++++++-- src/app/posts/[postId]/page.tsx | 5 ++++- src/app/posts/page.tsx | 3 ++- 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/app/not-found.tsx diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..d981c2d --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +export const dynamic = "force-static"; + +export default async function NotFound() { + const todayDate = Date.now().toString(); + + return ( +
+ NotFound at top level! {todayDate} + Go back home. +
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index c1dbaf8..c037cf3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,12 +1,16 @@ import Link from "next/link"; export default function Home() { + const todayDate = Date.now().toString(); + return (
-

Hello World

+

+ Hello World {todayDate} +

- See posts + See posts {todayDate}
diff --git a/src/app/posts/[postId]/page.tsx b/src/app/posts/[postId]/page.tsx index b8a8c92..139f0c7 100644 --- a/src/app/posts/[postId]/page.tsx +++ b/src/app/posts/[postId]/page.tsx @@ -1,6 +1,8 @@ import type { Post } from "@/types/PostProps"; import Link from "next/link"; +export const dynamicParams = false; + export async function generateStaticParams() { const posts: Post[] = await fetch( "https://jsonplaceholder.typicode.com/posts", @@ -15,6 +17,7 @@ export default async function Post({ params }: { params: { postId: string } }) { const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${params.postId}`, ); + const todayDate = Date.now().toString(); const post: Post = await response.json(); @@ -25,7 +28,7 @@ export default async function Post({ params }: { params: { postId: string } }) {

{post.body}

- Go Back + Go Back {todayDate} ); diff --git a/src/app/posts/page.tsx b/src/app/posts/page.tsx index 1a381fd..259e985 100644 --- a/src/app/posts/page.tsx +++ b/src/app/posts/page.tsx @@ -5,6 +5,7 @@ export default async function PostPage() { const response = await fetch("https://jsonplaceholder.typicode.com/posts"); const posts: Post[] = await response.json(); + const todayDate = Date.now().toString(); return (
@@ -12,7 +13,7 @@ export default async function PostPage() {

Post Title

- Back to home + Back to home {todayDate}
From 237a136547ec655f14d5f0925cd30530c5b04164 Mon Sep 17 00:00:00 2001 From: Mitchel C Date: Thu, 27 Jun 2024 14:39:57 -0400 Subject: [PATCH 3/7] test --- src/app/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index c037cf3..eba95ad 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,7 +10,7 @@ export default function Home() { Hello World {todayDate} - See posts {todayDate} + See posts. {todayDate}
From 89b7c22ae13027a392f09a2d8e9f45eba5db7a1c Mon Sep 17 00:00:00 2001 From: Mitchel C Date: Thu, 27 Jun 2024 14:52:54 -0400 Subject: [PATCH 4/7] throw notFound for id 10 --- src/app/posts/[postId]/page.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/posts/[postId]/page.tsx b/src/app/posts/[postId]/page.tsx index 139f0c7..1d4bcfe 100644 --- a/src/app/posts/[postId]/page.tsx +++ b/src/app/posts/[postId]/page.tsx @@ -1,5 +1,6 @@ import type { Post } from "@/types/PostProps"; import Link from "next/link"; +import { notFound } from "next/navigation"; export const dynamicParams = false; @@ -14,6 +15,9 @@ export async function generateStaticParams() { } export default async function Post({ params }: { params: { postId: string } }) { + if (params.postId === "10") { + notFound(); + } const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${params.postId}`, ); From 341f3d3c7a36848ec177f7138f0e0edf37265ad7 Mon Sep 17 00:00:00 2001 From: Mitchel C Date: Mon, 1 Jul 2024 14:00:02 -0400 Subject: [PATCH 5/7] Add PPR example --- next.config.mjs | 3 + package.json | 6 +- src/app/home/page.tsx | 51 ++++ src/app/layout.tsx | 9 +- src/app/loading.tsx | 9 + src/app/not-found.tsx | 2 +- src/app/page.tsx | 2 +- src/app/posts/[postId]/layout.tsx | 29 +++ src/app/posts/[postId]/loading.tsx | 9 + src/app/posts/[postId]/page.tsx | 72 ++++-- src/app/posts/loading.tsx | 9 + src/app/posts/not-found.tsx | 14 ++ src/app/posts/page.tsx | 94 ++++++-- src/components/Home.tsx | 71 ++++++ src/components/PostItem.tsx | 27 +++ tsconfig.json | 24 +- yarn.lock | 373 +++++++++++++++++++++-------- 17 files changed, 654 insertions(+), 150 deletions(-) create mode 100644 src/app/home/page.tsx create mode 100644 src/app/loading.tsx create mode 100644 src/app/posts/[postId]/layout.tsx create mode 100644 src/app/posts/[postId]/loading.tsx create mode 100644 src/app/posts/loading.tsx create mode 100644 src/app/posts/not-found.tsx create mode 100644 src/components/Home.tsx create mode 100644 src/components/PostItem.tsx diff --git a/next.config.mjs b/next.config.mjs index 72e509b..ef27667 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,5 +1,8 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + experimental: { + ppr: "incremental", + }, // output: "export", /** assetPrefix: "/out", diff --git a/package.json b/package.json index d20499e..286bedf 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ "lint": "next lint" }, "dependencies": { - "next": "14.2.4", - "react": "^18", - "react-dom": "^18" + "next": "^15.0.0-canary.46", + "react": "19.0.0-rc-e02baf6c92-20240627", + "react-dom": "19.0.0-rc-e02baf6c92-20240627" }, "devDependencies": { "@types/node": "^20", diff --git a/src/app/home/page.tsx b/src/app/home/page.tsx new file mode 100644 index 0000000..1b0ab45 --- /dev/null +++ b/src/app/home/page.tsx @@ -0,0 +1,51 @@ +import Home from "@/components/Home"; +// import type { Post } from "@/types/PostProps"; +import Link from "next/link"; + +export default async function PostPage() { + // const response = await fetch("https://jsonplaceholder.typicode.com/posts"); + + // const posts: Post[] = await response.json(); + const todayDate = new Date().toLocaleString(); + + return ( +
+
+
+

Post Title

+ + Testing Home!!!!! {todayDate} + +
+
+
+ + {/* {posts.length > 0 ? ( +
+ {posts.map((post: any) => ( + +

+ {post.title} +

+

{post.body}

+ + ))} +
+ ) : ( +

No posts found.

+ )} */} +
+
+
+

+ © 2022 Your Website. All rights reserved. +

+
+
+
+ ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3314e47..1d1d7d4 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,9 +1,12 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; +import { Suspense } from "react"; const inter = Inter({ subsets: ["latin"] }); +export const experimental_ppr = true; + export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", @@ -16,7 +19,11 @@ export default function RootLayout({ }>) { return ( - {children} + + Loading in app/layout...}> + {children} + + ); } diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 0000000..3d92c2d --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export default function Loading() { + return ( +
+
+
+ ); +} diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index d981c2d..fd1c8a1 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -3,7 +3,7 @@ import React from "react"; export const dynamic = "force-static"; export default async function NotFound() { - const todayDate = Date.now().toString(); + const todayDate = new Date().toLocaleString(); return (
diff --git a/src/app/page.tsx b/src/app/page.tsx index eba95ad..dad12f9 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,7 @@ import Link from "next/link"; export default function Home() { - const todayDate = Date.now().toString(); + const todayDate = new Date().toLocaleString(); return (
diff --git a/src/app/posts/[postId]/layout.tsx b/src/app/posts/[postId]/layout.tsx new file mode 100644 index 0000000..38b29c5 --- /dev/null +++ b/src/app/posts/[postId]/layout.tsx @@ -0,0 +1,29 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import { Suspense } from "react"; +// import "./globals.css"; + +const inter = Inter({ subsets: ["latin"] }); + +export const experimental_ppr = true; + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + Loading in [postid]/layout...
}> + {children} + + + + ); +} diff --git a/src/app/posts/[postId]/loading.tsx b/src/app/posts/[postId]/loading.tsx new file mode 100644 index 0000000..3d92c2d --- /dev/null +++ b/src/app/posts/[postId]/loading.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export default function Loading() { + return ( +
+
+
+ ); +} diff --git a/src/app/posts/[postId]/page.tsx b/src/app/posts/[postId]/page.tsx index 1d4bcfe..3d98c98 100644 --- a/src/app/posts/[postId]/page.tsx +++ b/src/app/posts/[postId]/page.tsx @@ -1,38 +1,70 @@ import type { Post } from "@/types/PostProps"; import Link from "next/link"; -import { notFound } from "next/navigation"; +import { Suspense } from "react"; -export const dynamicParams = false; +const isPostCached = (postId: string) => { + return ["1", "2", "3", "4", "5", "6"].includes(postId); +}; export async function generateStaticParams() { - const posts: Post[] = await fetch( - "https://jsonplaceholder.typicode.com/posts", - ).then((res) => res.json()); + // only pre render the first post, but have a good loading experience for the rest + // const isPostPreBuilt = (postId: string) => { + // return ["1", "2", "3", "7", "8", "9"].includes(postId); + // }; + return [ + { postId: "1" }, + { postId: "2" }, + { postId: "3" }, + { postId: "7" }, + { postId: "8" }, + { postId: "9" }, + ]; + // const posts: Post[] = await fetch( + // "https://jsonplaceholder.typicode.com/posts", + // ).then((res) => res.json()); - return posts.map((post) => ({ - postId: post.id.toString(), - })); + // return posts + // .map((post) => ({ + // postId: post.id.toString(), + // })) + // .slice(0, 5); } -export default async function Post({ params }: { params: { postId: string } }) { - if (params.postId === "10") { - notFound(); - } +const PostItem = async ({ postId }: { postId: string }) => { const response = await fetch( - `https://jsonplaceholder.typicode.com/posts/${params.postId}`, + `https://jsonplaceholder.typicode.com/posts/${postId}`, + { + cache: isPostCached(postId) ? "default" : "no-store", + // cache: "no-store", + // cache: "default", + }, ); - const todayDate = Date.now().toString(); - const post: Post = await response.json(); + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const todayDate = new Date().toLocaleString(); + + return ( +
+

+ {post.title + todayDate} +

+

{post.body}

+
+ ); +}; + +export default function Post({ params }: { params: { postId: string } }) { + const datewithSeconds = new Date().toLocaleString(); + const exactDate = Date.now().toString(); return (
-
-

{post.title}

-

{post.body}

-
+ loading............
}> + + - Go Back {todayDate} + Go Back {datewithSeconds} {exactDate} ); diff --git a/src/app/posts/loading.tsx b/src/app/posts/loading.tsx new file mode 100644 index 0000000..3d92c2d --- /dev/null +++ b/src/app/posts/loading.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export default function Loading() { + return ( +
+
+
+ ); +} diff --git a/src/app/posts/not-found.tsx b/src/app/posts/not-found.tsx new file mode 100644 index 0000000..95d7bf6 --- /dev/null +++ b/src/app/posts/not-found.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +export const dynamic = "force-static"; + +export default async function NotFound() { + const todayDate = new Date().toLocaleString(); + + return ( +
+ NotFound at in posts! {todayDate} + Go back home. +
+ ); +} diff --git a/src/app/posts/page.tsx b/src/app/posts/page.tsx index 259e985..8a78ba8 100644 --- a/src/app/posts/page.tsx +++ b/src/app/posts/page.tsx @@ -1,11 +1,78 @@ import type { Post } from "@/types/PostProps"; import Link from "next/link"; +import { Suspense } from "react"; +// posts +// 1 : cached + pre-built +// 2 : cached + pre-built +// 3 : cached + pre-built +// 4 : cached + not pre-built +// 5 : cached + not pre-built +// 6 : cached + not pre-built +// 7 : not cached + pre-built +// 8 : not cached + pre-built +// 9 : not cached + pre-built +// 10 : not cached + not pre-built +// 11 : not cached + not pre-built +// 12 : not cached + not pre-built -export default async function PostPage() { - const response = await fetch("https://jsonplaceholder.typicode.com/posts"); +const isPostCached = (postId: number) => { + return [1, 2, 3, 4, 5, 6].includes(postId); +}; + +const isPostPreBuilt = (postId: number) => { + return [1, 2, 3, 7, 8, 9].includes(postId); +}; + +const PostsList = async () => { + const response = await fetch("https://jsonplaceholder.typicode.com/posts", { + cache: "no-store", + }); const posts: Post[] = await response.json(); - const todayDate = Date.now().toString(); + await new Promise((resolve) => setTimeout(resolve, 500)); + + const getTitle = (postId: number) => { + if (isPostCached(postId) && isPostPreBuilt(postId)) { + return "When cachable and pre built, the page is built at build time and served from cache. The return is instant."; + } + if (isPostCached(postId) && !isPostPreBuilt(postId)) { + return "When cachable but not pre built, the page is built at request time and eventually served from cache. The return is delayed with no loading experience, just a pause. Future visits are instant"; + } + if (!isPostCached(postId) && isPostPreBuilt(postId)) { + return "When not cachable and is pre-built, when partial static generation is used, you get a static loading page served from cache created at build time, and the full page loads in dynmaically. The loading page is instant. The final page is not cached at all, since it is dyynamic"; + } + if (!isPostCached(postId) && !isPostPreBuilt(postId)) { + return "When not cachable and not pre-built, when partial static generation is used, the loading page is built on demand and served from the cache, future visits will use this cached version. The final page is not cached at all and is dynamic."; + } + }; + return ( + <> + {posts.length > 0 ? ( + + ) : ( +

No posts found.

+ )} + + ); +}; + +export default async function PostPage() { + // const response = await fetch("https://jsonplaceholder.typicode.com/posts"); + + // const posts: Post[] = await response.json(); + const todayDate = new Date().toLocaleString(); return (
@@ -18,24 +85,9 @@ export default async function PostPage() {
- {posts.length > 0 ? ( -
- {posts.map((post: any) => ( - -

- {post.title} -

-

{post.body}

- - ))} -
- ) : ( -

No posts found.

- )} + Loading Posts using PPR...}> + +