developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
8k stars 361 forks source link

A typescript package that supports both commonjs and esmodule should generate `.d.ts` and `.d.cts` type files, now only `.d.ts` #1030

Open yuntian001 opened 1 year ago

yuntian001 commented 1 year ago

typescript 文档请参考:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#packagejson-exports-imports-and-self-referencing

package.json

"type": "module",
    "main": "dist/index.cjs",
    "module": "dist/index.js",
    "types": "dist/index.d.ts",
    "exports": {
      ".": {
        "import": {
          "types": "./dist/index.d.ts",
          "default":"./dist/index.js"
        },
        "require":  {
          "types": "./dist/index.d.cts",
          "default":"./dist/index.cjs"
        }
      }      
    },
    "files": [
      "dist"
    ],
    "scripts": {
      "test": "npm run build && cd ./test && npm run dev",
      "clean": "rimraf dist",
      "build": "rimraf dist && microbundle --target node  -f esm,cjs"
    },
JohnAlbin commented 9 months ago

Specifically, the TypeScript docs say:

It’s important to note that the CommonJS entrypoint and the ES module entrypoint each needs its own declaration file, even if the contents are the same between them. Every declaration file is interpreted either as a CommonJS module or as an ES module, based on its file extension and the "type" field of the package.json, and this detected module kind must match the module kind that Node will detect for the corresponding JavaScript file for type checking to be correct. Attempting to use a single .d.ts file to type both an ES module entrypoint and a CommonJS entrypoint will cause TypeScript to think only one of those entrypoints exists, causing compiler errors for users of the package.

rschristian commented 9 months ago

While that's indeed the position of the TS team now, for the past 6+ years, ESM .d.ts files were all that existed and were pretty much without issue. I don't think this is going to be a priority to address here, and likely won't be addressed at all until TS provides a dual-compilation method.

brandonmcconnell commented 3 months ago

I just switched over to microbundle, but I'm not likely to stay long if this issue persists. Very simple to use, which is great, but this is a bit too risky.

From attw:

tailwindcss-default-shades v0.0.19 Build tools: - typescript@^5.1.6 - microbundle@^0.15.1 👺 Import resolved to an ESM type declaration file, but a CommonJS JavaScript file. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md "tailwindcss-default-shades" node10: 🟢 node16 (from CJS): 👺 Masquerading as ESM node16 (from ESM): 🟢 (ESM) bundler: 🟢 ***********************************

The instructions to resolve this are to output both .d.ts and .d.cts files, which is appears microbundle does not support.

rschristian commented 3 months ago

Then you'll probably be better served elsewhere -- I don't find TS's changes here to be particularly compelling (as it causes no real issue anyhow) and no one else has invested time to land this, so this issue will probably persist.

Edit: This is OSS ran by people volunteering free time; you're not a customer we're trying to keep. To start off a reply saying you'll go elsewhere unless maintainers support your feature request is incredibly demanding and rude.

If this tool doesn't fit your needs, please, there's a world of great software out there.

brandonmcconnell commented 3 months ago

@rschristian Hi there! Sorry, in no way did I mean what I said to be rude or demanding. I was attempting to provide an example of how this might be seen as important.

As a new adopter of the tool, I'm finding it genuinely challenging to use, as it conflicts with other common build tools that expect both .d.ts and .d.cts.

This is not meant in any sort of demanding way. I thought it would be more constructive to the team to mention my observation and experience here rather than silently switch to an alternative, in case there is an opportunity to meet this need, perhaps due to my new shared information (the conflicts with other build tools). If there's not, I completely understand.

OSS is hard work, and I truly respect and appreciate the team working on microbundle. I was just introduced to the tool today, and I found it exceptionally simple to use in comparison to other tools. That's why I'm so bummed it conflicts with my other build tools.

Thanks again 🙂

brandonmcconnell commented 3 months ago

@rschristian I also wonder if there could be a simple workaround, even in user land, such as duplicating the .d.ts file and text-replacing certain things that change between the .d.ts and .d.cts files.

rschristian commented 3 months ago

a simple workaround, such as duplicating the .d.ts file and text-replacing certain things that change between the .d.ts and .d.cts files.

Unfortunately, this is unlikely. To copy/paste from MDN:

// Exporting declarations
export let name1, name2/*, … */; // also var
export const name1 = 1, name2 = 2/*, … */; // also var, let
export function functionName() { /* … */ }
export class ClassName { /* … */ }
export function* generatorFunctionName() { /* … */ }
export const { name1, name2: bar } = o;
export const [ name1, name2 ] = array;

// Export list
export { name1, /* …, */ nameN };
export { variable1 as name1, variable2 as name2, /* …, */ nameN };
export { variable1 as "string name" };
export { name1 as default /*, … */ };

// Default exports
export default expression;
export default function functionName() { /* … */ }
export default class ClassName { /* … */ }
export default function* generatorFunctionName() { /* … */ }
export default function () { /* … */ }
export default class { /* … */ }
export default function* () { /* … */ }

// Aggregating modules
export * from "module-name";
export * as name1 from "module-name";
export { name1, /* …, */ nameN } from "module-name";
export { import1 as name1, import2 as name2, /* …, */ nameN } from "module-name";
export { default, /* …, */ } from "module-name";
export { default as name1 } from "module-name";

There's a lot of ways to export values w/ ESM, and translating them to CJS would be pretty tricky. A few of these are probably irrelevant, but as we do use TS (through rollup-plugin-typescript2), which is an eternally moving target, I don't think there's any way to expect only a certain subset of the syntax to convert. It'd be a pretty complicated plugin to convert this all over to CJS correctly for all cases I'd think.

Now, we likely could override the user's tsconfig.json settings to output the correct .[cm]ts during compilation, but I have no idea if that'll introduce other issues. I had hoped TS would walk back on this / provide better tooling by now, as introducing .cts years after being ESM-only is quite frustrating.

As a new adopter of the tool, I'm finding it genuinely challenging to use, as it conflicts with other common build tools that expect both .d.ts and .d.cts.

Honest question, what build tools are these? I've never seen a build tool that would take .d.ts files into account at all, short of (say) declaration merging.

rschristian commented 3 weeks ago

Now, we likely could override the user's tsconfig.json settings to output the correct .[cm]ts during compilation,

Took a better look at it today, appears that rpt2 doesn't yet support anything other than ESM output, and we can't really do much to correct this as the .d.ts files are written directly to the disk & not part of the Rollup bundle.