Skip to content

Commit 9ec06b3

Browse files
authored
Merge branch 'main' into scottcazan/rnd-5393-track-page-view-with-sitespaceid-in-api
2 parents 60ad16c + 7675c2c commit 9ec06b3

File tree

18 files changed

+139
-348
lines changed

18 files changed

+139
-348
lines changed

.changeset/long-dryers-try.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'gitbook': patch
3+
---
4+
5+
Optimize performances by using new API endpoint for fetching site data.

bun.lockb

-384 Bytes
Binary file not shown.

packages/gitbook/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static"
1717
},
1818
"dependencies": {
19-
"@gitbook/api": "^0.73.0",
19+
"@gitbook/api": "^0.76.0",
2020
"@gitbook/cache-do": "workspace:*",
2121
"@gitbook/emoji-codepoints": "workspace:*",
2222
"@gitbook/icons": "workspace:*",

packages/gitbook/src/app/(site)/(content)/[[...pathname]]/not-found.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { getSpaceLanguage, t } from '@/intl/server';
2-
import { getSiteLayoutData } from '@/lib/api';
2+
import { getSiteData } from '@/lib/api';
33
import { getSiteContentPointer } from '@/lib/pointer';
44
import { tcls } from '@/lib/tailwind';
55

66
export default async function NotFound() {
77
const pointer = getSiteContentPointer();
8-
const { customization } = await getSiteLayoutData(pointer);
8+
const { customization } = await getSiteData(pointer);
99

1010
const language = getSpaceLanguage(customization);
1111

packages/gitbook/src/app/(site)/(content)/[[...pathname]]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default async function Page(props: {
7373
page,
7474
};
7575

76-
const withSections = Boolean(sections && sections.length > 0);
76+
const withSections = Boolean(sections && sections.list.length > 0);
7777
const headerOffset = { sectionsHeader: withSections, topHeader: withTopHeader };
7878

7979
return (

packages/gitbook/src/app/(site)/(core)/robots.txt/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { ContentVisibility } from '@gitbook/api';
21
import { NextRequest } from 'next/server';
32

4-
import { getCollection, getSite, getSpace } from '@/lib/api';
3+
import { getSpace, getSite } from '@/lib/api';
54
import { absoluteHref } from '@/lib/links';
65
import { getSiteContentPointer } from '@/lib/pointer';
76
import { isSpaceIndexable } from '@/lib/seo';

packages/gitbook/src/app/(site)/(core)/~gitbook/icon/route.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ImageResponse } from 'next/og';
33
import { NextRequest } from 'next/server';
44
import React from 'react';
55

6-
import { getCurrentSiteCustomization, getSite, getSpace } from '@/lib/api';
6+
import { getSite, getSiteData, getSpace } from '@/lib/api';
77
import { getEmojiForCode } from '@/lib/emojis';
88
import { getSiteContentPointer } from '@/lib/pointer';
99
import { tcls } from '@/lib/tailwind';
@@ -38,9 +38,9 @@ export async function GET(req: NextRequest) {
3838
const pointer = getSiteContentPointer();
3939
const spaceId = pointer.spaceId;
4040

41-
const [space, customization] = await Promise.all([
41+
const [space, { customization }] = await Promise.all([
4242
getSpace(spaceId, pointer.siteShareKey),
43-
getCurrentSiteCustomization(pointer),
43+
getSiteData(pointer),
4444
]);
4545
const site = await getSite(pointer.organizationId, pointer.siteId);
4646
const contentTitle = getContentTitle(space, customization, site);

packages/gitbook/src/app/(site)/fetch.ts

Lines changed: 11 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
import { RevisionPage, SiteSection, SiteSpace, Space } from '@gitbook/api';
2-
import { assert } from 'ts-essentials';
1+
import { RevisionPage } from '@gitbook/api';
32

43
import {
54
getRevisionPageByPath,
65
getDocument,
76
ContentTarget,
7+
getSpaceContentData,
88
getSiteData,
9-
getSite,
10-
getCurrentSiteCustomization,
11-
getSiteStructure,
129
} from '@/lib/api';
1310
import { resolvePagePath, resolvePageId } from '@/lib/pages';
1411
import { getSiteContentPointer } from '@/lib/pointer';
@@ -21,35 +18,18 @@ export interface PageIdParams {
2118
pageId: string;
2219
}
2320

24-
export type SectionsList = { list: SiteSection[]; section: SiteSection; index: number };
25-
2621
/**
2722
* Fetch all the data needed to render the content layout.
2823
*/
2924
export async function fetchContentData() {
3025
const content = getSiteContentPointer();
3126

32-
const [{ space, contentTarget, pages, customization, scripts }, siteStructure] =
27+
const [{ space, contentTarget, pages }, { customization, site, sections, spaces, scripts }] =
3328
await Promise.all([
29+
getSpaceContentData(content, content.siteShareKey),
3430
getSiteData(content),
35-
fetchSiteStructure({
36-
organizationId: content.organizationId,
37-
siteId: content.siteId,
38-
siteShareKey: content.siteShareKey,
39-
}),
4031
]);
4132

42-
const site = siteStructure.site;
43-
44-
const siteSections =
45-
content.siteSectionId && siteStructure.sections
46-
? parseSiteSectionsList(content.siteSectionId, siteStructure.sections)
47-
: null;
48-
49-
const spaces =
50-
siteStructure.spaces ??
51-
(siteSections ? parseSpacesFromSiteSpaces(siteSections.section.siteSpaces) : []);
52-
5333
// we grab the space attached to the parent as it contains overriden customizations
5434
const spaceRelativeToParent = spaces?.find((space) => space.id === content.spaceId);
5535

@@ -58,53 +38,30 @@ export async function fetchContentData() {
5838
contentTarget,
5939
space: spaceRelativeToParent ?? space,
6040
pages,
61-
sections: siteSections,
6241
site,
42+
sections,
6343
spaces,
6444
customization,
6545
scripts,
6646
ancestors: [],
6747
};
6848
}
6949

70-
function parseSiteSectionsList(siteSectionId: string, sections: SiteSection[]) {
71-
const section = sections.find((section) => section.id === siteSectionId);
72-
assert(sectionIsDefined(section), 'A section must be defined when there are multiple sections');
73-
return { list: sections, section, index: sections.indexOf(section) } satisfies SectionsList;
74-
}
75-
76-
function sectionIsDefined(section?: SiteSection): section is NonNullable<SiteSection> {
77-
return typeof section !== 'undefined' && section !== null;
78-
}
79-
8050
/**
8151
* Fetch all the data needed to render the content.
8252
* Optimized to fetch in parallel as much as possible.
8353
*/
8454
export async function fetchPageData(params: PagePathParams | PageIdParams) {
85-
const content = getSiteContentPointer();
55+
const contentData = await fetchContentData();
8656

87-
const { space, contentTarget, pages, customization, scripts } = await getSiteData(content);
88-
const page = await resolvePage(contentTarget, pages, params);
89-
const [siteStructure, document] = await Promise.all([
90-
fetchSiteStructure({
91-
organizationId: content.organizationId,
92-
siteId: content.siteId,
93-
siteShareKey: content.siteShareKey,
94-
}),
95-
page?.page.documentId ? getDocument(space.id, page.page.documentId) : null,
96-
]);
57+
const page = await resolvePage(contentData.contentTarget, contentData.pages, params);
58+
const document = page?.page.documentId
59+
? await getDocument(contentData.space.id, page.page.documentId)
60+
: null;
9761

9862
return {
99-
content,
100-
contentTarget,
101-
space,
102-
pages,
103-
customization,
104-
scripts,
105-
ancestors: [],
63+
...contentData,
10664
...page,
107-
...siteStructure,
10865
document,
10966
};
11067
}
@@ -150,59 +107,6 @@ async function resolvePage(
150107
return undefined;
151108
}
152109

153-
/**
154-
* Fetch the structure of an organization site.
155-
* This includes the site and its sections or spaces.
156-
*/
157-
async function fetchSiteStructure(args: {
158-
organizationId: string;
159-
siteId: string;
160-
siteShareKey: string | undefined;
161-
}) {
162-
const { organizationId, siteId, siteShareKey } = args;
163-
const [orgSite, siteStructure, siteParentCustomizations] = await Promise.all([
164-
getSite(organizationId, siteId),
165-
getSiteStructure({ organizationId, siteId, siteShareKey }),
166-
getCurrentSiteCustomization({ organizationId, siteId, siteSpaceId: undefined }),
167-
]);
168-
169-
const siteSections =
170-
siteStructure.type === 'sections' && siteStructure.structure
171-
? siteStructure.structure
172-
: null;
173-
const siteSpaces =
174-
siteStructure.type === 'siteSpaces' && siteStructure.structure
175-
? parseSpacesFromSiteSpaces(siteStructure.structure)
176-
: null;
177-
178-
// override the title with the customization title
179-
const site = {
180-
...orgSite,
181-
...(siteParentCustomizations?.title ? { title: siteParentCustomizations.title } : {}),
182-
};
183-
184-
return {
185-
site,
186-
spaces: siteSpaces,
187-
sections: siteSections,
188-
};
189-
}
190-
191-
function parseSpacesFromSiteSpaces(siteSpaces: SiteSpace[]) {
192-
const spaces: Record<string, Space> = {};
193-
siteSpaces.forEach((siteSpace) => {
194-
spaces[siteSpace.space.id] = {
195-
...siteSpace.space,
196-
title: siteSpace.title ?? siteSpace.space.title,
197-
urls: {
198-
...siteSpace.space.urls,
199-
published: siteSpace.urls.published,
200-
},
201-
};
202-
});
203-
return Object.values(spaces);
204-
}
205-
206110
/**
207111
* Get the page path from the params.
208112
*/

packages/gitbook/src/app/(site)/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CustomizationRootLayout } from '@/components/RootLayout';
2-
import { getSiteLayoutData } from '@/lib/api';
2+
import { getSiteData } from '@/lib/api';
33
import { getSiteContentPointer } from '@/lib/pointer';
44

55
/**
@@ -10,7 +10,7 @@ export default async function SiteRootLayout(props: { children: React.ReactNode
1010
const { children } = props;
1111

1212
const pointer = getSiteContentPointer();
13-
const { customization } = await getSiteLayoutData(pointer);
13+
const { customization } = await getSiteData(pointer);
1414

1515
return (
1616
<CustomizationRootLayout customization={customization}>{children}</CustomizationRootLayout>

packages/gitbook/src/app/(space)/~gitbook/pdf/layout.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SpaceIntegrationScript } from '@gitbook/api';
22

33
import { CustomizationRootLayout } from '@/components/RootLayout';
4-
import { getSiteLayoutData, getSpaceCustomization } from '@/lib/api';
4+
import { getSiteData, getSpaceCustomization } from '@/lib/api';
55

66
import { getSiteOrSpacePointerForPDF } from './pointer';
77

@@ -14,7 +14,7 @@ export default async function PDFRootLayout(props: { children: React.ReactNode }
1414

1515
const pointer = getSiteOrSpacePointerForPDF();
1616
const { customization } = await ('siteId' in pointer
17-
? getSiteLayoutData(pointer)
17+
? getSiteData(pointer)
1818
: getSpaceLayoutData(pointer.spaceId));
1919

2020
return (
@@ -26,7 +26,7 @@ export default async function PDFRootLayout(props: { children: React.ReactNode }
2626
* Fetch all the layout data about a space at once.
2727
*/
2828
async function getSpaceLayoutData(spaceId: string) {
29-
const [customization, scripts] = await Promise.all([
29+
const [{ customization }, scripts] = await Promise.all([
3030
getSpaceCustomization(spaceId),
3131
[] as SpaceIntegrationScript[],
3232
]);

packages/gitbook/src/app/(space)/~gitbook/pdf/page.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
getSpace,
2222
getSpaceCustomization,
2323
getSpaceContentData,
24-
getCurrentSiteCustomization,
24+
getSiteData,
2525
} from '@/lib/api';
2626
import { pagePDFContainerId, PageHrefContext, absoluteHref } from '@/lib/links';
2727
import { resolvePageId } from '@/lib/pages';
@@ -40,11 +40,9 @@ export const runtime = 'edge';
4040

4141
export async function generateMetadata(): Promise<Metadata> {
4242
const pointer = getSiteOrSpacePointerForPDF();
43-
const [space, customization] = await Promise.all([
43+
const [space, { customization }] = await Promise.all([
4444
getSpace(pointer.spaceId, 'siteId' in pointer ? pointer.siteShareKey : undefined),
45-
'siteId' in pointer
46-
? getCurrentSiteCustomization(pointer)
47-
: getSpaceCustomization(pointer.spaceId),
45+
'siteId' in pointer ? getSiteData(pointer) : getSpaceCustomization(pointer.spaceId),
4846
]);
4947

5048
return {
@@ -67,10 +65,8 @@ export default async function PDFHTMLOutput(props: { searchParams: { [key: strin
6765
currentPDFUrl += '?' + searchParams.toString();
6866

6967
// Load the content,
70-
const [customization, { space, contentTarget, pages: rootPages }] = await Promise.all([
71-
'siteId' in pointer
72-
? getCurrentSiteCustomization(pointer)
73-
: getSpaceCustomization(pointer.spaceId),
68+
const [{ customization }, { space, contentTarget, pages: rootPages }] = await Promise.all([
69+
'siteId' in pointer ? getSiteData(pointer) : getSpaceCustomization(pointer.spaceId),
7470
getSpaceContentData(pointer, 'siteId' in pointer ? pointer.siteShareKey : undefined),
7571
]);
7672
const language = getSpaceLanguage(customization);

packages/gitbook/src/components/DocumentView/BlockContentRef.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async function SpaceRefCard(
4848
return null;
4949
}
5050

51-
const spaceCustomization = await ignoreAPIError(getSpaceCustomization(spaceId));
51+
const { customization: spaceCustomization } = getSpaceCustomization(spaceId);
5252
const customFavicon = spaceCustomization?.favicon;
5353
const customEmoji = customFavicon && 'emoji' in customFavicon ? customFavicon.emoji : undefined;
5454
const customIcon = customFavicon && 'icon' in customFavicon ? customFavicon.icon : undefined;

packages/gitbook/src/components/Header/Header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { CustomizationSettings, Site, SiteCustomizationSettings, Space } from '@
22
import { CustomizationHeaderPreset } from '@gitbook/api';
33
import { Suspense } from 'react';
44

5-
import type { SectionsList } from '@/app/(site)/fetch';
65
import { CONTAINER_STYLE, HEADER_HEIGHT_DESKTOP } from '@/components/layout';
76
import { t, getSpaceLanguage } from '@/intl/server';
7+
import type { SectionsList } from '@/lib/api';
88
import { ContentRefContext } from '@/lib/references';
99
import { tcls } from '@/lib/tailwind';
1010

packages/gitbook/src/components/Search/server-actions.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,11 @@ async function searchSiteContent(args: {
6868
scope.mode === 'current' ||
6969
(scope.mode === 'specific' && scope.siteSpaceIds.length > 1);
7070

71-
const [searchResults, siteStructure] = await Promise.all([
71+
const [searchResults, siteData] = await Promise.all([
7272
api.searchSiteContent(pointer.organizationId, pointer.siteId, query, scope, cacheBust),
73-
needsStructure
74-
? api.getSiteStructure({
75-
organizationId: pointer.organizationId,
76-
siteId: pointer.siteId,
77-
siteShareKey: pointer.siteShareKey,
78-
})
79-
: null,
73+
needsStructure ? api.getSiteData(pointer) : null,
8074
]);
75+
const siteStructure = siteData?.structure;
8176

8277
const siteSpaces = siteStructure
8378
? siteStructure.type === 'siteSpaces'

packages/gitbook/src/components/SpaceLayout/SpaceLayout.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ import {
1010
} from '@gitbook/api';
1111
import React from 'react';
1212

13-
import { SectionsList } from '@/app/(site)/fetch';
1413
import { Footer } from '@/components/Footer';
1514
import { CompactHeader, Header } from '@/components/Header';
1615
import { CONTAINER_STYLE } from '@/components/layout';
1716
import { ColorDebugger } from '@/components/primitives/ColorDebugger';
1817
import { SearchModal } from '@/components/Search';
1918
import { TableOfContents } from '@/components/TableOfContents';
20-
import { ContentTarget, SiteContentPointer } from '@/lib/api';
19+
import { ContentTarget, type SectionsList, SiteContentPointer } from '@/lib/api';
2120
import { ContentRefContext } from '@/lib/references';
2221
import { tcls } from '@/lib/tailwind';
2322

0 commit comments

Comments
 (0)