This repository was archived by the owner on Nov 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(types): Enable plugin to be imported under ES6 (#316)
Because the webpack plugin is written in vanilla JS (rather than TS), we have a manually-generated type declaration file, where we default-export the `SentryCliPlugin` class. We also have a file (`cjs.js`) which is meant to make the plugin play nicely with CommonJS imports. And if the user is indeed using CommonJS imports (`const SentryWebpackPlugin = require('@sentry/webpack-plugin')`), that all works great. But if you try to do ES6 imports, the only form which gets you anything besides `undefined` is `import * as SentryWebpackPlugin from '@sentry/webpack-plugin`.* As far as TS is concerned, though, that creates a namespace rather than a class, and so it will refuse to let you call `new SentryWebpackPlugin`, instead telling you that `SentryWebpackPlugin` is not contructable. One solution is to use `esModuleInterop`, but that's [gotten us into trouble before](getsentry/sentry-javascript#3401 (comment)) and in fact breaks some of our own SDK code. *The other two options are `import SentryCliPlugin as SentryWebpackPlugin from '@sentry/webpack-plugin'` and `import { default as SentryWebpackPlugin } from '@sentry/webpack-plugin'`, both of which let you call `new` on them, but neither of which currently actually gives you anything other than `undefined`). The alternative (which is what's done in this change) is to do two things: 1) Use the older, more universal `exports = ...` syntax in our type declaration file rather than our current `export default ...` syntax (which, according to the TS docs, [actually won’t work](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html#default-exports) unless `esModuleInterop` is set to `true`). This then necessitates moving the options interface into a namespace for the module. 2) Explicitly create an export under the name `default`, so that the two alternatives above actually come up with something rather than being undefined. This shouldn't affect any current imports, as the first change just moves to an equivalent syntax, and the second change is purely additive.
- Loading branch information
1 parent
ea8db20
commit f9ef5ce
Showing
5 changed files
with
487 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,20 @@ | ||
module.exports = require('./index').default; | ||
|
||
// The assignment to `default` below saves us from having to use | ||
// `esModuleInterop` (which then would force our users to set the same option), | ||
// by manually doing the one part of `esModuleInterop`'s job we actually need. | ||
// | ||
// (In order to avoid a breaking change, we need to stick with default-exporting | ||
// `SentryCliPlugin`. This means that if we want to use ES6 imports (in our own | ||
// use of the plugin), our options are: | ||
// | ||
// `import * as x from y`, | ||
// `import x from y`, and | ||
// `import {default as x} from y`. | ||
// | ||
// If we use the first option, it correctly pulls in the above `module.exports` | ||
// value, but it treats it as a namespace, not a class, and therefore refuses to | ||
// let it be used with `new`. If we use either of the other two, it looks for | ||
// `module.exports.default`, which will be undefined unless either we do (or | ||
// `esModuleInterop` does) the below.) | ||
module.exports.default = module.exports; |
Oops, something went wrong.