首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >webpack进口ESM套餐的ERR_REQUIRE_ESM

webpack进口ESM套餐的ERR_REQUIRE_ESM
EN

Stack Overflow用户
提问于 2021-12-26 07:47:24
回答 1查看 1.8K关注 0票数 3

我正在构建一个应用程序,使用Nx进行模块化,使用壁虎作为服务器部分。对于Nx的默认Node配置Webpack 5,在运行该应用程序时,我会得到以下错误:

代码语言:javascript
复制
/Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:8
module.exports = require("@geckos.io/server");
                 ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/node_modules/@geckos.io/server/lib/index.js from /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js not supported.
Instead change the require of index.js in /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js to a dynamic import() which is available in all CommonJS modules.
(...)

以下是复制的步骤:

代码语言:javascript
复制
$ npx create-nx-workspace@latest nx-geckos-test
Need to install the following packages:
  create-nx-workspace@latest
Ok to proceed? (y) y
✔ What to create in the new workspace · express
✔ Application name                    · geckos-server-app
✔ Use Nx Cloud? (It's free and doesn't require registration.) · No

>  NX  Nx is creating your v13.4.1 workspace.

  To make sure the command works reliably in all environments, and that the preset is applied correctly,
  Nx will run "npm install" several times. Please wait.

✔ Installing dependencies with npm
✔ Nx has successfully created the workspace.
代码语言:javascript
复制
$ npm run start

> nx-geckos-test@0.0.0 start
> nx serve

> nx run geckos-server-app:serve
chunk (runtime: main) main.js (main) 552 bytes [entry] [rendered]
webpack compiled successfully (26ac6f288b082854)
Debugger listening on ws://localhost:9229/70a1d9b4-af2b-4fc9-90f7-f3502e5fdf2e
Debugger listening on ws://localhost:9229/70a1d9b4-af2b-4fc9-90f7-f3502e5fdf2e
For help, see: https://nodejs.org/en/docs/inspector
Issues checking in progress...
Listening at http://localhost:3333/api

在这个阶段,默认的Express应用程序构建并运行。

现在,我将apps/geckos-server-app/src/main.ts的内容替换为来自自述的Geckos服务器示例:

代码语言:javascript
复制
import geckos from '@geckos.io/server'

const io = geckos()

io.listen(3000) // default port is 9208

io.onConnection(channel => {
  channel.onDisconnect(() => {
    console.log(`${channel.id} got disconnected`)
  })

  channel.on('chat message', data => {
    console.log(`got ${data} from "chat message"`)
    // emit the "chat message" data to all channels in the same room
    io.room(channel.roomId).emit('chat message', data)
  })
})

使用...and安装geckos服务器包

代码语言:javascript
复制
$ npm install @geckos.io/server

added 4 packages, and audited 785 packages in 7s

87 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

好的,是时候再次运行它了:

代码语言:javascript
复制
$ npm run start

> nx-geckos-test@0.0.0 start
> nx serve


> nx run geckos-server-app:serve
chunk (runtime: main) main.js (main) 610 bytes [entry] [rendered]
webpack compiled successfully (90920432a9d246ea)
Debugger listening on ws://localhost:9229/dc6d9e1a-1a15-432f-a46c-d2ac83b923ea
Debugger listening on ws://localhost:9229/dc6d9e1a-1a15-432f-a46c-d2ac83b923ea
For help, see: https://nodejs.org/en/docs/inspector

/Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:8
module.exports = require("@geckos.io/server");
                 ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/node_modules/@geckos.io/server/lib/index.js from /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js not supported.
Instead change the require of index.js in /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js to a dynamic import() which is available in all CommonJS modules.
    at Object.@geckos.io/server (/Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:8:18)
    at __webpack_require__ (/Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:32:41)
    at /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:45:18
    at /Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:59:3
    at Object.<anonymous> (/Users/hgrzeskowiak/hugo-game/fresh-nx-geckos/nx-geckos-test/dist/apps/geckos-server-app/main.js:64:12)

