digest-fetch 和 webpack - fetch 不是函数

digest-fetch and webpack - fetch is not a function

问题

TypeError: fetch is not a function
    at DigestClient.fetch (webpack-internal:///./node_modules/digest-fetch/digest-fetch-src.js:48:24)
    at User.create (webpack-internal:///./node_modules/mongodb-atlas-api-client/src/user.js:53:26)
    at Function.createOrgDBUser (webpack-internal:///./src/OrgUtils.ts:87:51)
    at Function.createOrg (webpack-internal:///./src/apis/OrgAPI.ts:373:39)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async APIResponse.processHandlerFunction (webpack-internal:///./node_modules/apilove/lib/APIResponse.ts:27:31)

这是我在尝试使用 mongodb-atlas-api-client@2.3.1 为集合创建索引时遇到的错误。我在本地和 aws-lambda 中看到此错误。

atlasClient.user.create({...})

我使用 webpack 来捆绑我的 api,所以我认为问题出在我的捆绑方式上,但在我的研究中我还没有找到解决方案。

digest-fetch,由 mongodb-atlas-api-client 使用,在没有本机 fetch 功能的情况下使用 node-fetch。但是,我相信我的 webpack 配置加上 digest-fetch 导入库的方式是导致问题的原因。

下面这行代码来自node-modules/digest-fetch/digest-fetch-src.js:8

if (typeof(fetch) !== 'function' && canRequire) var fetch = require('node-fetch')

如果我将其更改为以下内容,一切正常。换句话说,它是从 node-fetch.

导入模块而不是主要导出的提取函数
if (typeof(fetch) !== 'function' && canRequire) var fetch = require('node-fetch').default

node-fetch/package.json 描述了三个入口点。

"main": "lib/index.js",
"browser": "./browser.js",
"module": "lib/index.mjs",

我认为发生的事情是我的 webpack 配置告诉 webpack 使用 .mjs 模块入口点从 node-fetch 构建它的输出,export default fetch;.

我的webpack.config.js

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const NodemonPlugin = require('nodemon-webpack-plugin')
const ZipPlugin = require('zip-webpack-plugin')

module.exports = (env, argv) => {
  const config = {
    target: 'node',
    watchOptions: {
      ignored: ['node_modules', '*.js', '*.js.map', '*.d.ts'],
    },
    entry: './src/APIHandler.ts',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: `APIHandler.js`,
      libraryTarget: 'commonjs',
    },
    optimization: {
      minimize: false,
      // minimizer: [new TerserPlugin({})],
    },
    resolve: {
      extensions: ['.ts', '.json', '.mjs', '.js'],
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: {
            loader: 'ts-loader',
            options: {
              transpileOnly: true,
              allowTsInNodeModules: true,
            },
          },
        },
      ],
    },
    plugins: [
      new CleanWebpackPlugin(),
      new CopyPlugin([
        { from: path.join(__dirname, 'src/certs'), to: path.resolve(__dirname, 'dist', 'certs') },
      ]),
      new NodemonPlugin(),
    ],
  }

  // eslint-disable-next-line no-console
  console.log({ mode: argv.mode })

  if (argv.mode === 'development') {
    config.devtool = 'eval-cheap-module-source-map'
  }

  if (argv.mode === 'production') {
    config.plugins.push(
      new ZipPlugin({
        filename: 'handler',
      })
    )
  }

  return config
}

FWIW,这是我 node_modules 当前安装的每个库的版本。我在本地使用 node v12.22.7

"digest-fetch": "1.2.1",
"mongodb-atlas-api-client": "2.31.0",
"node-fetch": "2.6.7",
"webpack": "4.46.0"

问题

我错过了什么?我需要对我的 webpack.config.js 进行哪些更改才能正确解析从 node-fetch 导出的主模块?

注意:在我的研究中,我发现其他人也有这个问题,但没有解决方案对我有帮助。

解决方案非常简单。我将 mainFields 添加到 webpack 配置的 resolve 属性.

resolve: {
  extensions: ['.ts', '.json', '.mjs', '.js'],
  mainFields: ['main', 'module'],
}

这告诉 webpack 首先使用模块 package.jsonmain 属性,如果找不到则回退到 module 属性。

有关详细信息,请参阅 webpack's documentation