docusaurus修改Sidebar自定义时遇到的错误和解决方法

292 阅读2分钟

本意是修改如下的sidebar文件,根据浏览器网址提取docs id, 来为每个docs 实例添加对应的主题图片,

src_theme\DocSidebar\Desktop\Content\index.tsx

function ImageComponent() {
  const url = new URL(window.location.href);
  const pathname = decodeURIComponent(url.pathname);
  const keywordsToImages = {
    NBA: {
      imagePath: "/img/logo-nba.png",
      altText: "NBA Logo",
    },
    NASA: {
      imagePath: "/img/logo-nasa.jpg",
      altText: "NASA Logo",
    },
    // 继续添加其他关键词和对应的图片信息
  };

  for (const keyword in keywordsToImages) {
    if (pathname.includes(keyword)) {
      const { imagePath, altText } = keywordsToImages[keyword];

      return (
        <div>
          <img src={imagePath} alt={altText} style={{width:'80px',height:'80px'}}/>
        </div>
      );
    }
  }

  return <div>未找到对应的图片</div>;
}

在本地npm start测试环境下,一切正常,但是在npm run build时,提示错误:

image.png

[INFO] It looks like you are using code that should run on the client-side only. To get around it, try using <BrowserOnly> (docusaurus.io/docs/docusa…) or ExecutionEnvironment (docusaurus.io/docs/docusa…). It might also require to wrap your client code in useEffect hook and/or import a third-party library dynamically (if any). [ERROR] Docusaurus server-side rendering could not render static page with path

根据错误信息,你在使用Docusaurus构建项目时遇到了一个问题。错误信息指出你的代码包含应该只在客户端运行的部分。为了解决这个问题,可以尝试以下几种方法:

  1. 使用<BrowserOnly>组件:根据错误信息提供的链接,你可以使用Docusaurus提供的<BrowserOnly>组件来包裹只在浏览器端执行的代码。将你的ImageComponent组件放在<BrowserOnly>组件中,确保它只在浏览器环境下执行。
import BrowserOnly from '@docusaurus/BrowserOnly';

function ImageComponent() {
  return (
    <BrowserOnly fallback={<div>Loading...</div>}>
      {/* 在这里放置你的 ImageComponent 代码 */}
    </BrowserOnly>
  );
}
  1. 使用ExecutionEnvironment:另一种解决方法是使用Docusaurus提供的ExecutionEnvironment工具。你可以在ImageComponent代码中引入ExecutionEnvironment,然后根据执行环境条件执行代码。
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';

function ImageComponent() {
  if (ExecutionEnvironment.canUseDOM) {
    // 在这里放置只在客户端执行的代码
  } else {
    // 在这里放置只在服务器端执行的代码
  }
}

我选择了使用第1种方法来修改

将 ImageComponent 组件包裹在 <BrowserOnly> 组件中。在浏览器环境下执行相关代码,如果在服务器端执行则显示加载中的提示。

import BrowserOnly from '@docusaurus/BrowserOnly';

function ImageComponent() {
  return (
    <BrowserOnly fallback={<div>Loading...</div>}>
      {() => {
        const url = new URL(window.location.href);
        const pathname = decodeURIComponent(url.pathname);
        const keywordsToImages = {
          NBA: {
            imagePath: "/img/logo-nba.png",
            altText: "NBA Logo",
          },
          NASA: {
            imagePath: "/img/logo-nasa.jpg",
            altText: "NASA Logo",
          },          
          // 继续添加其他关键词和对应的图片信息
        };

        for (const keyword in keywordsToImages) {
          if (pathname.includes(keyword)) {
            const { imagePath, altText } = keywordsToImages[keyword];

            return (
              <div>
                <img src={imagePath} alt={altText} style={{width:'80px',height:'80px'}}/>
              </div>
            );
          }
        }

        return <div>未找到对应的图片</div>;
      }}
    </BrowserOnly>
  );
}

请注意,使用 <BrowserOnly> 组件时,需要将要执行的代码作为回调函数传递给组件。这样可以确保该回调函数只在浏览器环境下执行。如果在服务器端渲染时,会显示加载中的提示。

另外,有没有人知道,如何不使用上面的浏览器端的代码,来获取docusaurus下每个doc实例的id?研究了一下,没有找到。请告知。谢谢。