Skip to content

Conversation

@slorber
Copy link
Collaborator

@slorber slorber commented Oct 24, 2025

Docusaurus Faster

This PR is part of the Docusaurus Faster project aiming at reducing production build times


TLDR

Your site uses the showLastUpdateAuthor and showLastUpdateTime options of the docs/blog/page plugin?

It could build faster if you turn on Docusaurus Faster:

const siteConfig = {
  future: {
    experimental_faster: true,
  },
}

Alternatively, you can also use this option, which enables the same improvements:

const test = {
  future: {
    experimental_vcs: 'default-v2',
  },
}

The impact on build times can be significant for:

  • large repositories
  • large number of md/mdx files
  • large number of i18n locales

Problem

We want to improve site build performance.

It turns out that our "last updated at" feature is a real bottleneck.
For large sites, it leads to the inefficient execution of thousands of git log commands, delaying the plugin loadContent() phase significantly.

This performance bottleneck has been largely described here:

In this PR, we'll focus on solutions we implemented to overcome this perf bottleneck.


Solution

This PR implements:

  • siteConfig.future.experimental_vcs: an option to let you write your own VCS integration, defaulting to our historical Git-based implementation, with various VCS presets available out of the box
  • siteConfig.future.experimental_faster.gitEagerVcs: a future flag to turn on a new - much faster - git-based implementation that doesn't perform thousands of git log calls

New VCS API

We now have a new future.experimental_vcs site config option.

It lets you provide your own implementation to tell Docusaurus how to read the file creation / last update info of a given file.

For example, you could implement an "svn-ad-hoc" strategy yourself:

const siteConfig = {
  future: {
    experimental_vcs: {
      initialize: ({siteDir}) => {
		// nothing to initialize	
      },
      getFileCreationInfo: async (filePath: string) => {
        return getFileCreationInfoFromSVN(filePath)
      },
      getFileLastUpdateInfo: async (filePath: string) => {
        return getFileLastUpdateInfoFromSVN(filePath);
      },
    },
  },
};

Or implement an "svn-eager" strategy yourself:

function() {
  let svnRepo = null; 
  return {
    initialize: ({siteDir}) => {
      svnRepo = readFullSvnRepo(siteDir)
    },
    getFileCreationInfo: async (filePath: string) => {
      return svnRepo.getFileCreationInfo(filePath)
    },
    getFileLastUpdateInfo: async (filePath: string) => {
      return svnRepo.getFileLastUpdateInfo(filePath);
    },
  };
}

const siteConfig = {
  future: {
    experimental_vcs: createSvnEagerStrategy()
  },
};

You can also pass false to disable, or true (default) to enable the default Git strategy:

const test = {
  future: {
    experimental_vcs: true // Default
  },
}

The default strategy:

  • is based on Git in production builds
  • uses hardcoded values in dev/tests to speed up DX

It is also possible to pass VCS presets:

const test = {
  future: {
    experimental_vcs: "vcs-preset-name"
  },
}

The available presets are:

  • 'git-ad-hoc': the historical git log <filename> based strategy
  • 'git-eager': the new Git strategy that reads your whole repository upfront
  • 'hardcoded': returns hardcoded value, useful in dev/tests to speed up DX
  • 'disabled': returns null for all files, considering them untracked

We also have default strategies that are "dynamic" and delegate to the strategies above:

  • 'default-v1': the historical default ('git-ad-hoc' in prod, 'hardcoded' in dev)
  • 'default-v2': the upcoming default ('git-eager' in prod, 'hardcoded' in dev)

We recommend that most users use either true, 'default-v1' or 'default-v2'
Reading Git file info in dev can be expensive and can significantly slow down your dev server startup time.

Even simpler: just turn Docusaurus Faster on to leverage the new Git-based implementation. See below.

Docusaurus Faster - gitEagerVcs flag

The siteConfig.future.experimental_faster.gitEagerVcs flag will simply swap the default 'default-v1' to 'default-v2', replacing the git-ad-hoc impl in production builds by the git-eager strategy, while keeping hardcoded in dev).

const siteConfig = {
  future: {
    experimental_vcs: true, // defaults to either 'default-v1' or 'default-v2' depending on 'gitEagerVcs'
    experimental_faster: {
      gitEagerVcs: true
    },
  },
}

The simpler configuration I'd recommend is to turn on Docusaurus Faster globally:

const siteConfig = {
  future: {
    experimental_faster: true,
  },
}

Your site will now use the new 'default-v2' default VCS strategy by default.

If proven successful, this VCS strategy will become the new default in Docusaurus v4.


Benchmark

We are comparing the legacy (git-ad-hoc) vs the new (git-eager) VCS strategies on our own website.

We are using DOCUSAURUS_RETURN_AFTER_LOADING=true so that we only measure the site initial phase, skipping the bundling/SSG phases, so that we can measure more accurarely the perf improvement on the phase we aim to optimize.

yarn build:website:fast

Building our website for English only, with a limited subset of doc versions:

