如何正确导入graphql-upload?解决ERR_REQUIRE_ESM报错问题
问题描述
我正在使用graphql-upload包,它的package.json中exports配置如下:
"exports": { "./GraphQLUpload.mjs": "./GraphQLUpload.mjs", "./graphqlUploadExpress.mjs": "./graphqlUploadExpress.mjs", "./graphqlUploadKoa.mjs": "./graphqlUploadKoa.mjs", "./package.json": "./package.json", "./processRequest.mjs": "./processRequest.mjs", "./Upload.mjs": "./Upload.mjs" },
在我的app.js文件里,尝试用require导入graphqlUploadExpress:
require("dotenv").config({ path: `./env/.env-${process.env.NODE_ENV}` }); const express = require("express"); const logger = require("morgan"); const moment = require("moment"); const cors = require("cors"); const path = require("path"); const bodyParser = require('body-parser'); const app = express(); const fs = require("fs"); const { ApolloServer, gql } = require("apollo-server-express"); const { mergeGraphQLTypes, mergeResolvers } = require("@graphql-tools/merge"); const { makeExecutableSchema } = require("@graphql-tools/schema"); const { applyMiddleware } = require("graphql-middleware"); const { graphqlUploadExpress } = require("graphql-upload/graphqlUploadExpress.mjs"); // <= 我按导出方式这么导入的 const { createServer } = require("http"); // 新增 const { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } = require("apollo-server-core"); const { WebSocketServer } = require("ws"); const { useServer } = require("graphql-ws/lib/use/ws"); require("./database/db"); require("./helper/function"); const Stripe = require("./stripe/stripeRoute"); const Cron = require("./scheduleCron/scheduleCronRoute"); const generateFolder = Helper("generate-folder");
但出现了错误:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\node-project\parkyt-new-api\server\node_modules \graphql-upload\graphqlUploadExpress.mjs at Module.load (internal/modules/cjs/loader.js:994:11) …更多调用栈 (internal/modules/run_main.js:71:12) {code: 'ERR_REQUIRE_ESM'
请问该如何正确导入graphql-upload?
解决方法
核心问题是你用的graphql-upload版本是纯ES模块(.mjs后缀),但你的项目是CommonJS模块系统(用require),Node.js不允许直接用require加载ES模块,所以报错。给你三种可行解决办法:
方法一:把项目切换为ES模块系统
- 在项目根目录的package.json里添加一行:
"type": "module" - 把app.js里所有require语法替换成import,比如:
注意:之后所有.js文件都会被当作ES模块处理,自己写的模块导入也要改成import语法。import dotenv from 'dotenv'; dotenv.config({ path: `./env/.env-${process.env.NODE_ENV}` }); import express from 'express'; // ...其他依赖都改成import import { graphqlUploadExpress } from 'graphql-upload/graphqlUploadExpress.mjs';
方法二:用动态导入(适合不想改整个项目模块系统的情况)
CommonJS里可以用import()函数动态加载ES模块,它返回Promise,你可以把启动逻辑包裹在async函数里:
async function startServer() { require("dotenv").config({ path: `./env/.env-${process.env.NODE_ENV}` }); const express = require("express"); // ...其他require保持不变 // 动态导入graphqlUploadExpress const { graphqlUploadExpress } = await import('graphql-upload/graphqlUploadExpress.mjs'); // 接下来正常配置中间件和启动服务器 app.use(graphqlUploadExpress()); // ...其他app配置、Apollo Server设置等 const httpServer = createServer(app); // ...启动服务器的代码 } // 启动并捕获错误 startServer().catch(err => console.error('启动失败:', err));
这样就能避开require加载ES模块的限制。
方法三:降级到支持CommonJS的graphql-upload版本
graphql-upload从v16开始改成纯ES模块,v15及以下版本支持CommonJS。你可以降级版本:
npm install graphql-upload@15
之后导入方式改成:
const { graphqlUploadExpress } = require("graphql-upload");
不用改项目模块系统,直接用原来的require语法即可。
内容的提问来源于stack exchange,提问作者Saswat
相关产品推荐
相关产品推荐

