Skip to content

Commit

Permalink
AG-11304 - Reduce html size (#1564)
Browse files Browse the repository at this point in the history
* AG-11304 - Reduce html size by fetching resolved interfaces instead of injecting onto page

Get `resolved-interfaces.json` on client side instead of injecting it from the astro file into the react component. This caused the html to be very large.

* AG-11304 - Move doc interface patching to the generation step

* AG-11304 - Move docs-interfaces-patched to docs-interfaces task
  • Loading branch information
taktran committed May 14, 2024
1 parent 7272d43 commit 61951cd
Show file tree
Hide file tree
Showing 19 changed files with 229 additions and 164 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
---
import { patchAgChartOptionsReference } from '@features/api-documentation/apiReferenceHelpers';
import { ApiReferenceWithContext } from './components/ApiReference';
import { getInterfacesReference } from '@utils/devFiles';
const reference = getInterfacesReference();
patchAgChartOptionsReference(reference);
---

<ApiReferenceWithContext client:load {...Astro.props} reference={reference} />
<ApiReferenceWithContext client:load {...Astro.props} />
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { ApiReferenceConfig } from '@features/api-documentation/components/ApiReference';

import type {
ApiReferenceNode,
ApiReferenceType,
Expand All @@ -8,7 +7,7 @@ import type {
MemberNode,
TypeLiteralNode,
TypeNode,
} from './api-reference-types';
} from '@generate-code-reference-plugin/doc-interfaces/types';

type PossibleTypeNode = TypeNode | undefined | PossibleTypeNode[];

Expand Down Expand Up @@ -297,98 +296,7 @@ export function extractSearchData(
return [];
}

export function patchAgChartOptionsReference(reference: ApiReferenceType) {
const interfaceRef = reference.get('AgChartOptions');
const getTypeUnion = (typeRef: ApiReferenceNode | undefined): string[] => {
if (typeRef?.kind === 'typeAlias') {
if (typeof typeRef.type === 'string') {
return [typeRef.type];
}
if (typeof typeRef.type === 'object' && typeRef.type.kind === 'union') {
return typeRef.type.type.filter((type): type is string => typeof type === 'string');
}
}
return [];
};

const axisOptions: string[] = [];
const seriesOptions: string[] = [];

let altInterface: InterfaceNode | null = null;

for (const typeName of getTypeUnion(interfaceRef)) {
const typeRef = reference.get(typeName);

if (typeRef?.kind !== 'interface') {
throw Error('Unexpected AgChartOptions union type');
}

altInterface ??= typeRef;

for (const member of typeRef.members) {
if (
typeof member.type !== 'object' ||
member.type.kind !== 'array' ||
typeof member.type.type !== 'string'
) {
continue;
}

if (member.name === 'axes') {
const axisOption = reference.get(member.type.type);
// Ignore `groupedCategory` axis, as it is an implementation detail
const axisOptionUnion = getTypeUnion(axisOption).filter(
(name) => name !== 'AgGroupedCategoryAxisOptions'
);
axisOptions.push(...axisOptionUnion);
} else if (member.name === 'series') {
seriesOptions.push(...getTypeUnion(reference.get(member.type.type)));
}
}
}

if (altInterface === null) {
return;
}

reference.set('AgChartAxisOptions', {
kind: 'typeAlias',
name: 'AgChartAxisOptions',
type: { kind: 'union', type: axisOptions },
});
reference.set('AgChartSeriesOptions', {
kind: 'typeAlias',
name: 'AgChartSeriesOptions',
type: { kind: 'union', type: seriesOptions },
});

altInterface = {
...altInterface,
name: 'AgChartOptions',
members: altInterface.members.map((member) => {
if (typeof member.type !== 'object') {
return member;
}
if (member.name === 'axes') {
return Object.assign({}, member, {
type: Object.assign({}, member.type, { type: 'AgChartAxisOptions' }),
});
}
if (member.name === 'series') {
return Object.assign({}, member, {
type: Object.assign({}, member.type, { type: 'AgChartSeriesOptions' }),
});
}
return member;
}),
};

reference.set('AgChartOptions', altInterface);
}

export function getOptionsStaticPaths(reference: ApiReferenceType) {
patchAgChartOptionsReference(reference);

const getSubTypes = (ref: ApiReferenceNode): string[] =>
ref.kind === 'typeAlias' &&
typeof ref.type === 'object' &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { Icon } from '@ag-website-shared/components/icon/Icon';
import { navigate, scrollIntoViewById, useLocation } from '@ag-website-shared/utils/navigation';
import Code from '@components/Code';
import type {
ApiReferenceNode,
ApiReferenceType,
MemberNode,
TypeAliasNode,
} from '@generate-code-reference-plugin/doc-interfaces/types';
import { fetchInterfacesReference } from '@utils/client/fetchInterfacesReference';
import { useToggle } from '@utils/hooks/useToggle';
import classnames from 'classnames';
import type { AllHTMLAttributes, CSSProperties } from 'react';
import { createContext, useContext, useEffect } from 'react';
import Markdown from 'react-markdown';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
import remarkBreaks from 'remark-breaks';

import type { ApiReferenceNode, ApiReferenceType, MemberNode, TypeAliasNode } from '../api-reference-types';
import type { SpecialTypesMap } from '../apiReferenceHelpers';
import {
cleanupName,
Expand All @@ -25,6 +32,17 @@ import { PropertyTitle, PropertyType } from './Properies';
export const ApiReferenceContext = createContext<ApiReferenceType | undefined>(undefined);
export const ApiReferenceConfigContext = createContext<ApiReferenceConfig>({});

// NOTE: Not on the layout level, as that is generated at build time, and queryClient needs to be
// loaded on the client side
const queryClient = new QueryClient();

const queryOptions = {
retry: false,
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
};

export interface ApiReferenceConfig {
prioritise?: string[];
include?: string[];
Expand All @@ -51,20 +69,35 @@ interface ApiReferenceRowOptions {
}

export function ApiReferenceWithContext({
reference,
prioritise,
include,
exclude,
hideHeader,
hideRequired,
keepExpanded,
...props
}: ApiReferenceOptions & ApiReferenceConfig & { reference: ApiReferenceType }) {
}: ApiReferenceOptions & ApiReferenceConfig) {
return (
<ApiReferenceContext.Provider value={reference}>
<QueryClientProvider client={queryClient}>
<ApiReferenceConfigContext.Provider value={{ prioritise, include, exclude, hideHeader, hideRequired }}>
<ApiReference {...props} />
<ApiReferenceWithReferenceContext {...props} />
</ApiReferenceConfigContext.Provider>
</QueryClientProvider>
);
}

export function ApiReferenceWithReferenceContext(props: ApiReferenceOptions & ApiReferenceConfig) {
const { data: reference } = useQuery(
['resolved-interfaces'],
async () => {
const data = await fetchInterfacesReference();
return data;
},
queryOptions
);

return (
<ApiReferenceContext.Provider value={reference}>
<ApiReference {...props} />
</ApiReferenceContext.Provider>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { navigate, useHistory, useLocation } from '@ag-website-shared/utils/navigation';
import type { ApiReferenceType, InterfaceNode } from '@generate-code-reference-plugin/doc-interfaces/types';
import { urlWithBaseUrl } from '@utils/urlWithBaseUrl';
import classNames from 'classnames';
import type { CSSProperties } from 'react';
import { useContext, useEffect, useState } from 'react';
import Markdown from 'react-markdown';
import remarkBreaks from 'remark-breaks';

import type { ApiReferenceType, InterfaceNode } from '../api-reference-types';
import type { PageTitle } from '../apiReferenceHelpers';
import type { NavigationData, SpecialTypesMap } from '../apiReferenceHelpers';
import { ApiReference, ApiReferenceConfigContext, ApiReferenceContext } from './ApiReference';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Icon } from '@ag-website-shared/components/icon/Icon';
import { navigate, scrollIntoView, scrollIntoViewById, useLocation } from '@ag-website-shared/utils/navigation';
import type {
ApiReferenceNode,
ApiReferenceType,
MemberNode,
} from '@generate-code-reference-plugin/doc-interfaces/types';
import { useToggle } from '@utils/hooks/useToggle';
import classnames from 'classnames';
import type { AllHTMLAttributes, CSSProperties, Dispatch, MouseEventHandler, ReactNode, SetStateAction } from 'react';
import { createContext, useContext, useEffect, useMemo, useRef } from 'react';

import type { ApiReferenceNode, ApiReferenceType, MemberNode } from '../api-reference-types';
import { type NavigationData, type NavigationPath, isInterfaceHidden } from '../apiReferenceHelpers';
import {
cleanupName,
Expand Down
4 changes: 1 addition & 3 deletions packages/ag-charts-website/src/pages/options.astro
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
---
import { patchAgChartOptionsReference } from '@features/api-documentation/apiReferenceHelpers';
import { ApiReferencePage } from '@features/api-documentation/components/ApiReferencePage';
import APIViewLayout from '@layouts/APIViewLayout.astro';
import { getInterfacesReference } from '@utils/devFiles';
import { getInterfacesReference } from '@utils/server/getInterfacesReference';
const reference = getInterfacesReference();
patchAgChartOptionsReference(reference);
---

<APIViewLayout title="Options API">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
---
import { getOptionsStaticPaths, patchAgChartOptionsReference } from '@features/api-documentation/apiReferenceHelpers';
import { getOptionsStaticPaths } from '@features/api-documentation/apiReferenceHelpers';
import { ApiReferencePage } from '@features/api-documentation/components/ApiReferencePage';
import APIViewLayout from '@layouts/APIViewLayout.astro';
import { getInterfacesReference } from '@utils/devFiles';
import { getInterfacesReference } from '@utils/server/getInterfacesReference';
export async function getStaticPaths() {
const reference = getInterfacesReference();
return getOptionsStaticPaths(reference);
}
const reference = getInterfacesReference();
patchAgChartOptionsReference(reference);
---

<APIViewLayout title="Options API">
Expand Down
2 changes: 1 addition & 1 deletion packages/ag-charts-website/src/pages/themes-api.astro
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
import { ApiReferencePage } from '@features/api-documentation/components/ApiReferencePage';
import APIViewLayout from '@layouts/APIViewLayout.astro';
import { getInterfacesReference } from '@utils/devFiles';
import { getInterfacesReference } from '@utils/server/getInterfacesReference';
const reference = getInterfacesReference();
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { getThemesApiStaticPaths } from '@features/api-documentation/apiReferenceHelpers';
import { ApiReferencePage } from '@features/api-documentation/components/ApiReferencePage';
import APIViewLayout from '@layouts/APIViewLayout.astro';
import { getInterfacesReference } from '@utils/devFiles';
import { getInterfacesReference } from '@utils/server/getInterfacesReference';
export async function getStaticPaths() {
const reference = getInterfacesReference();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { ApiReferenceType } from '@generate-code-reference-plugin/doc-interfaces/types';
import { getDevFileUrl } from '@utils/devFileUrl';

/**
* Get interfaces reference by fetching from the dev files url
*/
export async function fetchInterfacesReference(): Promise<ApiReferenceType> {
const contents = await fetch(
getDevFileUrl({
filePath: '/resolved-interfaces.json',
})
).then((res) => res.json());

return new Map(Object.entries(contents));
}
33 changes: 0 additions & 33 deletions packages/ag-charts-website/src/utils/devFiles.ts

This file was deleted.

12 changes: 0 additions & 12 deletions packages/ag-charts-website/src/utils/hidden-api-options.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ApiReferenceType } from '@generate-code-reference-plugin/doc-interfaces/types';
import { DEV_FILE_PATH_MAP, getRootUrl } from '@utils/pages';
import { pathJoin } from '@utils/pathJoin';
import { readFileSync } from 'node:fs';

type DevFileKey = keyof typeof DEV_FILE_PATH_MAP;

function getJsonFromDevFile(devFileKey: DevFileKey) {
const file = pathJoin(getRootUrl().pathname, DEV_FILE_PATH_MAP[devFileKey]);
const fileContents = readFileSync(file).toString();
return fileContents ? JSON.parse(fileContents) : null;
}

/**
* Get interfaces reference from the file system
*
* For static site generation
*/
export function getInterfacesReference(): ApiReferenceType {
const jsonContent = getJsonFromDevFile('resolved-interfaces.json');
return new Map(Object.entries(jsonContent));
}
1 change: 1 addition & 0 deletions packages/ag-charts-website/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@utils/*": ["src/utils/*"],
"@constants": ["src/constants.ts"],
"@ag-website-shared/*": ["../../external/ag-website-shared/src/*"],
"@generate-code-reference-plugin/*": ["../../plugins/ag-charts-generate-code-reference-files/src/*"],
"ag-charts-community": ["../ag-charts-community/src/main.ts"],
"ag-charts-enterprise": ["../ag-charts-enterprise/src/main.ts"]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const HIDDEN_API_OPTIONS = {
AgGradientLegendOptions: ['stop'],
AgHeatmapSeriesOptions: ['showInLegend'],
AgSunburstSeriesHighlightStyle: ['item', 'series'],
AgSunburstSeriesOptions: ['showInLegend'],
AgTreemapSeriesHighlightStyle: ['item', 'series'],
AgTreemapSeriesOptions: ['showInLegend'],
AgAngleCategoryAxisOptions: ['keys'],
AgAngleNumberAxisOptions: ['keys'],
AgRadiusCategoryAxisOptions: ['keys'],
AgRadiusNumberAxisOptions: ['keys'],
};

0 comments on commit 61951cd

Please sign in to comment.