Update Redis Cache example with stabilized API (#60800)

This pull request updates the `cache-handler-redis` example with a
stabilized API. The updated `next.config.js` now uses the stable
`cacheHandler` option instead of the
`experimental.incrementalCacheHandlerPath`.
This commit is contained in:
Arseny 2024-01-21 05:40:54 +03:00 committed by GitHub
parent a1610fecd8
commit 3b46f22bb1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 19 additions and 107 deletions

View file

@ -2,6 +2,8 @@
This example is tailored for self-hosted setups and demonstrates how to use Redis as a shared cache. It is built on the principles of the `@neshca/cache-handler` package, which replaces the default Next.js cache handler and adds advanced caching features.
Check out this [repository](https://github.com/ezeparziale/nextjs-k8s) that contains a comprehensive setup for Kubernetes.
## How to use
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:
@ -35,11 +37,13 @@ For detailed information on configuration and usage, please refer to our compreh
- **Handlers:** The `@neshca/cache-handler` package includes [Handlers](https://caching-tools.github.io/next-shared-cache/redis-stack) for seamless integration with Redis.
- **Create Your Own Handlers:** Take a look at [Custom Redis Handler](https://caching-tools.github.io/next-shared-cache/redis-stack-custom) and use it as a basis to create your own handler.
- **Redis Server Setup:** Ensure your Redis server is running and properly configured before starting your Next.js application.
- **Configure Redis Credentials:** Update the `cache-handler-redis*` files with your Redis credentials. Connection details can be found [here](https://redis.io/docs/connect/clients/nodejs/).
- **Building Without Redis:** To build the app without connecting to Redis, conditionally create the Handler. Check the [documentation](https://caching-tools.github.io/next-shared-cache/configuration/opt-out-cache-on-build) for more details.
- **Building Without Redis:** To build the app without connecting to Redis use conditions inside `onCreation` callback. Check the [documentation](https://caching-tools.github.io/next-shared-cache/configuration/opt-out-cache-on-build) for more details.
## Development and Production Considerations

View file

@ -1,92 +0,0 @@
const {
reviveFromBase64Representation,
replaceJsonWithBase64,
} = require("@neshca/json-replacer-reviver");
const { IncrementalCache } = require("@neshca/cache-handler");
const createLruCache = require("@neshca/cache-handler/local-lru").default;
const { createClient } = require("redis");
const REVALIDATED_TAGS_KEY = "sharedRevalidatedTags";
const client = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
client.on("error", (error) => {
console.error("Redis error:", error.message);
});
IncrementalCache.onCreation(async () => {
// read more about TTL limitations https://caching-tools.github.io/next-shared-cache/configuration/ttl
const useTtl = false;
await client.connect();
const redisCache = {
async get(key) {
try {
const result = (await client.get(key)) ?? null;
if (!result) {
return null;
}
// use reviveFromBase64Representation to restore binary data from Base64
return JSON.parse(result, reviveFromBase64Representation);
} catch (error) {
console.error("cache.get", error);
return null;
}
},
async set(key, value, ttl) {
try {
await client.set(
key,
// use replaceJsonWithBase64 to store binary data in Base64 and save space
JSON.stringify(value, replaceJsonWithBase64),
useTtl && typeof ttl === "number" ? { EX: ttl } : undefined,
);
} catch (error) {
console.error("cache.set", error);
}
},
async getRevalidatedTags() {
try {
const sharedRevalidatedTags = await client.hGetAll(
REVALIDATED_TAGS_KEY,
);
const entries = Object.entries(sharedRevalidatedTags);
const revalidatedTags = Object.fromEntries(
entries.map(([tag, revalidatedAt]) => [tag, Number(revalidatedAt)]),
);
return revalidatedTags;
} catch (error) {
console.error("cache.getRevalidatedTags", error);
}
},
async revalidateTag(tag, revalidatedAt) {
try {
await client.hSet(REVALIDATED_TAGS_KEY, {
[tag]: revalidatedAt,
});
} catch (error) {
console.error("cache.revalidateTag", error);
}
},
};
const localCache = createLruCache({
useTtl,
});
return {
cache: [redisCache, localCache],
useFileSystem: !useTtl,
};
});
module.exports = IncrementalCache;

View file

@ -13,7 +13,11 @@ client.on("error", (error) => {
IncrementalCache.onCreation(async () => {
// read more about TTL limitations https://caching-tools.github.io/next-shared-cache/configuration/ttl
const useTtl = true;
function useTtl(maxAge) {
const evictionAge = maxAge * 1.5;
return evictionAge;
}
await client.connect();
@ -28,7 +32,8 @@ IncrementalCache.onCreation(async () => {
return {
cache: [redisCache, localCache],
useFileSystem: !useTtl,
// read more about useFileSystem limitations https://caching-tools.github.io/next-shared-cache/configuration/use-file-system
useFileSystem: false,
};
});

View file

@ -1,14 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
incrementalCacheHandlerPath:
process.env.NODE_ENV === "production"
? require.resolve(
// './cache-handler-redis-custom.js' // custom configuration
"./cache-handler-redis.js",
)
: undefined,
},
cacheHandler:
process.env.NODE_ENV === "production"
? require.resolve("./cache-handler.js")
: undefined,
env: {
NEXT_PUBLIC_REDIS_INSIGHT_URL:
process.env.REDIS_INSIGHT_URL ?? "http://localhost:8001",

View file

@ -13,9 +13,9 @@
"devDependencies": {
"@neshca/cache-handler": "^0.6",
"@neshca/json-replacer-reviver": "^1",
"@types/node": "^20.10.4",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.2.17",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"redis": "latest",
"typescript": "^5.3.3"
}