facebook / facebook/docusaurus

Feature: Enable Plugin loadContent caching, improve plugin reload perf

Aperta
#5,393 4 commenti 1 reazione 0 assegnatari Vedi su GitHub
feature
Lingua principale
TypeScript
Stelle
66.2k
Fork
10k
Merge medio
1g 3h
PR unite (30g)
52

Descrizione

## 🚀 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.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.