I have a setup with webpack typescript (using ts-loader).
To enable code splitting with webpack, you must set module to esnext in tsconfig:
// tsconfig.json
{
"compilerOptions": {
"module": "esnext"
// other configuration ...
}
}
I'm trying to pass this
as a parameter in one of my files. It works on node.js, which runs on individually compiled files using the native typescript compiler, but the problem is:
in webpack this
is replaced with undefined
I've reduced it to this simple setup:
Typescript source code
export var this2 = this;
Output of tsc
:
export var this2 = this;
Webpack output:
/*!**********************!*\
!*** ./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;
/******/ })()
;
This even happens when there is a lot of other things exported in the file (so this is not just empty and therefor reduced to undefined)
I'm not 100% sure where the issue lies. But note that this does not happen with the same setup without typescript (so webpack javascript source module=esnext) nor does it happen with compiling typescript to javascript for nodejs with tsc
.
I wonder where the problem lies and if this is expected behavior for any reason.
I want a file register all the exports of that file somewhere, without having to import it (the other file doesn't know of its existence). But this behavior seems to make it impossible to access the files' exports and pass them to a function
minimal reproduction setup
See this live stackblitz setup
Run webpack
or tsc
in the terminal to recreate the outputs in /webpack
and /tsc
CodePudding user response:
this
at the top level of an ESM module has the value undefined
. That's per specification (link). So Webpack is just doing what the specification says.
If you want the value this
would have at the top level of a non-module script, use the new(ish) globalThis
(spec | MDN).
In a comment (and in your question!) you've said:
I would like to access all the files' exports like this usually does in commonjs
You can do that in a surprising way: By getting the module namespace object of the module from...itself! Say you're doing this in mod.js
. You can get the module namespace object for the module itself by doing:
// *IN* `mod.js` itself
import * as mod from "./mod.js";
mod
will refer to an object that has properties for all of the module's exports (the default export will have the property name default
). Here's a complete example:
export const a = 42;
export const fn = () => { };
import * as mod from "./mod.js";
console.log(mod.a); // 42
console.log(typeof mod.fn) // "function"
That said, if you want to pass things around as a unit like that, you might consider creating an object explicitly and exporting the object. It depends on the use case.