facebook / facebook/docusaurus

Feature: Enable Plugin loadContent caching, improve plugin reload perf

オープン
#5,393 コメント 4 件 リアクション 1 件 担当者 0 名 GitHub で見る
feature
主要言語
TypeScript
スター
66.2k
フォーク
10k
平均マージ
1日 3時間
マージ済み PR(30日)
52

説明

## 🚀 Feature

This feature request will help to avoid slow builds/hot reloads by allowing plugin authors to cache effectively.

> Do note that this is a plugin author feature request and _not_ for the end-user.

### Have you read the [Contributing Guidelines on issues](https://github.com/facebook/docusaurus/blob/main/CONTRIBUTING.md#reporting-new-issues)?

Yes

### Has this been requested on [Canny](https://docusaurus.io/feedback)?

No

## Motivation

Plugin authors can utilize the `loadContent` life-cycle ([docs](https://docusaurus.io/docs/lifecycle-apis#async-loadcontent)) to async/sync load content needed for the plugin. However, this method is called _every time_ a file is changed while the development server is running.

Typically this is ok and _wanted_ functionality, but if the code within `loadContent` takes a considerable amount of time to process, then the entire experience is degraded. I ran into this while building [docusaurus-plugin-typedoc-api](https://github.com/milesj/docusaurus-plugin-typedoc-api/blob/master/packages/plugin/src/index.ts#L91), as the TypeDoc build process is rather slow (roughly 30 seconds).

To help alleviate this problem we can cache the long processes, _but_ there is no way to invalidate the cache, _or_ know when we should rebuild.

## API Design

My proposal is to pass a "build state" object to the `loadContent` life-cycle method. This object would contain the following properties:

- `firstLoad` (`boolean`) - A flag representing the 1st time `loadContent` is called. Triggered by both `build` and `start`. This will allow authors to effectively cache miss on new builds.
- `changedFiles` (`string[]`) - A list of files that have changed since the last rebuild/reload. This will allow authors to determine whether to cache hit/miss based on file paths/extensions.

Using my TypeDoc problem above, an example of this in practice would look something like.

```ts
async loadContent({ firstLoad, changedFiles }) {
const cachePath = path.join(context.generatedFilesDir, 'typedoc.json');
const hasTsFiles = changedFiles.some(file => file.match(/\.tsx?$/));

// Run TypeDoc and write to cache if first load or TS files have changed
if (firstLoad || hasTsFiles) {
await generateTypeDocJson(cachePath);
}

return import(cachePath);
}
```

## Have you tried building it?

No, not yet...

I have tried to detect whether a rebuild is happening, but there's no way to persist plugin state. For example, the following does not work, it always logs `1`.

```ts
export default function() {
let count = 0;

return {
async loadContent() {
count += 1;
console.log(count);
}
};
}
```

Have also looked into environment variables, but nothing related to rebuilds.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。