diff --git a/.changeset/chilled-pants-suffer.md b/.changeset/chilled-pants-suffer.md new file mode 100644 index 000000000..e6cf50bd8 --- /dev/null +++ b/.changeset/chilled-pants-suffer.md @@ -0,0 +1,6 @@ +--- +"@headstartwp/core": patch +"@headstartwp/next": patch +--- + +Fix fetch settings for next.js diff --git a/.changeset/short-jokes-repair.md b/.changeset/short-jokes-repair.md new file mode 100644 index 000000000..a143f8413 --- /dev/null +++ b/.changeset/short-jokes-repair.md @@ -0,0 +1,5 @@ +--- +"@10up/next-redis-cache-provider": major +--- + +Introducing support for App Router diff --git a/packages/core/src/data/strategies/AbstractFetchStrategy.ts b/packages/core/src/data/strategies/AbstractFetchStrategy.ts index 615b67342..030fecf6b 100644 --- a/packages/core/src/data/strategies/AbstractFetchStrategy.ts +++ b/packages/core/src/data/strategies/AbstractFetchStrategy.ts @@ -53,11 +53,9 @@ export interface FetchResponse { queriedObject: QueriedObject; } -type NextJSHeaders = { - next?: { - revalidate?: false | 0 | number; - tags?: string[]; - }; +type NextJSFetchOptions = { + revalidate?: false | 0 | number; + tags?: string[]; }; /** @@ -101,7 +99,9 @@ export interface FetchOptions { /** * Headers to sent to fetch */ - headers?: Record & NextJSHeaders; + headers?: Record; + + next?: NextJSFetchOptions; } export interface FilterDataOptions { @@ -337,6 +337,10 @@ export abstract class AbstractFetchStrategy ): Promise { - const [key, ctx] = args; - if (ctx?.fetchIdx || ctx?.fetchUrl) { - return null; - } + const [key] = args; - // get build id and connect to redis - const [BUILD_ID] = await Promise.all([ - this.getBuildId(), - this.lazyConnect ? this.redisClient.connect() : Promise.resolve(), - ]); - const value = await this.redisClient.get(`${BUILD_ID}:${key}`); + await this.getBuildIdAndConnect(); + + const value = await this.redisClient.get(this.buildKey(key)); if (this.lazyConnect) { this.redisClient.disconnect(); @@ -160,26 +175,42 @@ export default class RedisCache implements CacheHandler { public async set(...args: Parameters): Promise { const [key, data, ctx] = args; - if (!this.flushToDisk || !data || ctx.fetchCache) return; + if (!this.flushToDisk || !data) return; - // get build id and connect to redis - const [BUILD_ID] = await Promise.all([ - this.getBuildId(), - this.lazyConnect ? this.redisClient.connect() : Promise.resolve(), - ]); + await this.getBuildIdAndConnect(); - await this.redisClient.set( - `${BUILD_ID}:${key}`, - JSON.stringify({ lastModified: Date.now(), value: data }), - ); + const value = JSON.stringify({ lastModified: Date.now(), value: data }); + const redisKey = this.buildKey(key); + + if (typeof ctx.revalidate === 'number') { + await this.redisClient.set(redisKey, value, 'EX', ctx.revalidate); + } else { + await this.redisClient.set(redisKey, value); + } + + const tags = ctx.tags || []; + + for await (const tag of tags) { + await this.redisClient.sadd(this.buildKey(`tag:${tag}`), key); + } if (this.lazyConnect) { this.redisClient.disconnect(); } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async revalidateTag(_tag: string): Promise { - // do nothing + async revalidateTag(_tag: string | string[]): Promise { + await this.getBuildIdAndConnect(); + const tags = [_tag].flat(); + + for await (const tag of tags) { + const keys = await this.redisClient.smembers(this.buildKey(`tag:${tag}`)); + + for await (const key of keys) { + await this.redisClient.del(this.buildKey(key)); + } + + await this.redisClient.del(this.buildKey(`tag:${tag}`)); + } } } diff --git a/packages/next/src/rsc/data/queries/prepareQuery.ts b/packages/next/src/rsc/data/queries/prepareQuery.ts index 7aaa933e5..528f46ca5 100644 --- a/packages/next/src/rsc/data/queries/prepareQuery.ts +++ b/packages/next/src/rsc/data/queries/prepareQuery.ts @@ -39,7 +39,7 @@ export function prepareQuery

( const options = merge['options']>([ { - cache: 'no-store', + cache: typeof rest.options?.next?.revalidate === 'undefined' ? 'no-store' : undefined, }, rest.options ?? {}, ]); diff --git a/packages/next/src/rsc/data/seo.ts b/packages/next/src/rsc/data/seo.ts index ded59edd5..84489de5f 100644 --- a/packages/next/src/rsc/data/seo.ts +++ b/packages/next/src/rsc/data/seo.ts @@ -52,7 +52,7 @@ export function fromYoastToMetadata(yoast: YoastJSON, config: HeadlessConfig = { }, twitter: { creator: yoast.twitter_creator, - card: yoast.twitter_card, + card: yoast.twitter_card ?? 'summary', title: yoast.twitter_title, description: yoast.twitter_description, images: yoast.twitter_image, diff --git a/projects/wp-nextjs-app/next.config.js b/projects/wp-nextjs-app/next.config.js index 191842431..f0f9bb11f 100644 --- a/projects/wp-nextjs-app/next.config.js +++ b/projects/wp-nextjs-app/next.config.js @@ -9,4 +9,13 @@ const nextConfig = { }, }; +if (process.env.NEXT_REDIS_URL || process.env.VIP_REDIS_PRIMARY) { + // eslint-disable-next-line global-require + const { initRedisClient } = require('@10up/next-redis-cache-provider'); + initRedisClient(); + + nextConfig.cacheHandler = require.resolve('@10up/next-redis-cache-provider'); + nextConfig.cacheMaxMemorySize = 0; +} + module.exports = withHeadstartWPConfig(nextConfig); diff --git a/projects/wp-nextjs-app/package.json b/projects/wp-nextjs-app/package.json index 21eacd2e0..d2ac3dd91 100644 --- a/projects/wp-nextjs-app/package.json +++ b/projects/wp-nextjs-app/package.json @@ -13,7 +13,8 @@ "react-dom": "^18", "next": "^14.2.5", "@headstartwp/core": "^1.5.0-next.7", - "@headstartwp/next": "^1.5.0-next.8" + "@headstartwp/next": "^1.5.0-next.8", + "@10up/next-redis-cache-provider": "^1.0.0" }, "devDependencies": { "@10up/eslint-config": "^4.0.0", diff --git a/projects/wp-nextjs-app/src/app/(single)/[...path]/page.tsx b/projects/wp-nextjs-app/src/app/(single)/[...path]/page.tsx index 7032465df..55fc1849d 100644 --- a/projects/wp-nextjs-app/src/app/(single)/[...path]/page.tsx +++ b/projects/wp-nextjs-app/src/app/(single)/[...path]/page.tsx @@ -43,6 +43,9 @@ async function query({ params }: HeadstartWPRoute) { params: { postType: ['post', 'page'], }, + options: { + cache: 'force-cache', + }, }); } diff --git a/projects/wp-nextjs-app/src/app/page.tsx b/projects/wp-nextjs-app/src/app/page.tsx index 944904679..98ec79f83 100644 --- a/projects/wp-nextjs-app/src/app/page.tsx +++ b/projects/wp-nextjs-app/src/app/page.tsx @@ -9,6 +9,12 @@ async function query({ params }: HeadstartWPRoute) { slug: 'sample-page', postType: 'page', }, + options: { + next: { + revalidate: 60, + tags: ['home'], + }, + }, }); }