Skip to content

Commit

Permalink
add a "memory management" documentation page
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas committed Dec 6, 2023
1 parent 28a4289 commit 4e693f0
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 37 deletions.
106 changes: 69 additions & 37 deletions config/apiExtractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IConfigFile,
} from "@microsoft/api-extractor";
import { parseArgs } from "node:util";
import fs from "node:fs";

// @ts-ignore
import { map } from "./entryPoints.js";
Expand Down Expand Up @@ -40,37 +41,67 @@ const packageJsonFullPath = path.resolve(__dirname, "../package.json");

process.exitCode = 0;

map((entryPoint: { dirs: string[] }) => {
if (entryPoint.dirs.length > 0 && parsed.values["main-only"]) return;
const tempDir = fs.mkdtempSync("api-model");
try {
if (parsed.values.generate?.includes("docModel")) {
console.log(
"\n\nCreating API extractor docmodel for the a combination of all entry points"
);
const dist = path.resolve(__dirname, "../dist");
const entryPoints = map((entryPoint: { dirs: string[] }) => {
return `export * from "${dist}/${entryPoint.dirs.join("/")}/index.d.ts";`;
}).join("\n");
const entryPointFile = path.join(tempDir, "entry.d.ts");
fs.writeFileSync(entryPointFile, entryPoints);

buildReport(entryPointFile, "docModel");
}

const path = entryPoint.dirs.join("/");
const mainEntryPointFilePath =
`<projectFolder>/dist/${path}/index.d.ts`.replace("//", "/");
console.log(
"\n\nCreating API extractor report for " + mainEntryPointFilePath
);
if (parsed.values.generate?.includes("apiReport")) {
map((entryPoint: { dirs: string[] }) => {
const path = entryPoint.dirs.join("/");
const mainEntryPointFilePath =
`<projectFolder>/dist/${path}/index.d.ts`.replace("//", "/");
console.log(
"\n\nCreating API extractor report for " + mainEntryPointFilePath
);
buildReport(
mainEntryPointFilePath,
"apiReport",
`api-report${path ? "-" + path.replace(/\//g, "_") : ""}.md`
);
});
}
} finally {
fs.rmSync(tempDir, { recursive: true });
}

function buildReport(
mainEntryPointFilePath: string,
mode: "apiReport" | "docModel",
reportFileName = ""
) {
const configObject: IConfigFile = {
...(JSON.parse(JSON.stringify(baseConfig)) as IConfigFile),
mainEntryPointFilePath,
};

configObject.apiReport!.reportFileName = `api-report${
path ? "-" + path.replace(/\//g, "_") : ""
}.md`;

configObject.apiReport!.enabled =
parsed.values.generate?.includes("apiReport") || false;

configObject.docModel!.enabled =
parsed.values.generate?.includes("docModel") || false;

if (entryPoint.dirs.length !== 0) {
if (mode === "apiReport") {
configObject.apiReport!.enabled = true;
configObject.docModel = { enabled: false };
configObject.tsdocMetadata = { enabled: false };
configObject.messages!.extractorMessageReporting![
"ae-unresolved-link"
]!.logLevel = ExtractorLogLevel.None;
configObject.apiReport!.reportFileName = reportFileName;
} else {
configObject.docModel!.enabled = true;
configObject.apiReport = {
enabled: false,
// this has to point to an existing folder, otherwise the extractor will fail
// but it will not write the file
reportFileName: "disabled.md",
reportFolder: tempDir,
};
}

const extractorConfig = ExtractorConfig.prepare({
Expand All @@ -85,22 +116,23 @@ map((entryPoint: { dirs: string[] }) => {
});

let succeededAdditionalChecks = true;
const contents = readFileSync(extractorConfig.reportFilePath, "utf8");

if (contents.includes("rehackt")) {
succeededAdditionalChecks = false;
console.error(
"❗ %s contains a reference to the `rehackt` package!",
extractorConfig.reportFilePath
);
}
if (contents.includes('/// <reference types="react" />')) {
succeededAdditionalChecks = false;
console.error(
"❗ %s contains a reference to the global `React` type!/n" +
'Use `import type * as ReactTypes from "react";` instead',
extractorConfig.reportFilePath
);
if (fs.existsSync(extractorConfig.reportFilePath)) {
const contents = readFileSync(extractorConfig.reportFilePath, "utf8");
if (contents.includes("rehackt")) {
succeededAdditionalChecks = false;
console.error(
"❗ %s contains a reference to the `rehackt` package!",
extractorConfig.reportFilePath
);
}
if (contents.includes('/// <reference types="react" />')) {
succeededAdditionalChecks = false;
console.error(
"❗ %s contains a reference to the global `React` type!/n" +
'Use `import type * as ReactTypes from "react";` instead',
extractorConfig.reportFilePath
);
}
}

if (extractorResult.succeeded && succeededAdditionalChecks) {
Expand All @@ -115,4 +147,4 @@ map((entryPoint: { dirs: string[] }) => {
}
process.exitCode = 1;
}
});
}
49 changes: 49 additions & 0 deletions docs/source/caching/memory-management.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Memory management
api_doc:
- "@apollo/client!cacheSizes:var"
- "@apollo/client!CacheSizes:interface"
---

## Cache Sizes

For better performance, Apollo Client caches a lot of internally calculated values.
In most cases, these values are cached in WeakCaches, which means that if the
source object is garbage-collected, the cached value will be garbage-collected,
too.

Additionally, those caches are LRU caches, which means that if the cache is full,
the least recently used value will be garbage-collected.

Depending on your application you might want to tweak the cache size to fit your
needs.

You can do this in two ways:

### Setting Cache Sizes before loading the Apollo Client library

This is the recommended way to set the cache sizes, as it will allow you to set
cache sizes before the Apollo Client library is loaded (some caches will already
be initialized when the library is loaded, and changed cache sizes will only
affect caches created after the fact).

<DocPiece canonicalReference="@apollo/client!cacheSizes:var" example />

### Adjusting Cache Sizes after loading the Apollo Client library

You can also adjust cache sizes after loading the library.

```js
import { cacheSizes } from '@apollo/client/utilities';
import { print } from '@apollo/client'

cacheSizes.print = 100;
// cache sizes changed this way will only take effect for caches created after
// the cache size has been changed, so we need to reset the cache for it to be effective

print.reset();
```

### Cache Details

<InterfaceDetails canonicalReference="@apollo/client!CacheSizes:interface" />
1 change: 1 addition & 0 deletions docs/source/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"Reading and writing": "/caching/cache-interaction",
"Garbage collection and eviction": "/caching/garbage-collection",
"Customizing field behavior": "/caching/cache-field-behavior",
"Memory Management": "/caching/memory-management",
"Advanced topics": "/caching/advanced-topics"
},
"Pagination": {
Expand Down

0 comments on commit 4e693f0

Please sign in to comment.