Skip to content

Commit f37a396

Browse files
committed
feat: add demo pages
1 parent faa8b63 commit f37a396

File tree

19 files changed

+353
-82
lines changed

19 files changed

+353
-82
lines changed

README.md

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,32 @@
1-
# Next + Netlify Starter
1+
# Demo: Netlify Durable Cache with Next.js
22

3-
[![Netlify Status](https://api.netlify.com/api/v1/badges/46648482-644c-4c80-bafb-872057e51b6b/deploy-status)](https://app.netlify.com/sites/next-dev-starter/deploys)
3+
This is a Next.js site demonstrating the [Netlify Durable
4+
Cache](https://docs.netlify.com/platform/caching/#durable-directive) feature,
5+
released in July 2024.
46

5-
This is a [Next.js](https://nextjs.org/) v14 project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) and set up to be instantly deployed to [Netlify](https://url.netlify.com/SyTBPVamO)!
7+
This is a [Next.js](https://nextjs.org/) v14 project bootstrapped with
8+
[`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) and set up to be instantly deployed to [Netlify](https://url.netlify.com/SyTBPVamO)!
69

7-
This project is a very minimal starter that includes 2 sample components, a global stylesheet, a `netlify.toml` for deployment, and a `jsconfig.json` for setting up absolute imports and aliases. With Netlify, you'll have access to features like Preview Mode, server-side rendering/incremental static regeneration via Netlify Functions, and internationalized routing on deploy automatically.
10+
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/serhalp/next.js-netlify-durable-cache-demo&utm_source=github&utm_medium=nextstarter-cs&utm_campaign=devex-cs)
811

9-
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify-templates/next-netlify-starter&utm_source=github&utm_medium=nextstarter-cs&utm_campaign=devex-cs)
12+
(If you click this button, it will create a new repo for you that looks exactly
13+
like this one, and sets that repo up immediately for deployment on Netlify)
1014

11-
(If you click this button, it will create a new repo for you that looks exactly like this one, and sets that repo up immediately for deployment on Netlify)
15+
## Demo
1216

13-
## Table of Contents:
17+
You can visit the two deployments below to see the feature in action.
1418

15-
- [Getting Started](#getting-started)
16-
- [Installation options](#installation-options)
17-
- [Testing](#testing)
18-
- [Included Default Testing](#included-default-testing)
19-
- [Removing Renovate](#removing-renovate)
19+
### With the Durable Cache
2020

21-
## Getting Started
21+
[This deployment of the demo site](https://nextjs-netlify-durable-cache-demo.netlify.app/)
22+
has the Durable Cache feature **enabled**.
2223

23-
First, run the development server:
24+
With the Durable Cache, valid responses cached on the CDN are always returned.
2425

25-
```bash
26-
npm run dev
27-
# or
28-
yarn dev
29-
```
26+
### Without the Durable Cache
3027

31-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
28+
[This deployment of the demo site](https://6685d117714ca41686e1a306--nextjs-netlify-durable-cache-demo.netlify.app/)
29+
has the Durable Cache feature **disabled**.
3230

33-
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
34-
35-
### Installation options
36-
37-
**Option one:** One-click deploy
38-
39-
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify-templates/next-netlify-starter&utm_source=github&utm_medium=nextstarter-cs&utm_campaign=devex-cs)
40-
41-
**Option two:** Manual clone
42-
43-
1. Clone this repo: `git clone https://github.com/netlify-templates/next-netlify-starter.git`
44-
2. Navigate to the directory and run `npm install`
45-
3. Run `npm run dev`
46-
4. Make your changes
47-
5. Connect to [Netlify](https://url.netlify.com/Bk4UicocL) manually (the `netlify.toml` file is the one you'll need to make sure stays intact to make sure the export is done and pointed to the right stuff)
48-
49-
## Testing
50-
51-
### Included Default Testing
52-
53-
We’ve included some tooling that helps us maintain these templates. This template currently uses:
54-
55-
- [Renovate](https://www.mend.io/free-developer-tools/renovate/) - to regularly update our dependencies
56-
- [Cypress](https://www.cypress.io/) - to run tests against how the template runs in the browser
57-
- [Cypress Netlify Build Plugin](https://github.com/cypress-io/netlify-plugin-cypress) - to run our tests during our build process
58-
59-
If your team is not interested in this tooling, you can remove them with ease!
60-
61-
### Removing Renovate
62-
63-
In order to keep our project up-to-date with dependencies we use a tool called [Renovate](https://github.com/marketplace/renovate). If you’re not interested in this tooling, delete the `renovate.json` file and commit that onto your main branch.
31+
Without the Durable Cache, valid responses cached on the CDN may or may not be used,
32+
depending on which CDN node happens to serve subsequent requests.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { metadata as parentMetadata } from "../../layout";
2+
3+
export const metadata = {
4+
title: `${parentMetadata.title} - dynamic cacheable page`,
5+
};
6+
7+
// Avoid next.js heuristics to be 100% sure we're testing what we think we are
8+
export const dynamicParams = true;
9+
10+
// This is seemingly the only way to render a page dynamically and have the full response be cached.
11+
// See https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#replacing-fallback.
12+
export async function generateStaticParams() {
13+
return [];
14+
}
15+
16+
export default () => {
17+
const id = new Date().getMilliseconds();
18+
return (
19+
<>
20+
<p className="description">
21+
This is a dynamic cacheable page. It is rendered on demand by a Netlify
22+
function via SSR and it is cacheable on the CDN for 15 seconds.
23+
</p>
24+
<code>{id}</code>
25+
</>
26+
);
27+
};

app/dynamic-page/page.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { metadata as parentMetadata } from "../layout";
2+
3+
export const metadata = {
4+
title: `${parentMetadata.title} - dynamic page`,
5+
};
6+
7+
// Avoid next.js heuristics to be 100% sure we're testing what we think we are
8+
export const dynamic = "force-dynamic";
9+
export const revalidate = 0;
10+
11+
export default () => {
12+
const id = new Date().getMilliseconds();
13+
return (
14+
<>
15+
<p className="description">
16+
This is a dynamic page. It is rendered on demand by a Netlify function
17+
via SSR and it is not cacheable.
18+
</p>
19+
<code>{id}</code>
20+
</>
21+
);
22+
};

app/isr-page/page.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { metadata as parentMetadata } from "../layout";
2+
3+
export const metadata = {
4+
title: `${parentMetadata.title} - dynamic cacheable page`,
5+
};
6+
7+
// Avoid next.js heuristics to be 100% sure we're testing what we think we are
8+
export const dynamic = "force-static";
9+
export const revalidate = 15;
10+
11+
export default () => {
12+
const id = new Date().getMilliseconds();
13+
return (
14+
<>
15+
<p className="description">
16+
This is a static page that uses Incremental Static Regeneration (ISR).
17+
It is rendered initially at build time, then it is re-rendered - in the
18+
background - by a Netlify function via SSR, if the served page is older
19+
than 15 seconds.
20+
</p>
21+
<code>{id}</code>
22+
</>
23+
);
24+
};

app/layout.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import "@styles/globals.css";
2+
3+
import React from "react";
4+
5+
import Header from "@components/Header";
6+
import Footer from "@components/Footer";
7+
8+
export const metadata = {
9+
title: "Demo: Netlify Durable Cache with Next.js",
10+
description: "A demo of Netlify Durable Cache with Next.js",
11+
};
12+
13+
export default function RootLayout({ children }) {
14+
return (
15+
<html lang="en">
16+
<body>
17+
<div className="container">
18+
<main>
19+
<Header title="Demo: Netlify Durable Cache with Next.js" />
20+
{children}
21+
</main>
22+
<Footer />
23+
</div>
24+
</body>
25+
</html>
26+
);
27+
}

app/page.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export default function HomePage() {
2+
return (
3+
<>
4+
<h3>App Router</h3>
5+
<ul>
6+
<li>
7+
<a href="/static-page">a static page</a>
8+
</li>
9+
<li>
10+
<a href="/dynamic-cacheable-page">a dynamic page (cacheable)</a>
11+
</li>
12+
<li>
13+
<a href="/dynamic-page">a dynamic page (not cacheable)</a>
14+
</li>
15+
<li>
16+
<a href="/isr-page">an ISR page</a>
17+
</li>
18+
</ul>
19+
20+
<h3>Pages Router</h3>
21+
<ul>
22+
<li>
23+
<a href="/pages-router/static-page">a static page</a>
24+
</li>
25+
<li>
26+
<a href="/pages-router/dynamic-cacheable-page">
27+
a dynamic page (cacheable)
28+
</a>
29+
</li>
30+
<li>
31+
<a href="/pages-router/dynamic-page">
32+
a dynamic page (not cacheable)
33+
</a>
34+
</li>
35+
<li>
36+
<a href="/pages-router/isr-page">an ISR page</a>
37+
</li>
38+
</ul>
39+
</>
40+
);
41+
}

app/static-page/page.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { metadata as parentMetadata } from "../layout";
2+
3+
export const metadata = {
4+
title: `${parentMetadata.title} - static page`,
5+
};
6+
7+
// Avoid next.js heuristics to be 100% sure we're testing what we think we are
8+
export const dynamic = "force-static";
9+
10+
export default () => {
11+
const id = new Date().getMilliseconds();
12+
return (
13+
<>
14+
<p className="description">
15+
This is a static page. It is rendered once at build time and it is
16+
immutably cached.
17+
</p>
18+
<code>{id}</code>
19+
</>
20+
);
21+
};

components/Header.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
export default function Header({ title }) {
2-
return <h1 className="title">{title}</h1>
2+
return (
3+
<>
4+
<h1 className="title">{title}</h1>
5+
<div className="callout">
6+
❌ This deployment has the Durable Cache feature{" "}
7+
<strong>disabled</strong>.
8+
</div>
9+
</>
10+
);
311
}

components/Layout.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Head from "next/head";
2+
import Header from "@components/Header";
3+
import Footer from "@components/Footer";
4+
5+
export default function Layout({ subtitle, children }) {
6+
return (
7+
<div className="container">
8+
<Head>
9+
<title>Netlify Durable Cache with Next.js - {subtitle}</title>
10+
<link rel="icon" href="/favicon.ico" />
11+
</Head>
12+
13+
<main>
14+
<Header title="Demo: Netlify Durable Cache with Next.js" />
15+
{children}
16+
</main>
17+
18+
<Footer />
19+
</div>
20+
);
21+
}

netlify.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
publish = ".next"
44

55
[[plugins]]
6-
package = "@netlify/plugin-nextjs"
6+
package = "@netlify/plugin-nextjs"

package-lock.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
"next": "^14.2.4",
1313
"react": "^18.3.1",
1414
"react-dom": "^18.3.1"
15+
},
16+
"devDependencies": {
17+
"@netlify/plugin-nextjs": "^5.4.0"
1518
}
1619
}

pages/_app.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import '@styles/globals.css'
1+
import "@styles/globals.css";
2+
3+
import Layout from "@components/Layout";
24

35
function Application({ Component, pageProps }) {
4-
return <Component {...pageProps} />
6+
return (
7+
<Layout subtitle={Component.subtitle}>
8+
<Component {...pageProps} />
9+
</Layout>
10+
);
511
}
612

7-
export default Application
13+
export default Application;

pages/index.js

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const DynamicCacheablePage = ({ id }) => {
2+
return (
3+
<>
4+
<p className="description">
5+
This is a dynamic cacheable page. It is rendered on demand by a Netlify
6+
function via SSR and it is cacheable on the CDN for 15 seconds.
7+
</p>
8+
<code>{id}</code>
9+
</>
10+
);
11+
};
12+
13+
DynamicCacheablePage.subtitle = "dynamic cacheable page";
14+
15+
export default DynamicCacheablePage;
16+
17+
export const getServerSideProps = async ({ res }) => {
18+
// https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props#caching-with-server-side-rendering-ssr
19+
res.setHeader("Cache-Control", "public, s-maxage=15, must-revalidate");
20+
return {
21+
props: { id: new Date().getMilliseconds() },
22+
};
23+
};

0 commit comments

Comments
 (0)