Conversation
package.json
Outdated
| "require": "./dist/cjs/index.js", | ||
| "types": "./dist/types/index.d.ts" | ||
| }, | ||
| "./dist/cjs/*": { |
There was a problem hiding this comment.
Just so I understand this correctly from your comment here, because Browserify ignores exports, the paths on the left-hand side of exports (aside from ".") need to be written so that they resolve to real files in the filesystem. We do this so that if the extension uses a library that contains a subpath import e.g., @metamask/key-tree/dist/cjs/some/path, will continue to work.
However, this seems to imply two things: 1) the responsibility for resolving an import path shifts from the consumer to the library itself, and 2) we cannot create fully ESM-compatible libraries.
Say we publish a library that contains a subpath import of another library. Ideally we could use a shortcut for that import (e.g. @metamask/key-tree/some/path) and it would resolve to either the CJS or ESM version depending on what the consumer is using (a bundler or straight Node). But we can't do that, so we have to be explicit and use the CJS version (@metamask/key-tree/dist/cjs/some/path).
But if we do that, wouldn't this mean that in the compiled version of our library, both the CJS and ESM builds will contain this import? So even if in our ESM build, we'd potentially have a mixture of ESM and CJS?
There was a problem hiding this comment.
Could you give an example of "a subpath import of another library"? I'm not sure what that means, or why we'd want to support it.
There was a problem hiding this comment.
But if we do that, wouldn't this mean that in the compiled version of our library, both the CJS and ESM builds will contain this import? So even if in our ESM build, we'd potentially have a mixture of ESM and CJS?
Yeah, that's the downside of doing this. I thought about doing something like this:
{
"./dist/cjs/*": {
"import": "./dist/esm/*.js",
"require": "./dist/cjs/*.js"
}
}So even if you import ./dist/cjs/foo, and your bundler supports exports, it will resolve to ./dist/esm/foo. But this feels very hacky.
I wonder if there's a way to support exports in Browserify through a plugin, but I couldn't find anything about this. That would solve all problems I think.
There was a problem hiding this comment.
Could you give an example of "a subpath import of another library"? I'm not sure what that means, or why we'd want to support it.
For example:
utilsimportsabi-utils/dist/cjs/foosnaps-utilsimportsutils.snaps-utilsis now indirectly usingabi-utils/dist/cjs/foo, even though the bundler may support ESM.
There was a problem hiding this comment.
Thanks, my brain somehow read "subpath import" as "subpath export". That makes more sense.
|
Perhaps we could omit the |
I'm not sure how much work would be involved in this, but if it's not too much, that seems like a good option too. A regex search in the Snaps repo ( |
| "require": "./dist/cjs/index.js", | ||
| "types": "./dist/types/index.d.ts" | ||
| }, | ||
| "./package.json": "./package.json" |
There was a problem hiding this comment.
This is useful for resolving the root of the package. I'm not sure if it should be added to the module template, but it doesn't hurt I suppose?
We use this in the Snaps repo several times, which doesn't work without this line:
path.dirname(require.resolve('package/package.json'));There was a problem hiding this comment.
Interesting. I guess it doesn't hurt 🤷
| "build:docs": "typedoc", | ||
| "build:esm": "swc src --out-dir dist/esm --config-file .swcrc.build.json --config module.type=es6", | ||
| "build:esm": "swc src --out-dir dist/esm --config-file .swcrc.build.json --config module.type=es6 && yarn build:esm:package", | ||
| "build:esm:package": "echo >dist/esm/package.json \"{\\\"type\\\":\\\"module\\\"}\"", |
There was a problem hiding this comment.
Apparently Node.js doesn't allow using .js for both the CJS and ESM version in the same project (??), but you can work around it by adding a package.json to the ESM folder.
I like this. Maybe it shouldn't be a blocker for this PR? But I do think it's a good idea. |
Following discussion in #203, I removed the
exportsfield from thepackage.jsonbecause it seemed unnecessary. Unfortunately, not having it breaks when importing a package when Node.js is running in ESM mode, because Node.js doesn't look at themodulefield at all. This causes issues like in MetaMask/key-tree#144.This adds a two exports fields:
.: The main export, which is used when importing a package from the root. This means that we cannot reliably import from subpaths anymore../package.json: To allow resolving thepackage.jsonpath (and importing it, if desired), we also export this.Since Browserify does not support the exports field, we can't use
./*exports (i.e.,package/fooresolves topackage/dist/esm/fooorpackage/dist/cjs/foodepending on the environment), as it would break in the extension.