3

我试图遵循有关包括 gatsby-plugin-mdx 的 rehype 插件的文档。具体来说,我试图使用该rehype-slug插件。我安装了 npm 打包并将我的gatsby.config.js文件设置为

module.exports = {
  siteMetadata: {
    siteUrl: "https://www.yourdomain.tld",
    title: "test Website",
  },
  plugins: [
    {
      resolve: "gatsby-plugin-mdx",
      options:{
        rehypePlugins: [
          require("rehype-slug")
        ]
      }
    }
  ],
};
但是在运行时gatsby develop我遇到以下错误: Error: [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\Users\User\Documents\test-site\node_modules\rehype-slug\index.js require() of ES modules is not supported.

我在尝试使用remark-mathrehype-katex插件时遇到了类似的问题。我正在使用 Gatsby CLI 的 3.13.0 版本。即使使用全新的网站,问题仍然存在。对此问题的任何帮助将不胜感激。

4

2 回答 2

1

不确定它是否会起作用,但是,除了使用 ES 模块中的 require 之外,您是否尝试过类似的方法:

import slug from 'rehype-slug'

module.exports = {
  siteMetadata: {
    siteUrl: "https://www.yourdomain.tld",
    title: "test Website",
  },
  plugins: [
    {
      resolve: "gatsby-plugin-mdx",
      options:{
        rehypePlugins: [
          slug 
        ]
      }
    }
  ],
};

基于:https ://github.com/rehypejs/rehype-slug

或者直接在里面rehypePlugins作为动态导入导入。


我做了一些研究,发现不支持动态导入,因为您无法访问回调中的值,因此等待导入既不是解决方案,也不是使用ES 模块

但是,可以在此GitHub 讨论中找到具有完全相同用例的最终解决方案(或至少是临时工作解决方案):

更新:我rehype-slug@5.0.0通过gatsby-config.js安装esmpatch-package和:

  1. 修改gatsby-config.js如下(允许require()使用纯 ES 模块)

    require = require('esm')(module);
    
    module.exports = {
      plugins: [
        {
          resolve: `gatsby-plugin-mdx`,
          options: {
            rehypePlugins: [
              require('rehype-slug').default,
    
  2. 尝试运行 Gatsby 开发服务器,看看有什么问题。它会像这样抛出错误:

      Error: Must use import to load ES Module: /Users/k/p/project/node_modules/rehype-slug/index.js
      require() of ES modules is not supported.
      require() of /Users/k/p/project/node_modules/rehype-slug/index.js from /Users/k/p/project/gatsby-config.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
      Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/k/p/project/node_modules/rehype-slug/package.json.
    

    ...或者像这样:

      Error: /Users/k/p/project/gatsby-config.js:1
      Error: Must use import to load ES Module: /Users/k/p/project/node_modules/rehype-slug/index.js
    
  3. 记下纯 ES Modules 包的位置,以便您可以找到package.json与纯 ESM 包对应的文件并手动删除该行,"type": "module",如下所示:

    -  "type": "module",
    
  4. Run yarn patch-package <pkg name> --exclude '^$',它将记录您在package.json文件中所做的更改(patch-package每次运行时都会重新应用yarnnpm install)。例子:

    # For a top-level dependency
    yarn patch-package rehype-slug --exclude '^$'
    
    # For a transitive dependency
    yarn patch-package rehype-slug/unist-util-visit --exclude '^$'
    
  5. 再次运行 Gatsby 开发服务器,对每个纯 ESM 包重复步骤 3 和 4。

那时,我可以使用新的纯 ESM 依赖版本启动 Gatsby 开发服务器。

抄送@Ir1d @kimbaudi @wardpeet @LekoArts

警告:在我的具体情况下,我还需要修补其中一个依赖项 ( hast-util-heading-rank),因为我得到了一个 undefined node.tagName,但我认为这与这个问题无关——可能与另一个问题有关。

所有涉及魔术师的学分

于 2021-09-13T18:31:07.800 回答
0

在同一个GitHub 讨论中有一个更简单更优雅的解决方案

require-esm.js在根文件夹(与 package.json 相同的位置)中创建:

// Source: https://stackoverflow.com/a/71344589/2078908

const esm = require('esm')
const fs = require('fs')
const Module = require('module')

// Node: bypass [ERR_REQUIRE_ESM]
const orig = Module._extensions['.js']
Module._extensions['.js'] = function (module, filename) {
  try {
    return orig(module, filename)
  } catch (e) {
    const content = fs.readFileSync(filename, 'utf8')
    module._compile(content, filename)
  }
}

const _esmRequire = esm(module, {
  cjs: true,
  mode: 'all',
})

// don't pollute Module
Module._extensions['.js'] = orig

module.exports = function esmRequire(id) {
  return _esmRequire(id).default
}

然后gatsby-config.js像这样使用它:

require.esm = require('./require-esm')

module.exports = {
        .......
        {
            resolve: `gatsby-plugin-mdx`,
            options: {
                extensions: ['.mdx', '.md'],
                rehypePlugins: [
                    // Generate heading ids for rehype-autolink-headings
                    [require.esm('rehype-slug')],
                    // To pass options, use a 2-element array with the
                    // configuration in an object in the second element
                    [require.esm('rehype-autolink-headings'), { behavior: "wrap" }],
                ],
            }
        },
        .......
}

更新

经过一些测试后,我将上面的代码简化为几行。它仍然适用于我的设置。

require.esm(...)像这样使用gatsby-config.js

const requireEsm = require('esm')(module)
require.esm = id => requireEsm(id).default

module.exports = {
                .......
                rehypePlugins: [
                    // Generate heading ids for rehype-autolink-headings
                    [require.esm('rehype-slug')],
                    .......
}

于 2022-03-03T22:31:35.760 回答