Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/cli/cli/versions.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
- changelogEntry:
- summary: |
Improve performance of `fern docs dev` by only reloading the markdown content when
only markdown files are changed, avoiding unnecessary recompilation of the full docs.

type: fix
irVersion: 55
version: 0.50.17

- changelogEntry:
- summary: |
Improve performance of `fern docs dev` by debouncing across edits to multiple files,
Expand Down
41 changes: 39 additions & 2 deletions packages/cli/docs-preview/src/previewDocs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { readFile } from "fs/promises";
import { v4 as uuidv4 } from "uuid";

import { DocsDefinitionResolver, filterOssWorkspaces } from "@fern-api/docs-resolver";
Expand All @@ -13,27 +14,63 @@ import {
convertDbDocsConfigToRead,
convertDocsDefinitionToDb
} from "@fern-api/fdr-sdk";
import { convertToFernHostAbsoluteFilePath } from "@fern-api/fs-utils";
import { AbsoluteFilePath, convertToFernHostAbsoluteFilePath, relative } from "@fern-api/fs-utils";
import { IntermediateRepresentation } from "@fern-api/ir-sdk";
import { Project } from "@fern-api/project-loader";
import { convertIrToFdrApi } from "@fern-api/register";
import { TaskContext } from "@fern-api/task-context";

import { replaceReferencedMarkdown } from "../../docs-markdown-utils/src";

export async function getPreviewDocsDefinition({
domain,
project,
context
context,
previousDocsDefinition,
editedAbsoluteFilepaths
}: {
domain: string;
project: Project;
context: TaskContext;
previousDocsDefinition?: DocsV1Read.DocsDefinition;
editedAbsoluteFilepaths?: AbsoluteFilePath[];
}): Promise<DocsV1Read.DocsDefinition> {
const docsWorkspace = project.docsWorkspaces;
const apiWorkspaces = project.apiWorkspaces;
if (docsWorkspace == null) {
throw new Error("No docs workspace found in project");
}

if (editedAbsoluteFilepaths != null && previousDocsDefinition != null) {
const allMarkdownFiles = editedAbsoluteFilepaths.every(
(filepath) => filepath.endsWith(".mdx") || filepath.endsWith(".md")
);
for (const absoluteFilePath of editedAbsoluteFilepaths) {
const relativePath = relative(docsWorkspace.absoluteFilePath, absoluteFilePath);
const markdown = (await readFile(absoluteFilePath)).toString();
const processedMarkdown = await replaceReferencedMarkdown({
markdown,
absolutePathToFernFolder: docsWorkspace.absoluteFilePath,
absolutePathToMarkdownFile: absoluteFilePath,
context
});

const previousValue = previousDocsDefinition.pages[FdrAPI.PageId(relativePath)];
if (previousValue == null) {
continue;
}

previousDocsDefinition.pages[FdrAPI.PageId(relativePath)] = {
markdown: processedMarkdown,
editThisPageUrl: previousValue.editThisPageUrl
};
}

if (allMarkdownFiles) {
return previousDocsDefinition;
}
}

const fernWorkspaces = await Promise.all(
apiWorkspaces.map(
async (workspace) =>
Expand Down
14 changes: 11 additions & 3 deletions packages/cli/docs-preview/src/runPreviewServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
let isReloading = false;
const RELOAD_DEBOUNCE_MS = 1000;

const reloadDocsDefinition = async () => {
const reloadDocsDefinition = async (editedAbsoluteFilepaths?: AbsoluteFilePath[]) => {
context.logger.info("Reloading docs...");
const startTime = Date.now();
try {
Expand All @@ -136,7 +136,9 @@
const newDocsDefinition = await getPreviewDocsDefinition({
domain: `${instance.host}${instance.pathname}`,
project,
context
context,
previousDocsDefinition: docsDefinition,
editedAbsoluteFilepaths: editedAbsoluteFilepaths

Check failure on line 141 in packages/cli/docs-preview/src/runPreviewServer.ts

View workflow job for this annotation

GitHub Actions / eslint

Expected property shorthand
});
context.logger.info(`Reload completed in ${Date.now() - startTime}ms`);
return newDocsDefinition;
Expand Down Expand Up @@ -169,6 +171,8 @@
renameDetection: true
});

const editedAbsoluteFilepaths: AbsoluteFilePath[] = [];

// eslint-disable-next-line @typescript-eslint/no-misused-promises
watcher.on("all", async (event: string, targetPath: string, _targetPathNext: string) => {
context.logger.info(chalk.dim(`[${event}] ${targetPath}`));
Expand All @@ -178,6 +182,8 @@
return;
}

editedAbsoluteFilepaths.push(AbsoluteFilePath.of(targetPath));

// Clear any existing timer
if (reloadTimer != null) {
clearTimeout(reloadTimer);
Expand All @@ -192,11 +198,13 @@
type: "startReload"
});

const reloadedDocsDefinition = await reloadDocsDefinition();
const reloadedDocsDefinition = await reloadDocsDefinition(editedAbsoluteFilepaths);
if (reloadedDocsDefinition != null) {
docsDefinition = reloadedDocsDefinition;
}

editedAbsoluteFilepaths.length = 0;

sendData({
version: 1,
type: "finishReload"
Expand Down
Loading