使用 webpack + typescript + module = "esnext" 更改为未定义

this is changed to undefined with webpack + typescript + module = "esnext"

我有一个带有 webpack + typescript 的设置(使用 ts-loader)。

要使用 webpack 启用代码拆分,you must set module to esnext in tsconfig:

// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext"
    // other configuration ...
  }
}

我正在尝试将 this 作为我的一个文件中的参数传递。它适用于 node.js,它使用本机打字稿编译器在单独编译的文件上运行,但问题是:

在webpack中this被替换为undefined

我已将其简化为这个简单的设置:

打字稿源代码

export var this2 = this;

tsc 的输出:

export var this2 = this;

Webpack 输出:

/*!**********************!*\
  !*** ./src/index.ts ***!
  \**********************/
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "this2": () => (/* binding */ this2)
/* harmony export */ });
var this2 = undefined;

/******/ })()
;

当文件中导出了很多其他内容时甚至会发生这种情况(因此这不仅仅是空的,因此减少为未定义)

我不是 100% 确定问题出在哪里。但请注意,这确实 不会 发生 使用没有打字稿的相同设置(所以 webpack + javascript source + module=esnext)nor 使用 tsc.

将 typescript 编译为 javascript for nodejs 是否会发生这种情况

我想知道问题出在哪里,这是否出于某种原因是预期的行为。

我想要一个文件在某处注册该文件的所有导出,而不必导入它(另一个文件不知道它的存在)。但是这种行为似乎无法访问文件的导出并将它们传递给函数

最小复制设置

看到这个live stackblitz setup

运行 webpacktsc 在终端中重新创建 /webpack/tsc

中的输出
ESM 模块顶层的

this 的值为 undefined。这是每个规范 (link)。所以 Webpack 只是按照规范所说的去做。

如果您希望值 this 位于 non-module 脚本的顶层,请使用新的(ish)globalThis (spec | MDN)。

在评论中(以及在您的问题中!)您说:

I would like to access all the files' exports like this usually does in commonjs

您可以通过一种令人惊讶的方式做到这一点:通过从...本身获取模块的模块命名空间对象!假设您在 mod.js 中执行此操作。您可以通过执行以下操作获取模块本身的模块名称空间对象:

// *IN* `mod.js` itself
import * as mod from "./mod.js";

mod 将引用具有所有模块导出属性的对象(默认导出将具有 属性 名称 default)。这是一个完整的例子:

export const a = 42;
export const fn = () => { };

import * as mod from "./mod.js";
console.log(mod.a);        // 42
console.log(typeof mod.fn) // "function"

就是说,如果您想像那样将事物作为一个单元传递,您可以考虑显式创建一个对象并导出该对象。这取决于用例。