Docusaurus:在加载内容期间写入文件系统是不是插件的不良做法?

Mic*_*rry 5 plugins docusaurus

我想使用“docs”插件和自定义 (JavaScript) 插件将文档填充到我的 Docusaurus 项目中,以将其连接到无头 CMS。目前,我正在使用loadContent Lifecycle API 事件来调用我的 Headless CMS API,然后使用fs.writeFileSync在“/docs”中创建物理降价文件并覆盖 ./sidebars.js 文件,以便出现“docs”插件与经典的预设作品。

./my-plugin/index.js:

module.exports = function (context, options) {
return {
  name: 'my-docusaurus-plugin',
  async loadContent() {
    //calls to Headless CMS API for documentation content
    let response =  await fetchArticles('documentation');
    // Adds the markdown files for 'docs' plugin using fs.writeFileSync   
    await buildArticles(response)

    //fetch homepage and navigation sections from CMS API
    let homepage = await fetchPages('homepage');
    let sidebarSection = await fetchPages('page');

    //overwrite ./sidebars.js with API navigation data using fs.writeFileSync
    await buildSidebar(homepage, sidebarSection);
  }
};
Run Code Online (Sandbox Code Playgroud)

};

这是因为我从我的 CMS 和文档渲染中获取内容,但它似乎更像是一种解决方法,而不是将无头 CMS 与 Docusaurus 连接的优雅解决方案。我是否遗漏了一些最佳实践,或者是否有使用其他生命周期事件的更好方法?

小智 0

前几天,我在构建自己的 Docusaurus 插件时遇到了同样的问题,而且我也无法在文档中找到明确的答案。实现插件的预期方法似乎是:

  1. 从函数返回内容loadContent
  2. 接收函数中返回的内容contentLoaded,并使用它来创建数据以提供给路由。您也可以在此处创建显示数据的路由。

但是,此模型似乎不适用于检索要在文档中显示的数据。该@docusaurus/plugin-content-docs插件似乎没有为另一个插件提供任何方法来为其提供包含在文档中的数据,因此似乎唯一的方法是将 Markdown 文件写入该目录/docs

然而,正如加宾评论中提到的,这会导致无限循环。经过一番调查后,我能够解释原因。问题是,每当任何插件监视的目录中的文件被更新时,都会触发重新加载并在所有loadContent插件上调用该函数。因此,如果将自定义插件配置为写入并触发重新加载,则会调用自定义插件的函数并将文件重写为. 但由于被 监视,自定义插件更新的每个文件都会触发另一个重新加载,这会导致自定义插件的函数再次被调用......这会导致无限循环。/docsloadContent/docs/docs@docusaurus/plugin-content-docs/docsloadContent

我确实设法找到了解决此问题的方法,即/docs如果预期内容与实际内容之间没有不匹配,则避免写入,从而防止再次重新加载。在三种不同的场景(并不相互排斥)中,插件需要进行更改/docs

  1. 现有文件的内容/docs需要更改。
  2. 需要将新文件添加到/docs.
  3. 需要从 中删除旧文件/docs

对于上面的场景 1,我必须编写一些代码来检查我要写入的文件是否/docs已经存在,并检查它是否已经包含我要写入的相同内容。如果这些条件都成立,那么我会跳过写入文件,因为没有什么可更改的。

对于上面的场景 3,我必须将“清理”代码移至函数末尾loadContent。由于顺序更改,我还必须修改该代码,因此它不会删除目标目录中的所有文件,而是仅删除不希望出现的任何“额外”文件。

loadContent即使进行了这些更改,只要需要写入 ,仍然会至少对自定义插件的函数进行一次不必要的调用/docs,因为写入/docs将触发重新加载,从而loadContent再次调用。但随后它会发现没有需要进行的更改,并且它将避免/docs再次写入并触发另一次重新加载。这至少比无限循环好得多!

我认为 Docusaurus 可以通过以下方式之一解决这个问题:

  1. 创建一种方法,让插件告诉 Docusaurus 仅在loadContent重新加载时调用其函数(如果重新加载是由插件getPathsToWatch函数返回的目录更改触发的)。
  2. 创建一种向官方插件(例如@docusaurus/plugin-content-docs. 看起来这个 GitHub Issue中已经提出了“中间件”功能,我认为这将是一个很好的解决方案。