我在package.json中测试了不少Webpack配置重写和使用package.json的配置,但都没有效果。无论我改变什么webpack设置,输出main.js看起来都是一样的。我尝试在应用程序的webpack覆盖配置中更改的内容:

代码语言:javascript
复制
module.exports = function(webpackConfig, context) {
  webpackConfig.target = "async-node16";
  webpackConfig.output.libraryTarget = "module";
  webpackConfig.output.library = {type: "module"};
  webpackConfig.output.chunkFormat = "module";
  webpackConfig.experiments.outputModule = true;
  console.log("webpack config:");
  console.log(webpackConfig);
  console.log("module rules:");
  console.log(webpackConfig.module.rules);
  return webpackConfig;
}

控制台记录在配置中,验证脚本是否正在运行。

当我在传输输出中手动将require更改为import时,该应用程序就能工作,但这不是一个可持续的解决方案。

我怀疑这个错误与Geckos是一个ESM包有关,Webpack只使用require而不是import,但我无法找到任何改变这种行为的方法。

有什么想法吗?

  • 节点版本16.13.0
  • Nx版本13.4.1
  • Webpack (Nx传递员):5.65.0
EN

回答 1

Stack Overflow用户

发布于 2021-12-26 15:26:49

这里是我能找到的最干净的解决方案,它适用于大于4.6的Type脚本版本(它应该增加对此特性的支持)。这实际上是用较旧的WebPack版本(包括撰写本文时的最新版本)将ESM支持修补到TypeScript中。

一个自定义Webpack插件,它将外部模块的类型更改为import

代码语言:javascript
复制
// TypeScript before version 4.6 does not support transpiling ESM imports to
// `import()`, but uses `require()` instead. NodeJS does not support the use
// of `require() for ECMAScript modules (ESM).
//
// Good reads:
// https://www.typescriptlang.org/docs/handbook/esm-node.html
// https://devblogs.microsoft.com/typescript/announcing-typescript-4-5/#esm-nodejs

/**
 * A Webpack 5 plugin that can be passed a list of packages that are of type
 * ESM. The typescript compiler will then be instructed to use the `import`
 * external type.
 */
class ESMLoader {
  static defaultOptions = {
    esmPackages: "all"
  };

  constructor(options = {}) {
    this.options = { ...ESMLoader.defaultOptions, ...options };
  }

  apply(compiler) {
    compiler.hooks.compilation.tap(
      "ECMAScript Module (ESM) Loader. Turns require() into import()",
      (
        compilation
      ) => {
        compilation.hooks.buildModule.tap("Hello World Plugin", (module) => {
            if (
              module.type === "javascript/dynamic" &&
              (
                this.options.esmPackages === "all" ||
                this.options.esmPackages.includes(module.request)
              )
            ) {
              // All types documented at
              // https://webpack.js.org/configuration/externals/#externalstype
              module.externalType = "import";
            }
          }
        )
        ;
      }
    );
  }
}

module.exports = function(webpackConfig, context) {
  // NodeJS supports dynamic imports since version 12.
  webpackConfig.target = "node16";
  webpackConfig.plugins.push(
    // Manually specify the ESM modules or leave blank for using `import()`
    // on all packages.
    //new ESMLoader()
    new ESMLoader({esmPackages: "@geckos.io/server"})
  );
  return webpackConfig;
};

自定义webpack配置可以通过project.json在Nx应用程序上设置。

代码语言:javascript
复制
{
  "targets": {
    "build": {
      "executor": "@nrwl/node:build",
      "options": {
       ...
        "webpackConfig": "apps/your-app/webpackConfig.js"
      },
      ...

此解决方案还要求tsconfig.json将模块类型设置为比commonjs更现代的类型,例如es2020

代码语言:javascript
复制
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/out-tsc",
    "module": "es2020",
    "types": ["node"],
  },
  "exclude": ["**/*.spec.ts", "**/*.test.ts"],
  "include": ["**/*.ts"]
}

完成此操作后,可以使用通常的nx serve运行构建的文件。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70484934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档