Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add new plugin allContentLoaded lifecycle #9931

Merged
merged 8 commits into from
Mar 8, 2024

Conversation

slorber
Copy link
Collaborator

@slorber slorber commented Mar 8, 2024

Important: this feature is considered experimental, and is for now undocumented. Please only use it on your own site plugins, and avoid publishing third-party Docusaurus plugins on npm relying on this lifecycle.

Motivation

Introducing a new allContentLoaded({allContent, actions}) plugin lifecycle offers the opportunity for plugins to consume data coming from other plugins.

This means you can create a plugin aggregating data from multiple plugins/instances, and display that information on a single page. For example, you could use this to create your site homepage and display some docs-related and blog-related info.

If your plugin has both a contentLoaded and allContentLoaded lifecycles, the routes and global data created by both will be shallowly merged.

const plugin = () => ({
  name: "plugin-name",
  loadContent: () => ({val: 42})
  contentLoaded({ actions, content }) {
    actions.addRoute({
      path: "/path1",
      component: "Comp",
    });
    actions.setGlobalData({
      val1: content.val, 
      shared: content.val,
    });
  },
  allContentLoaded({ actions }) {
    actions.addRoute({
      path: "/path2",
      component: "Comp",
    });
    actions.setGlobalData({
      val2: content.val * 2, 
      shared: content.val * 2,
    });
  },
});

In this case the plugin will have:

  • routes /path1 and /path2
  • global data: {val1: 42, val2: 84, shared: 84}

Limitation: this new lifecycle does not permit to display data from one plugin inside another's page. You can aggregate data for a new brand-new standalone page (such as your homepage), but you cannot display blog posts on a doc page for example. We will try to enable that use case later. Note it remains possible to implement a workaround to extend existing plugins: #4138

Note: technically the existing contentLoaded already received the allContent, but it was a secret undocumented feature (only used by our debug plugin) that is now replaced by this brand-new lifecycle. I won't consider this as a breaking change.

An important motivation for this new lifecycle is also the optimization of the dev server (#9903), to provide fine-grained plugin reloads and to avoid wasting CPU/IO running uselessly expensive lifecycles such as contentLoaded just because they could eventually read the former allContent data.

Test Plan

unit tests + dogfood on the debug plugin

Test links

Related issues/PRs

Unlocks further DX optimizations: #9903

Related discussions: #9922 (reply in thread)

The allContent data was added to the contentLoaded params as part of #3229


Example

Reading this PR it might be complex to understand how to aggregate data from multiple plugins on a single page.

Here's an example aggregating the blog posts of 2 separate blogs into a single page.

https://stackblitz.com/edit/github-agngt8?file=MyHomePage%2FMyHomePagePlugin.js,MyHomePage%2FMyHomePage.js,docusaurus.config.js

CleanShot 2024-03-14 at 16 28 14@2x

export default async function MyHomePagePlugin(context, options) {
  return {
    name: 'my-home-page-plugin',
    async allContentLoaded({ allContent, actions }) {

      // We aggregate the 2 blog lists into 1 here
      const allBlogs = allContent['docusaurus-plugin-content-blog'];
      const blog1 = allBlogs['blog1'];
      const blog2 = allBlogs['blog2'];
      const allBlogPosts = [...blog1.blogPosts, ...blog2.blogPosts];

      // We create the route for the homepage here
      actions.addRoute({
        path: '/',
        exact: true,
        component: '@site/MyHomePage/MyHomePage.js',
        modules: {
          // "allBlogPosts" is the name of the React props the component will receive
          allBlogPosts: await actions.createData(
            'allBlogPosts.json', // The file name doesn't matter, we'll simplify this soon
            JSON.stringify(allBlogPosts)
          ),
        },
      });
    },
  };
}
export default function Home(props) {
  // We receive the created module as a prop here
  const { allBlogPosts } = props;
  return (
      <main>
        <h2>All blog posts</h2>
        <ul>
          {allBlogPosts.map((blogPost, i) => (
            <li key={i}>{blogPost.metadata.title}</li>
          ))}
        </ul>
      </main>
  );
}

IMPORTANT: be sure to understand the limits of the current approach. You can create a brand new page on which you display data of multiple plugins, but you can't inject data on an existing page created by an existing plugin. For example it's not possible to show blog posts on a doc page, or to show docs versions on a blog post, because it's not your plugin that creates those pages.

The solution to this problem will be adding support for React Server Components, so that you can access allContent directly in your React render tree instead of having to create a plugin. Track #9089

@slorber slorber added pr: new feature This PR adds a new API or behavior. to backport This PR is planned to be backported to a stable version of Docusaurus labels Mar 8, 2024
@slorber slorber requested a review from Josh-Cena as a code owner March 8, 2024 17:22
@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label Mar 8, 2024
@slorber slorber added the Argos Add this label to run UI visual regression tests. See argos.yml GH action. label Mar 8, 2024
Copy link

netlify bot commented Mar 8, 2024

[V2]

Name Link
🔨 Latest commit 5e64950
🔍 Latest deploy log https://app.netlify.com/sites/docusaurus-2/deploys/65eb4e15c5c50e00080b5ce2
😎 Deploy Preview https://deploy-preview-9931--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 site configuration.

Copy link

github-actions bot commented Mar 8, 2024

⚡️ Lighthouse report for the deploy preview of this PR

URL Performance Accessibility Best Practices SEO PWA Report
/ 🟠 60 🟢 98 🟢 96 🟢 100 🟠 88 Report
/docs/installation 🟠 56 🟢 96 🟢 100 🟢 100 🟠 88 Report
/docs/category/getting-started 🟠 74 🟢 100 🟢 100 🟢 90 🟠 88 Report
/blog 🟠 68 🟢 100 🟢 100 🟢 90 🟠 88 Report
/blog/preparing-your-site-for-docusaurus-v3 🟠 64 🟢 96 🟢 100 🟢 100 🟠 88 Report
/blog/tags/release 🟠 69 🟢 100 🟢 100 🟠 80 🟠 88 Report
/blog/tags 🟠 75 🟢 100 🟢 100 🟢 90 🟠 88 Report

Copy link

argos-ci bot commented Mar 8, 2024

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No change detected - Mar 8, 2024, 5:51 PM

Copy link

github-actions bot commented Mar 8, 2024

Size Change: 0 B

Total Size: 992 kB

ℹ️ View Unchanged
Filename Size
website/.docusaurus/globalData.json 75.4 kB
website/build/assets/css/styles.********.css 114 kB
website/build/assets/js/main.********.js 765 kB
website/build/index.html 37.9 kB

compressed-size-action

@slorber slorber merged commit 8d115a9 into main Mar 8, 2024
32 checks passed
@slorber slorber deleted the slorber/allContentLoaded branch March 8, 2024 18:14
diemol added a commit to saucelabs/elemental-next that referenced this pull request Apr 12, 2024
diemol added a commit to saucelabs/elemental-next that referenced this pull request Apr 12, 2024
* fix(deps): update docusaurus monorepo to v3.2.1

* Fix breaking change caused by facebook/docusaurus#9931

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Diego Molina <diemol@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Argos Add this label to run UI visual regression tests. See argos.yml GH action. CLA Signed Signed Facebook CLA pr: new feature This PR adds a new API or behavior. to backport This PR is planned to be backported to a stable version of Docusaurus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants