mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-16 23:55:20 +00:00
Use absolute URLs for metadata (icon / social graph) (#30)
* Use absolute URLs for metadata (icon / social graph) * Disable cache using "next" instead of "cache" * Use cloudflare module from upstash
This commit is contained in:
@@ -3,7 +3,7 @@ import { notFound, redirect } from 'next/navigation';
|
||||
|
||||
import { SpaceContent } from '@/components/SpaceContent';
|
||||
import { getDocument } from '@/lib/api';
|
||||
import { PageHrefContext, baseUrl, pageHref } from '@/lib/links';
|
||||
import { PageHrefContext, absoluteHref, baseUrl, pageHref } from '@/lib/links';
|
||||
import { getPagePath } from '@/lib/pages';
|
||||
|
||||
import { PagePathParams, fetchPageData, getPathnameParam } from '../fetch';
|
||||
@@ -53,25 +53,33 @@ export async function generateMetadata({ params }: { params: PagePathParams }):
|
||||
|
||||
return {
|
||||
title: `${page.title} | ${space.title}`,
|
||||
description: page.description,
|
||||
description: page.description ?? '',
|
||||
generator: 'GitBook',
|
||||
// We pass `metadataBase` to avoid warnings from Next, but we still use absolute URLs
|
||||
// as metadataBase doesn't seem to work well on next-on-cloudflare.
|
||||
metadataBase: new URL(baseUrl()),
|
||||
icons: {
|
||||
icon: [
|
||||
{
|
||||
url: customIcon?.light ?? '.gitbook/icon?size=small&theme=light',
|
||||
url:
|
||||
customIcon?.light ??
|
||||
absoluteHref('.gitbook/icon?size=small&theme=light', true),
|
||||
type: 'image/png',
|
||||
media: '(prefers-color-scheme: light)',
|
||||
},
|
||||
{
|
||||
url: customIcon?.dark ?? '.gitbook/icon?size=small&theme=dark',
|
||||
url:
|
||||
customIcon?.dark ??
|
||||
absoluteHref('.gitbook/icon?size=small&theme=dark', true),
|
||||
type: 'image/png',
|
||||
media: '(prefers-color-scheme: dark)',
|
||||
},
|
||||
],
|
||||
},
|
||||
openGraph: {
|
||||
images: [customization.socialPreview.url ?? `.gitbook/ogimage/${page.id}`],
|
||||
images: [
|
||||
customization.socialPreview.url ?? absoluteHref(`.gitbook/ogimage/${page.id}`),
|
||||
],
|
||||
},
|
||||
// TODO: remove once the development is finished
|
||||
robots: space.visibility === 'public' && 0 ? 'index, follow' : 'noindex, nofollow',
|
||||
|
||||
+14
-17
@@ -8,7 +8,7 @@ import {
|
||||
} from '@gitbook/api';
|
||||
import { headers } from 'next/headers';
|
||||
|
||||
import { cache, cacheResponse } from './cache';
|
||||
import { cache, cacheResponse, noCacheFetchOptions } from './cache';
|
||||
|
||||
export interface ContentPointer {
|
||||
spaceId: string;
|
||||
@@ -72,10 +72,7 @@ export const getPublishedContentByUrl = cache(
|
||||
secure: false,
|
||||
format: 'json',
|
||||
signal: signal,
|
||||
// Cloudflare doesn't support the `cache` directive before next-on-pages patches the fetch function
|
||||
// https://github.com/cloudflare/workerd/issues/698
|
||||
// cache: 'no-store',
|
||||
next: { revalidate: 0 },
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
|
||||
return cacheResponse(response);
|
||||
@@ -91,7 +88,7 @@ export const getPublishedContentByUrl = cache(
|
||||
*/
|
||||
export const getSpace = cache('api.getSpace', async (spaceId: string) => {
|
||||
const response = await api().spaces.getSpaceById(spaceId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
return cacheResponse(response);
|
||||
});
|
||||
@@ -103,18 +100,18 @@ export const getRevisionPages = cache('api.getRevisionPages', async (pointer: Co
|
||||
const { data } = await (async () => {
|
||||
if (pointer.revisionId) {
|
||||
return api().spaces.listPagesInRevisionById(pointer.spaceId, pointer.revisionId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
}
|
||||
|
||||
if (pointer.changeRequestId) {
|
||||
return api().spaces.listPagesInChangeRequest(spaceId, pointer.changeRequestId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
}
|
||||
|
||||
return api().spaces.listPages(pointer.spaceId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
})();
|
||||
return { data: data.pages! };
|
||||
@@ -134,7 +131,7 @@ export const getRevisionFile = cache(
|
||||
pointer.revisionId,
|
||||
fileId,
|
||||
{
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -145,13 +142,13 @@ export const getRevisionFile = cache(
|
||||
pointer.changeRequestId,
|
||||
fileId,
|
||||
{
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return api().spaces.getFileById(pointer.spaceId, fileId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
})();
|
||||
return cacheResponse(response);
|
||||
@@ -170,7 +167,7 @@ export const getRevisionFile = cache(
|
||||
*/
|
||||
export const getCurrentRevision = cache('api.getCurrentRevision', async (spaceId: string) => {
|
||||
const response = await api().spaces.getCurrentRevision(spaceId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
return cacheResponse(response);
|
||||
});
|
||||
@@ -180,7 +177,7 @@ export const getCurrentRevision = cache('api.getCurrentRevision', async (spaceId
|
||||
*/
|
||||
export const getDocument = cache('api.getDocument', async (spaceId: string, documentId: string) => {
|
||||
const response = await api().spaces.getDocumentById(spaceId, documentId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
return cacheResponse(response);
|
||||
});
|
||||
@@ -190,7 +187,7 @@ export const getDocument = cache('api.getDocument', async (spaceId: string, docu
|
||||
*/
|
||||
export const getSpaceCustomization = cache('api.getSpaceCustomization', async (spaceId: string) => {
|
||||
const response = await api().spaces.getSpacePublishingCustomizationById(spaceId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
return cacheResponse(response);
|
||||
});
|
||||
@@ -200,7 +197,7 @@ export const getSpaceCustomization = cache('api.getSpaceCustomization', async (s
|
||||
*/
|
||||
export const getCollection = cache('api.getCollection', async (collectionId: string) => {
|
||||
const response = await api().collections.getCollectionById(collectionId, {
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
});
|
||||
return cacheResponse(response);
|
||||
});
|
||||
@@ -215,7 +212,7 @@ export const getCollectionSpaces = cache(
|
||||
collectionId,
|
||||
{},
|
||||
{
|
||||
cache: 'no-store',
|
||||
...noCacheFetchOptions,
|
||||
},
|
||||
);
|
||||
// TODO: do this filtering on the API side
|
||||
|
||||
+11
-1
@@ -1,4 +1,4 @@
|
||||
import { Redis } from '@upstash/redis';
|
||||
import { Redis } from '@upstash/redis/cloudflare';
|
||||
import parseCacheControl from 'parse-cache-control';
|
||||
|
||||
const cacheNamespace = process.env.UPSTASH_REDIS_NAMESPACE ?? 'gitbook';
|
||||
@@ -23,6 +23,16 @@ export interface CacheResult<Result> {
|
||||
ttl?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to pass to the `fetch` call to disable the Next data-cache when wrapped in `cache()`.
|
||||
*/
|
||||
export const noCacheFetchOptions: Partial<RequestInit> = {
|
||||
// Cloudflare doesn't support the `cache` directive before next-on-pages patches the fetch function
|
||||
// https://github.com/cloudflare/workerd/issues/698
|
||||
// cache: 'no-store',
|
||||
next: { revalidate: 0 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache data from an async function.
|
||||
* We don't use the next.js cache because it has a 2MB limit.
|
||||
|
||||
+2
-2
@@ -50,8 +50,8 @@ export function baseUrl(): string {
|
||||
/**
|
||||
* Create an absolute href in the current content.
|
||||
*/
|
||||
export function absoluteHref(href: string): string {
|
||||
const base = basePath();
|
||||
export function absoluteHref(href: string, withHost: boolean = false): string {
|
||||
const base = withHost ? baseUrl() : basePath();
|
||||
return `${base}${href.startsWith('/') ? href.slice(1) : href}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user