docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

feat: add support for browser-based theme config file (docusaurus.theme.js)

Open OzakIOne opened this issue 2 years ago • 6 comments

Motivation

Add support for a new browser docusaurus.theme.tsx file to declare the Docusaurus theme config.

Using a browser-based file unlocks many other features, including the ability to pass unserializable data such as React components and callbacks.

Some features it unlocks, or improves the DX:

  • https://github.com/facebook/docusaurus/issues/7227
  • https://github.com/facebook/docusaurus/issues/4389
  • https://github.com/facebook/docusaurus/issues/2968
  • https://github.com/facebook/docusaurus/issues/4542
  • https://github.com/facebook/docusaurus/issues/9611

This feature is designed to be v3 retro-compatible and easy to adopt incrementally. The new theme config gets merged into the old serialized siteConfig.themeConfig and it's possible to slowly migrate your theme config to the new file.

Test Plan

unit tests + dogfood + preview

Test links

https://deploy-preview-9619--docusaurus-2.netlify.app/

OzakIOne avatar Dec 07 '23 16:12 OzakIOne

[V2]

Built without sensitive environment variables

Name Link
Latest commit 161c72729ef3151a0a50fd34f23e3b32a7c938b8
Latest deploy log https://app.netlify.com/sites/docusaurus-2/deploys/65858c5920ff8200085bedcc
Deploy Preview https://deploy-preview-9619--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.

netlify[bot] avatar Dec 07 '23 16:12 netlify[bot]

⚡️ Lighthouse report for the deploy preview of this PR

URL Performance Accessibility Best Practices SEO PWA Report
/ 🟠 69 🟢 98 🟢 100 🟢 100 🟠 89 Report
/docs/installation 🟢 90 🟢 98 🟢 100 🟢 100 🟠 89 Report
/docs/category/getting-started 🟠 76 🟢 100 🟢 100 🟢 90 🟠 89 Report
/blog 🟠 68 🟢 100 🟢 100 🟢 90 🟠 89 Report
/blog/preparing-your-site-for-docusaurus-v3 🟠 65 🟢 97 🟢 100 🟢 100 🟠 89 Report
/blog/tags/release 🟢 95 🟢 100 🟢 100 🟠 80 🟠 89 Report
/blog/tags 🟠 74 🟢 100 🟢 100 🟢 90 🟠 89 Report

github-actions[bot] avatar Dec 07 '23 16:12 github-actions[bot]

I'm not sure if this is the right design, but I also don't know if I have much to say.

We have always said "all config files you write are server-side; client-side customizations are to be done through swizzling and custom CSS". And indeed, I don't see how announcement/footer items can't be done through safe swizzling. This just seems like one extra way to do things.

Here this is not only theme customizations but also theme extensions. You shouldn't need to swizzle to provide custom mdx components, navbar items, or simply use callbacks to enable/disable navbar items.

Too often we encounter limits due to unserializable configs.

Swizzle remains the way to customize existing theme components, but here the goal is not really to customize existing components.

This design is already widely used by other tools, for example: https://nextra.site/docs/docs-theme/theme-configuration

slorber avatar Dec 07 '23 19:12 slorber

Okay, fair enough. One or two years ago, our plan was still to provide "dummy components" that one could swizzle and inject additional logic, but maybe this is fine too.

Josh-Cena avatar Dec 07 '23 22:12 Josh-Cena

Okay, fair enough. One or two years ago, our plan was still to provide "dummy components" that one could swizzle and inject additional logic, but maybe this is fine too.

As far as I remember, we decided that it was not needed to have such "dummy components" like BeforeBlogSidebar because swizzle wrap is a good alternative to add a component above/under an existing one. Swizzle remains a useful tool for these scenarios.


With this new proposal, the goal is to give another way to customize that is not super well covered by swizzle.

For example:

export default {
  navbar: {
    items: [
      {
        component: React.lazy(() => import("@site/components/navbar/MyNavbarItem")),
        props: { someProp: 42 },
        isActive: (params) => 
                   (params.location.pathname === "/" 
                   || (params.plugin.name === "docs" && params.plugin.id === "default"))
      },
    ],
  },
  mdxComponents: {
    a: React.lazy(() => import("@site/components/MyCustomMarkdownLink"))
    MyComp: React.lazy(() => import("@site/components/MyComp"))
  },
};

This should allow to integrate with Suspense and make it easier to code split and lazy load custom components on demand as user navigates, instead of loading all of them upfront eagerly.

slorber avatar Dec 08 '23 12:12 slorber