hyperfine \
--runs 5 \
'DOCUSAURUS_RETURN_AFTER_LOADING=true DOCUSAURUS_SITE_VCS=default-v1 yarn build:website:fast' \
'DOCUSAURUS_RETURN_AFTER_LOADING=true DOCUSAURUS_SITE_VCS=default-v2 yarn build:website:fast'

The new implementation is ~1.3x faster:

CleanShot 2025-11-14 at 16 37 08@2x

The result is significant, but not outstanding, because:

  • The legacy implementation only issues git log commands for a limited number of docs
  • The new implementation has to read entirely a large 10k commits repo

This is likely the worst-case scenario for the new implementation, and yet it performs faster.

yarn build:website --locale en

Building our website for English only:

hyperfine \
--runs 5 \
'DOCUSAURUS_RETURN_AFTER_LOADING=true DOCUSAURUS_SITE_VCS=default-v1 yarn build:website --locale en' \
'DOCUSAURUS_RETURN_AFTER_LOADING=true DOCUSAURUS_SITE_VCS=default-v2 yarn build:website --locale en'

The new implementation is ~2.8x faster:

CleanShot 2025-11-14 at 16 27 51@2x

From our tests, we believe the gap will likely increase even more with the number of docs and the size of your repository.

yarn build:website

Building our website for all locales:

hyperfine \
--runs 5 \
'DOCUSAURUS_RETURN_AFTER_LOADING=true DOCUSAURUS_SITE_VCS=default-v1 yarn build:website' \
'DOCUSAURUS_RETURN_AFTER_LOADING=true DOCUSAURUS_SITE_VCS=default-v2 yarn build:website'

The new implementation is 5.6x+ faster:

CleanShot 2025-11-14 at 16 31 35@2x

This result is even more impressive because we only read the Git repository eagerly once for the first locale. For all subsequent locales, we'll read the git file info data from the repository that we already read!

The new implementation is expected to speed up significantly i18n sites that build all the locales in a single docusaurus build run.
(ie, not using multiple docusaurus build --locale <currentLocale> calls)


What's next?

The new git-eager implementation is an initial experimental implementation.

It is possible that it doesn't work well for all sites, or perform as fast as it does on our own website. Please report us problems you have with this new implementation, and we'll improve it!

Please also note that this is an initial version: it should be possible to make it even more performant. For example, we could implement an incremental mode so that we only have to read the latest commits from your Git history, leading to more performant rebuilds (similar to bundler persistent caching).

e18e/ecosystem-issues#216


Test Plan

CI + unit tests + dogfood

Test links

@slorber slorber requested a review from Josh-Cena as a code owner October 24, 2025 16:39
@slorber slorber added the pr: new feature This PR adds a new API or behavior. label Oct 24, 2025
@meta-cla meta-cla bot added the CLA Signed Signed Facebook CLA label Oct 24, 2025
@netlify
Copy link

netlify bot commented Oct 24, 2025

[V2]

Name Link
🔨 Latest commit 2584288
🔍 Latest deploy log https://app.netlify.com/projects/docusaurus-2/deploys/69175eb179ebc8000811b433
😎 Deploy Preview https://deploy-preview-11512--docusaurus-2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link

github-actions bot commented Oct 24, 2025

Size Change: +23.4 kB (+0.2%)

Total Size: 11.8 MB

Filename Size Change
website/.docusaurus/docusaurus.config.mjs 28.9 kB +55 B (+0.19%)
website/build/assets/js/main.********.js 741 kB +35 B (0%)
website/build/docs/api/docusaurus-config.html 228 kB +23 kB (+11.25%) ⚠️
ℹ️ View Unchanged
Filename Size Change
website/.docusaurus/codeTranslations.json 2 B 0 B
website/.docusaurus/globalData.json 38.5 kB 0 B
website/.docusaurus/i18n.json 1.36 kB 0 B
website/.docusaurus/registry.js 176 kB 0 B
website/.docusaurus/routes.js 87.7 kB 0 B
website/.docusaurus/routesChunkNames.json 91.6 kB 0 B
website/.docusaurus/site-metadata.json 2.54 kB 0 B
website/build/assets/css/styles.********.css 141 kB 0 B
website/build/assets/js/runtime~main.********.js 38.9 kB 0 B
website/build/blog.html 77.1 kB 0 B
website/build/blog/2017/12/14/introducing-docusaurus.html 65.6 kB 0 B
website/build/blog/2018/04/30/How-I-Converted-Profilo-To-Docusaurus.html 44.9 kB +12 B (+0.03%)
website/build/blog/2018/09/11/Towards-Docusaurus-2.html 49.2 kB 0 B
website/build/blog/2018/12/14/Happy-First-Birthday-Slash.html 29.1 kB 0 B
website/build/blog/2019/12/30/docusaurus-2019-recap.html 40 kB -1 B (0%)
website/build/blog/2020/01/07/tribute-to-endi.html 32.6 kB 0 B
website/build/blog/2021/01/19/docusaurus-2020-recap.html 51.4 kB 0 B
website/build/blog/2021/03/09/releasing-docusaurus-i18n.html 47.4 kB -1 B (0%)
website/build/blog/2021/05/12/announcing-docusaurus-two-beta.html 48 kB 0 B
website/build/blog/2021/11/21/algolia-docsearch-migration.html 54.2 kB +12 B (+0.02%)
website/build/blog/2022/01/24/docusaurus-2021-recap.html 43.4 kB 0 B
website/build/blog/2022/08/01/announcing-docusaurus-2.0.html 132 kB 0 B
website/build/blog/2022/09/01/docusaurus-2.1.html 50.2 kB -1 B (0%)
website/build/blog/archive.html 23.5 kB 0 B
website/build/blog/authors.html 50.3 kB 0 B
website/build/blog/authors/j-marcey.html 70.2 kB 0 B
website/build/blog/authors/josh-cena.html 46.8 kB 0 B
website/build/blog/authors/lex-111.html 55.6 kB 0 B
website/build/blog/authors/slorber.html 80.6 kB 0 B
website/build/blog/authors/slorber/authors/2.html 80.8 kB 0 B
website/build/blog/authors/slorber/authors/3.html 83 kB 0 B
website/build/blog/authors/slorber/authors/4.html 97.5 kB 0 B
website/build/blog/authors/slorber/authors/5.html 42.3 kB 0 B
website/build/blog/authors/yangshun.html 66.1 kB 0 B
website/build/blog/authors/zpao.html 47.2 kB 0 B
website/build/blog/page/2.html 77.3 kB 0 B
website/build/blog/page/3.html 80.2 kB 0 B
website/build/blog/page/4.html 87.6 kB 0 B
website/build/blog/page/5.html 62.4 kB 0 B
website/build/blog/page/6.html 38 kB 0 B
website/build/blog/preparing-your-site-for-docusaurus-v3.html 126 kB +4 B (0%)
website/build/blog/releases/2.2.html 50.4 kB 0 B
website/build/blog/releases/2.3.html 60.7 kB 0 B
website/build/blog/releases/2.4.html 64.2 kB 0 B
website/build/blog/releases/3.0.html 105 kB 0 B
website/build/blog/releases/3.1.html 53.2 kB +1 B (0%)
website/build/blog/releases/3.2.html 48.9 kB 0 B
website/build/blog/releases/3.3.html 56 kB 0 B
website/build/blog/releases/3.4.html 55.2 kB +7 B (+0.01%)
website/build/blog/releases/3.5.html 57.9 kB +1 B (0%)
website/build/blog/releases/3.6.html 76.2 kB +1 B (0%)
website/build/blog/releases/3.7.html 50.7 kB +1 B (0%)
website/build/blog/releases/3.8.html 85.6 kB 0 B
website/build/blog/releases/3.9.html 60.5 kB 0 B
website/build/blog/tags.html 27.2 kB 0 B
website/build/blog/upgrading-frontend-dependencies-with-confidence-using-visual-regression-testing.html 123 kB 0 B
website/build/docs.html 48.4 kB 0 B
website/build/docs/advanced.html 30 kB 0 B
website/build/docs/advanced/architecture.html 29.5 kB +4 B (+0.01%)
website/build/docs/advanced/client.html 68.7 kB 0 B
website/build/docs/advanced/plugins.html 54.1 kB 0 B
website/build/docs/advanced/routing.html 69.2 kB +8 B (+0.01%)
website/build/docs/advanced/ssg.html 73.3 kB 0 B
website/build/docs/api/misc/@docusaurus/eslint-plugin.html 44.1 kB +4 B (+0.01%)
website/build/docs/api/misc/@docusaurus/eslint-plugin/no-html-links.html 35.6 kB 0 B
website/build/docs/api/misc/@docusaurus/eslint-plugin/no-untranslated-text.html 34.6 kB 0 B
website/build/docs/api/misc/@docusaurus/eslint-plugin/prefer-docusaurus-heading.html 35.9 kB +4 B (+0.01%)
website/build/docs/api/misc/@docusaurus/eslint-plugin/string-literal-i18n-messages.html 39.5 kB 0 B
website/build/docs/api/misc/@docusaurus/logger.html 38 kB 0 B
website/build/docs/api/misc/create-docusaurus.html 33.1 kB 0 B
website/build/docs/api/misc/docusaurus-init/index.html 361 B 0 B
website/build/docs/api/plugin-methods.html 64.3 kB +4 B (+0.01%)
website/build/docs/api/plugin-methods/extend-infrastructure.html 58.2 kB +4 B (+0.01%)
website/build/docs/api/plugin-methods/i18n-lifecycles.html 56.6 kB +4 B (+0.01%)
website/build/docs/api/plugin-methods/lifecycle-apis.html 158 kB 0 B
website/build/docs/api/plugin-methods/static-methods.html 43.9 kB +4 B (+0.01%)
website/build/docs/api/plugins.html 32.4 kB +4 B (+0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-client-redirects.html 59 kB +13 B (+0.02%)
website/build/docs/api/plugins/@docusaurus/plugin-content-blog.html 182 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-content-docs.html 189 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-content-pages.html 73.5 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-css-cascade-layers.html 46.8 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-debug.html 47.4 kB +12 B (+0.03%)
website/build/docs/api/plugins/@docusaurus/plugin-google-analytics.html 48.9 kB +3 B (+0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-google-gtag.html 48.4 kB -4 B (-0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-google-tag-manager.html 47.3 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-ideal-image.html 51.1 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-pwa.html 115 kB +4 B (0%)
website/build/docs/api/plugins/@docusaurus/plugin-rsdoctor.html 40.1 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-sitemap.html 64.8 kB +6 B (+0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-svgr.html 45.1 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-vercel-analytics.html 40.4 kB +12 B (+0.03%)
website/build/docs/api/themes.html 29.4 kB 0 B
website/build/docs/api/themes/@docusaurus/theme-classic.html 42.6 kB +4 B (+0.01%)
website/build/docs/api/themes/@docusaurus/theme-live-codeblock.html 35.8 kB +2 B (+0.01%)
website/build/docs/api/themes/@docusaurus/theme-mermaid.html 34.6 kB +4 B (+0.01%)
website/build/docs/api/themes/@docusaurus/theme-search-algolia.html 32.5 kB 0 B
website/build/docs/api/themes/configuration.html 247 kB 0 B
website/build/docs/blog.html 199 kB 0 B
website/build/docs/browser-support.html 46.9 kB 0 B
website/build/docs/category/getting-started.html 27 kB 0 B
website/build/docs/category/guides.html 35.6 kB 0 B
website/build/docs/cli.html 58.9 kB 0 B
website/build/docs/configuration.html 90.4 kB +7 B (+0.01%)
website/build/docs/create-doc.html 60.4 kB +3 B (0%)
website/build/docs/creating-pages.html 56.1 kB +1 B (0%)
website/build/docs/deployment.html 211 kB +5 B (0%)
website/build/docs/docs-introduction.html 49.7 kB 0 B
website/build/docs/docs-multi-instance.html 72.2 kB +4 B (+0.01%)
website/build/docs/docusaurus-core.html 220 kB 0 B
website/build/docs/guides/whats-next.html 32.3 kB 0 B
website/build/docs/i18n/crowdin.html 141 kB +12 B (+0.01%)
website/build/docs/i18n/git.html 75.9 kB +4 B (+0.01%)
website/build/docs/i18n/introduction.html 48.5 kB 0 B
website/build/docs/i18n/tutorial.html 162 kB 0 B
website/build/docs/installation.html 63.4 kB 0 B
website/build/docs/introduction/index.html 280 B 0 B
website/build/docs/markdown-features.html 78.7 kB 0 B
website/build/docs/markdown-features/admonitions.html 109 kB +4 B (0%)
website/build/docs/markdown-features/assets.html 85 kB +2 B (0%)
website/build/docs/markdown-features/code-blocks.html 216 kB +7 B (0%)
website/build/docs/markdown-features/diagrams.html 53.9 kB +9 B (+0.02%)
website/build/docs/markdown-features/head-metadata.html 50.2 kB 0 B
website/build/docs/markdown-features/links.html 40.4 kB +1 B (0%)
website/build/docs/markdown-features/math-equations.html 88.2 kB +4 B (0%)
website/build/docs/markdown-features/plugins.html 94.1 kB +8 B (+0.01%)
website/build/docs/markdown-features/react.html 131 kB 0 B
website/build/docs/markdown-features/tabs.html 137 kB 0 B
website/build/docs/markdown-features/toc.html 81.8 kB +4 B (0%)
website/build/docs/migration.html 38.2 kB +4 B (+0.01%)
website/build/docs/migration/v2.html 39 kB 0 B
website/build/docs/migration/v2/automated.html 39.4 kB 0 B
website/build/docs/migration/v2/manual.html 186 kB 0 B
website/build/docs/migration/v2/translated-sites.html 50.2 kB 0 B
website/build/docs/migration/v2/versioned-sites.html 59.1 kB +8 B (+0.01%)
website/build/docs/migration/v3.html 187 kB +2 B (0%)
website/build/docs/playground.html 31 kB 0 B
website/build/docs/resources/index.html 325 B 0 B
website/build/docs/search.html 121 kB +2 B (0%)
website/build/docs/seo.html 86.5 kB +13 B (+0.02%)
website/build/docs/sidebar.html 133 kB +1 B (0%)
website/build/docs/sidebar/autogenerated.html 144 kB 0 B
website/build/docs/sidebar/items.html 171 kB +1 B (0%)
website/build/docs/sidebar/multiple-sidebars.html 60.9 kB +4 B (+0.01%)
website/build/docs/static-assets.html 50.9 kB +4 B (+0.01%)
website/build/docs/styling-layout.html 134 kB +1 B (0%)
website/build/docs/support/index.html 319 B 0 B
website/build/docs/swizzling.html 109 kB +14 B (+0.01%)
website/build/docs/team/index.html 310 B 0 B
website/build/docs/typescript-support.html 59.1 kB +4 B (+0.01%)
website/build/docs/using-plugins.html 104 kB 0 B
website/build/docs/versioning.html 90.1 kB -2 B (0%)
website/build/index.html 35.3 kB 0 B

compressed-size-action::DOCUSAURUS_INFRA_FASTER

@github-actions
Copy link

github-actions bot commented Oct 24, 2025

⚡️ Lighthouse report for the deploy preview of this PR

URL Performance Accessibility Best Practices SEO Report
/ 🔴 45 🟢 98 🟢 100 🟢 100 Report
/docs/installation 🟠 55 🟢 97 🟢 100 🟢 100 Report
/docs/category/getting-started 🟠 70 🟢 100 🟢 100 🟠 86 Report
/blog 🟠 56 🟢 96 🟢 100 🟠 86 Report
/blog/preparing-your-site-for-docusaurus-v3 🟠 67 🟢 92 🟢 100 🟢 100 Report
/blog/tags/release 🟠 68 🟢 96 🟢 100 🟠 86 Report
/blog/tags 🟠 59 🟢 100 🟢 100 🟠 86 Report

@github-actions
Copy link

github-actions bot commented Oct 24, 2025

Size Change: +24 kB (+0.2%)

Total Size: 12.3 MB

Filename Size Change
website/.docusaurus/docusaurus.config.mjs 28.9 kB +56 B (+0.19%)
website/build/assets/css/styles.********.css 133 kB -34 B (-0.03%)
website/build/assets/js/main.********.js 743 kB +35 B (0%)
website/build/docs/api/docusaurus-config.html 236 kB +23.7 kB (+11.14%) ⚠️
ℹ️ View Unchanged
Filename Size Change
website/.docusaurus/codeTranslations.json 2 B 0 B
website/.docusaurus/globalData.json 38.5 kB 0 B
website/.docusaurus/i18n.json 1.36 kB 0 B
website/.docusaurus/registry.js 176 kB 0 B
website/.docusaurus/routes.js 87.7 kB 0 B
website/.docusaurus/routesChunkNames.json 91.6 kB 0 B
website/.docusaurus/site-metadata.json 2.38 kB 0 B
website/build/assets/js/runtime~main.********.js 38.8 kB 0 B
website/build/blog.html 79.9 kB 0 B
website/build/blog/2017/12/14/introducing-docusaurus.html 67.7 kB 0 B
website/build/blog/2018/04/30/How-I-Converted-Profilo-To-Docusaurus.html 46.8 kB +12 B (+0.03%)
website/build/blog/2018/09/11/Towards-Docusaurus-2.html 51.3 kB 0 B
website/build/blog/2018/12/14/Happy-First-Birthday-Slash.html 30.7 kB 0 B
website/build/blog/2019/12/30/docusaurus-2019-recap.html 41.9 kB -1 B (0%)
website/build/blog/2020/01/07/tribute-to-endi.html 34.3 kB 0 B
website/build/blog/2021/01/19/docusaurus-2020-recap.html 53.5 kB 0 B
website/build/blog/2021/03/09/releasing-docusaurus-i18n.html 49.4 kB -1 B (0%)
website/build/blog/2021/05/12/announcing-docusaurus-two-beta.html 50.1 kB 0 B
website/build/blog/2021/11/21/algolia-docsearch-migration.html 56.5 kB +12 B (+0.02%)
website/build/blog/2022/01/24/docusaurus-2021-recap.html 45.3 kB 0 B
website/build/blog/2022/08/01/announcing-docusaurus-2.0.html 137 kB 0 B
website/build/blog/2022/09/01/docusaurus-2.1.html 52.5 kB -1 B (0%)
website/build/blog/archive.html 24.9 kB 0 B
website/build/blog/authors.html 52.5 kB 0 B
website/build/blog/authors/j-marcey.html 72.9 kB 0 B
website/build/blog/authors/josh-cena.html 48.9 kB 0 B
website/build/blog/authors/lex-111.html 57.9 kB 0 B
website/build/blog/authors/slorber.html 83.5 kB 0 B
website/build/blog/authors/slorber/authors/2.html 83.7 kB 0 B
website/build/blog/authors/slorber/authors/3.html 85.9 kB 0 B
website/build/blog/authors/slorber/authors/4.html 101 kB 0 B
website/build/blog/authors/slorber/authors/5.html 44.2 kB 0 B
website/build/blog/authors/yangshun.html 68.8 kB 0 B
website/build/blog/authors/zpao.html 49.3 kB 0 B
website/build/blog/page/2.html 80 kB 0 B
website/build/blog/page/3.html 83 kB 0 B
website/build/blog/page/4.html 90.5 kB 0 B
website/build/blog/page/5.html 64.8 kB 0 B
website/build/blog/page/6.html 39.8 kB 0 B
website/build/blog/preparing-your-site-for-docusaurus-v3.html 130 kB -1 B (0%)
website/build/blog/releases/2.2.html 52.6 kB 0 B
website/build/blog/releases/2.3.html 63.2 kB 0 B
website/build/blog/releases/2.4.html 67 kB 0 B
website/build/blog/releases/3.0.html 109 kB 0 B
website/build/blog/releases/3.1.html 55.3 kB +1 B (0%)
website/build/blog/releases/3.2.html 51.1 kB 0 B
website/build/blog/releases/3.3.html 58.4 kB 0 B
website/build/blog/releases/3.4.html 57.5 kB +7 B (+0.01%)
website/build/blog/releases/3.5.html 60.3 kB +1 B (0%)
website/build/blog/releases/3.6.html 79.2 kB +1 B (0%)
website/build/blog/releases/3.7.html 53 kB +1 B (0%)
website/build/blog/releases/3.8.html 88.7 kB 0 B
website/build/blog/releases/3.9.html 63 kB 0 B
website/build/blog/tags.html 29 kB 0 B
website/build/blog/upgrading-frontend-dependencies-with-confidence-using-visual-regression-testing.html 127 kB 0 B
website/build/docs.html 50.3 kB 0 B
website/build/docs/advanced.html 31.5 kB 0 B
website/build/docs/advanced/architecture.html 31 kB +4 B (+0.01%)
website/build/docs/advanced/client.html 71.4 kB 0 B
website/build/docs/advanced/plugins.html 56.3 kB 0 B
website/build/docs/advanced/routing.html 71.8 kB +8 B (+0.01%)
website/build/docs/advanced/ssg.html 76.4 kB 0 B
website/build/docs/api/misc/@docusaurus/eslint-plugin.html 46.4 kB +4 B (+0.01%)
website/build/docs/api/misc/@docusaurus/eslint-plugin/no-html-links.html 37.5 kB 0 B
website/build/docs/api/misc/@docusaurus/eslint-plugin/no-untranslated-text.html 36.4 kB 0 B
website/build/docs/api/misc/@docusaurus/eslint-plugin/prefer-docusaurus-heading.html 37.6 kB +4 B (+0.01%)
website/build/docs/api/misc/@docusaurus/eslint-plugin/string-literal-i18n-messages.html 41.4 kB 0 B
website/build/docs/api/misc/@docusaurus/logger.html 39.7 kB 0 B
website/build/docs/api/misc/create-docusaurus.html 34.7 kB 0 B
website/build/docs/api/misc/docusaurus-init/index.html 361 B 0 B
website/build/docs/api/plugin-methods.html 66.7 kB +4 B (+0.01%)
website/build/docs/api/plugin-methods/extend-infrastructure.html 60.5 kB +4 B (+0.01%)
website/build/docs/api/plugin-methods/i18n-lifecycles.html 58.8 kB +4 B (+0.01%)
website/build/docs/api/plugin-methods/lifecycle-apis.html 163 kB 0 B
website/build/docs/api/plugin-methods/static-methods.html 45.8 kB +4 B (+0.01%)
website/build/docs/api/plugins.html 34 kB +4 B (+0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-client-redirects.html 61.7 kB +13 B (+0.02%)
website/build/docs/api/plugins/@docusaurus/plugin-content-blog.html 191 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-content-docs.html 197 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-content-pages.html 77.2 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-css-cascade-layers.html 49 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-debug.html 49.6 kB +12 B (+0.02%)
website/build/docs/api/plugins/@docusaurus/plugin-google-analytics.html 51.2 kB +3 B (+0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-google-gtag.html 50.7 kB -4 B (-0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-google-tag-manager.html 49.5 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-ideal-image.html 53.6 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-pwa.html 120 kB +4 B (0%)
website/build/docs/api/plugins/@docusaurus/plugin-rsdoctor.html 42.1 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-sitemap.html 67.7 kB +6 B (+0.01%)
website/build/docs/api/plugins/@docusaurus/plugin-svgr.html 47.2 kB 0 B
website/build/docs/api/plugins/@docusaurus/plugin-vercel-analytics.html 42.4 kB +12 B (+0.03%)
website/build/docs/api/themes.html 30.9 kB 0 B
website/build/docs/api/themes/@docusaurus/theme-classic.html 44.7 kB +4 B (+0.01%)
website/build/docs/api/themes/@docusaurus/theme-live-codeblock.html 37.6 kB +2 B (+0.01%)
website/build/docs/api/themes/@docusaurus/theme-mermaid.html 36.3 kB +4 B (+0.01%)
website/build/docs/api/themes/@docusaurus/theme-search-algolia.html 34.1 kB 0 B
website/build/docs/api/themes/configuration.html 259 kB 0 B
website/build/docs/blog.html 205 kB 0 B
website/build/docs/browser-support.html 49.2 kB 0 B
website/build/docs/category/getting-started.html 28.4 kB 0 B
website/build/docs/category/guides.html 37.4 kB 0 B
website/build/docs/cli.html 62.3 kB 0 B
website/build/docs/configuration.html 93.9 kB +7 B (+0.01%)
website/build/docs/create-doc.html 62.9 kB +3 B (0%)
website/build/docs/creating-pages.html 58.5 kB +1 B (0%)
website/build/docs/deployment.html 218 kB +5 B (0%)
website/build/docs/docs-introduction.html 52 kB 0 B
website/build/docs/docs-multi-instance.html 75.4 kB +4 B (+0.01%)
website/build/docs/docusaurus-core.html 228 kB 0 B
website/build/docs/guides/whats-next.html 34 kB 0 B
website/build/docs/i18n/crowdin.html 146 kB +12 B (+0.01%)
website/build/docs/i18n/git.html 79.2 kB +4 B (+0.01%)
website/build/docs/i18n/introduction.html 50.7 kB 0 B
website/build/docs/i18n/tutorial.html 168 kB 0 B
website/build/docs/installation.html 66.1 kB 0 B
website/build/docs/introduction/index.html 280 B 0 B
website/build/docs/markdown-features.html 81.6 kB 0 B
website/build/docs/markdown-features/admonitions.html 113 kB +4 B (0%)
website/build/docs/markdown-features/assets.html 89 kB +2 B (0%)
website/build/docs/markdown-features/code-blocks.html 224 kB +7 B (0%)
website/build/docs/markdown-features/diagrams.html 56.4 kB +9 B (+0.02%)
website/build/docs/markdown-features/head-metadata.html 52.6 kB 0 B
website/build/docs/markdown-features/links.html 42.4 kB +1 B (0%)
website/build/docs/markdown-features/math-equations.html 92.1 kB +4 B (0%)
website/build/docs/markdown-features/plugins.html 97.7 kB +8 B (+0.01%)
website/build/docs/markdown-features/react.html 136 kB 0 B
website/build/docs/markdown-features/tabs.html 143 kB 0 B
website/build/docs/markdown-features/toc.html 85.3 kB +4 B (0%)
website/build/docs/migration.html 40.1 kB -1 B (0%)
website/build/docs/migration/v2.html 40.8 kB 0 B
website/build/docs/migration/v2/automated.html 41.3 kB 0 B
website/build/docs/migration/v2/manual.html 193 kB 0 B
website/build/docs/migration/v2/translated-sites.html 52.4 kB 0 B
website/build/docs/migration/v2/versioned-sites.html 61.5 kB +8 B (+0.01%)
website/build/docs/migration/v3.html 194 kB +2 B (0%)
website/build/docs/playground.html 32.6 kB 0 B
website/build/docs/resources/index.html 325 B 0 B
website/build/docs/search.html 125 kB +2 B (0%)
website/build/docs/seo.html 90.3 kB +13 B (+0.01%)
website/build/docs/sidebar.html 139 kB +1 B (0%)
website/build/docs/sidebar/autogenerated.html 149 kB 0 B
website/build/docs/sidebar/items.html 177 kB +1 B (0%)
website/build/docs/sidebar/multiple-sidebars.html 63.9 kB +4 B (+0.01%)
website/build/docs/static-assets.html 53.3 kB +4 B (+0.01%)
website/build/docs/styling-layout.html 139 kB +1 B (0%)
website/build/docs/support/index.html 319 B 0 B
website/build/docs/swizzling.html 113 kB +14 B (+0.01%)
website/build/docs/team/index.html 310 B 0 B
website/build/docs/typescript-support.html 61.6 kB +4 B (+0.01%)
website/build/docs/using-plugins.html 108 kB 0 B
website/build/docs/versioning.html 93.8 kB -2 B (0%)
website/build/index.html 36.9 kB 0 B

compressed-size-action::DOCUSAURUS_INFRA_SLOWER

@slorber slorber changed the title feat(core): Add siteConfig.future.experimental_vcs API to read file metadata from Git & other systems feat(core): New siteConfig future.experimental_vcs API + future.experimental_faster.gitEagerVcs flag Nov 14, 2025
@slorber slorber mentioned this pull request Nov 14, 2025
@felipecrs
Copy link
Contributor

felipecrs commented Nov 14, 2025

@slorber do you mind if I suggest a test case?

my-docusaurus-site/
├── .git/
├── package.json
├── docusaurus.config.js
└── external-docs/      <-- an inner repository, could be a git submodule
    ├── .git/
    ├── README.md
    └── docs/
        ├── intro.md
        ├── guide.md
        └── tutorials/
            └── how-to.md

When scanning for the how-to.md update date, it should be looked from the inner repository's, because otherwise the file is untracked for the parent repository's.

PS: I have not read your implementation entirely, maybe you already account for it.

@slorber
Copy link
Collaborator Author

slorber commented Nov 14, 2025

@slorber do you mind if I suggest a test case?

my-docusaurus-site/
├── .git/
├── package.json
├── docusaurus.config.js
└── external-docs/      <-- a repository inside the repository, like a git submodule
    ├── .git/
    ├── README.md
    └── docs/
        ├── intro.md
        ├── guide.md
        └── tutorials/
            └── how-to.md

When scanning for the how-to.md update date, it should be looked from that repository's root, otherwise the file will is untracked from the parent repository's point of view.

PS: I have not read your implementation entirely, maybe you already account for it.

@felipecrs I have implemented something that should work for your case. It assumes that you are using git submodules, which afaik is your case.

The logic looks like this:

  • Find the "superproject"
  • Find all its submodules
  • Read all the repositories (superproject + its submodules)
  • Create an aggregated map of known tracked files
async function loadAllGitFilesInfoMap(cwd: string): Promise<GitFileInfoMap> {
  const roots = await PerfLogger.async('Reading Git root dirs', () =>
    getGitAllRepoRoots(cwd),
  );

  const allMaps: GitFileInfoMap[] = await Promise.all(
    roots.map(async (root) => {
      const map = await PerfLogger.async(
        `Reading Git history for repo ${logger.path(basename(root))}`,
        () => getGitRepositoryFilesInfo(root),
      );
      return resolveFileInfoMapPaths(root, map);
    }),
  );

  return mergeFileMaps(allMaps);
}

We have tests covering that. However, if you use nested Git repositories without submodules, we do not support that yet, but we could improve it later to support more cases.

It seems not so easy to implement a getGitAllRepoRoots() function that covers all esoteric Git setups. I am not a Git expert, unfortunately 😅 But I think the current implementation should work for a majority of websites that are either using a single Git repository, or a superproject with submodules.


Note that you can provide your own implementation. If the "git-eager" one doesn't work for you, it's now possible to implement in userland, and show us your working implementation that we could eventually add to Docusaurus core later.

What I mean is: it doesn't have to be perfect, and we can ship this PR in its current state:

  • the new implementation is opt-in: you can keep using the old one if the new one doesn't wort (yet)
  • you are not entirely blocked and can write your own VCS implementation to show us the way

I'm going to merge this PR asap, but I am willing to keep improving from the initial "git-eager" strategy implementation!


I have used this Git superproject as a test case: https://github.com/slorber/docusaurus-git-submodules-tests

It contains 3 large submodule repositories: Docusaurus, React Native, React Native Website.

The current implementation is able to read over 50k commits and retrieve a map of 45k file infos over the 3 repositories in ~3s on my Mac M3 (ran in parallel with other Docusaurus things loading).

@slorber slorber merged commit acc66c1 into main Nov 14, 2025
45 checks passed
@slorber slorber deleted the slorber/last-update-api branch November 14, 2025 17:15
@felipecrs
Copy link
Contributor

That's cool, thanks for considering it upfront.

I don't use git submodules though, I just have automation to clone the repositories at their latest revisions in a git-ignored sub-directory of my website repository.

I also have automation to initialize multiple branches of the same repository in different sub-directories, as the source from my versioned docs come from those branches (you may recall from #11288).

But maybe I can suggest a simpler approach (not in TS, sorry):

$ git clone https://gerrit.googlesource.com/gerrit --recurse-submodules
$ find . -name .git \( -type d -o -type f \) -prune -exec sh -c 'git -C "$(dirname "$1")" rev-parse --show-toplevel 2>/dev/null' -- {} \;
/home/felipecrs/repos/gerrit/plugins/delete-project
/home/felipecrs/repos/gerrit/plugins/replication
/home/felipecrs/repos/gerrit/plugins/gitiles
/home/felipecrs/repos/gerrit/plugins/singleusergroup
/home/felipecrs/repos/gerrit/plugins/commit-message-length-validator
/home/felipecrs/repos/gerrit/plugins/webhooks
/home/felipecrs/repos/gerrit/plugins/download-commands
/home/felipecrs/repos/gerrit/plugins/reviewnotes
/home/felipecrs/repos/gerrit/plugins/plugin-manager
/home/felipecrs/repos/gerrit/plugins/codemirror-editor
/home/felipecrs/repos/gerrit/plugins/hooks
/home/felipecrs/repos/gerrit/polymer-bridges
/home/felipecrs/repos/gerrit
/home/felipecrs/repos/gerrit/modules/jgit
/home/felipecrs/repos/gerrit/modules/java-prettify

Which should work for any case, regardless of submodules, worktrees, or not. It would even work for recursive submodules (which I suppose you have not accounted for yet).

And it's probably fast enough. :)

@slorber
Copy link
Collaborator Author

slorber commented Nov 14, 2025

I'm open to improving the implementation, so if you want to write a PR please do ;)

We also need to support Windows and other OS, so we need to ensure the implementation works across all OS.

Also, this logic to "find" the repositories should rather be fast: we don't want to slow down the most common scenario (single Git repo) to cover the 1% advanced needs. If we can't find a sensible default implementation, it may be better to offer a "composable" approach that lets you provide a hardcoded list of Git roots instead of detecting those.

@felipecrs
Copy link
Contributor

Or maybe some lazy load approach: if discovering date for a given file fails, check if it has its own repository. If it does, scan that repository as well.

I'm open to improving the implementation, so if you want to write a PR please do ;)

Right. Maybe someday. For now anyway there is git-ad-hoc, which works for me.

@slorber
Copy link
Collaborator Author

slorber commented Nov 14, 2025

Or maybe some lazy load approach: if discovering date for a given file fails, check if it has its own repository. If it does, scan that repository as well.

I thought about that kind of implementation, but IMHO it's not ideal because it is likely to lead to a lot of useless commands for untracked files.

We have plugins that codegen MDX lots of MDX files (often from OpenAPI schemas, for example), and those files are untracked. We can't run one or more shell commands for each of these files, so the implementation needs to be more clever to skip useless work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Signed Facebook CLA pr: new feature This PR adds a new API or behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants