Skip to content

Conversation

@ibc
Copy link
Member

@ibc ibc commented Mar 10, 2025

Details

  • Use rollup to generate two bundles in lib/ folder (and other files):
    • rtp.js.bundle.cjs: A CommonJS bundle file.
    • rtp.js.bundle.cjs.map: Source map file for the CommonJS bundle file.
    • rtp.js.bundle.mjs: An ES bundle file.
    • rtp.js.bundle.mjs.map: Source map file for the ES bundle file.
    • rtp.js.bundle.d.ts: TypeScript types.
  • package.json: Use exports field with import and require entries pointing to the CommonJS and ES bundle files.

Generated lib folder

ls -l lib
total 2680
  191848 rtp.js.bundle.cjs
  428300 rtp.js.bundle.cjs.map
  126206 rtp.js.bundle.d.ts
  191807 rtp.js.bundle.mjs
  428297 rtp.js.bundle.mjs.map

So if the parent application uses ES (import * as rtpJs from 'rtp.js') then it will read the rtp.js.bundle.mjs file. If it uses CJS (const rtpJs = require('rtp.js')) then it will read the rtp.js.bundle.cjs file instead. Tested.

@ibc ibc marked this pull request as ready for review March 12, 2025 20:59
@ibc ibc changed the title Use ES modules Export EM and CJS bundle files Mar 12, 2025
@ibc ibc merged commit b4832f9 into master Mar 13, 2025
8 checks passed
@ibc ibc deleted the try-type-module branch March 13, 2025 10:29
ibc added a commit that referenced this pull request Mar 20, 2025
## Details

- This PR basically reverts PR #32 because this is hell. More about this in **Why???** section below.
- Only generate CommonJS code in `lib/` instead of both ESM and CommonJS code.
- Remove Babel stuff and rely on `tsc` to generate CommonJS code and TypeScript declaration files in `lib/`.

## Why???

- Because this is hell. Totally hell.
- Before this PR, rtp.js can not be used in TypeScript projects that use Webpack to generate a bundled JS file. Why? Because Webpack assumes that everything is CommonJS but then it miserably fails to locate/resolve '.cjs' files.
- If we have '.ts' files in `src/` folder, then `tsc` will generate 'js' files rather than '.mjs' files, and that means problems with loaders/bundlers that assume that '.js' files contain CommonJS and then they fail to process them because those '.js'  files contain 'import/export' rather than 'require/module.exports'.
- And if we have '.mts' files in `src` then `tsc` will generate `.mjs` with ESM code but it's literally impossible to have another `tsconfig-cjs.json` file to make `tsc` generate CommonJS code.
- So then we moved to Babel to generate ESM and CJS code (see PR #32), and we have to include tricks to replace the extension in the `import` and `require()` calls in the generated ESM and CJS code in `lib/`, which is terrible. But then Babel also generates `.js.map` files that reference a `.mts` file in `lib/` folder which obviously doesn't exist.
- And another problem is that Babel only generates JavaScript code so we still need to use `tsc` to generate TypeScript declaration files and, since we have '.mts' files in `src/`, those declaration files have `d.mts` extension. But they many text editors and TypeScript consumers asusme that declaraion files must be '.d.ts' only. And if we rename their extension then we have also to munge generated `.mjs` (ESM) and `.cjs` files in `lib/` because those files contain special commented mapping lines that reference the declaration file (with '.d.mts').
- And then it also happens that in CommonJS importing a file without extendion is ok, but in ESM you must write `import foo from './foo.ts'` rather than `from './foo'`. So here another needed rewrite in generated `lib/` code.
- etc etc etc, and **trust me**, more etc etc etc. I've tried EVERYTHING, much more than what I've told here.

## Conclusion

- It's impossible to generate ESM and CJS file in a proper way because it entirely affects the way the TypeScript code must be written, and it includes whether to use `.ts` or `.mts` extension in source files, whether to import internal files with or without extension, and `tsconfig.json` doesn't expose options enough to cover all cases we need when generating ESM or CJS code. I've checked them all, and the same with Babel.
- My conclusion is that, if you want to publish a library in ESM format, you only generate ESM code ('.mjs' files) from TypeScript '.mts' files. But you cannot generate **also** CJS files. And the other way around.
@ibc ibc mentioned this pull request Mar 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants