Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to ship in CJS format when my package has pure ESM package dependencies? #79

Closed
holazz opened this issue May 17, 2022 · 8 comments
Closed

Comments

@holazz
Copy link

holazz commented May 17, 2022

index.ts:

import ora from 'ora'
 
const spinner = ora('Starting...').start()
spinner.succeed('Done!')

build.config.ts:

export default defineBuildConfig({
  entries: [
    'index',
  ],
  rollup: {
    emitCJS: true,
  },
})

run unbuild && node dist/index.cjs and get error:

const ora = require('ora');
            ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/zhangjiawei/Desktop/git-download/node_modules/.pnpm/ora@6.1.0/node_modules/ora/index.js from /Users/zhangjiawei/Desktop/git-download/dist/index.cjs not supported.
Instead change the require of index.js in /Users/zhangjiawei/Desktop/git-download/dist/index.cjs to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/Users/zhangjiawei/Desktop/git-download/dist/index.cjs:3:13) {
  code: 'ERR_REQUIRE_ESM'
}
@innocenzi
Copy link

Hey, same question. My case was with execa, which is now pure ESM as well. I was using tsup previously and it has a noExternal option which solved the issue: https://github.com/egoist/tsup/blob/b9cd8d5f0973f94d494b8b0d0e65121e5712ee49/src/esbuild/external.ts#L7

@holazz
Copy link
Author

holazz commented Jun 1, 2022

Hey, same question. My case was with execa, which is now pure ESM as well. I was using tsup previously and it has a noExternal option which solved the issue: egoist/tsup@b9cd8d5/src/esbuild/external.ts#L7

Thanks for the idea, I want to ship both cjs and esm format, I tried setting noExternal , cjs works well, but esm doesn't work.

@pi0
Copy link
Member

pi0 commented Jun 1, 2022

When possible, using dynamic imports is the best way to load such libraries for CJS build support:

const execa = await import('execa')

Unbuild has rollup.inlineDependencies option that inlines all deps but i would avoid that. But i would go with dynamic import as possible.

Some alternatives:

  • Find an alternative dep or use a version that is still supporting CJS
  • Drop CJS support from your library as well to keep such deps

@innocenzi
Copy link

In my context I can't not ship CJS unfortunately. I could downgrade execa but I think it's nice to be able to inline the dependency. I found tsup's noExternal option to be quite useful.

That being said @pi0, I was using the following config which did not inline execa:

export default defineBuildConfig({
    entries: [
        'src/index',
        'src/inertia',
    ],
    clean: true,
    declaration: true,
    externals: [
        'rollup',
        'vite',
        'esbuild',
        'tailwindcss',
        'autoprefixer',
    ],
    rollup: {
        emitCJS: true,
        inlineDependencies: true,
    },
})

I use import { execaSync } from 'execa' somewhere in my code, and the generated index.cjs has a require('execa') still. Did I do something wrong here?

@pi0
Copy link
Member

pi0 commented Jun 1, 2022

Do you mind to share a repo @innocenzi? Also certainly you cannot use dynamic import approach? Being able to inline is for sure a valid case but it is not always the best idea...

@innocenzi
Copy link

Sure @pi0: https://github.com/innocenzi/unbuild-issue-79

Run npx unbuild and see that there is still a const execa = require('execa') instead of that dependency to be inlined.

In my case the dynamic import is not an option, but I can downgrade execa (v5 is CJS). Maybe it's not the best option to inline the dependency but I prefer to stay up to date and it's a package that is consumed on the Node side, not on the browser, so I don't mind the extra bit of size.

@innocenzi
Copy link

Anthony Fu helped me, I just needed to make execa a development dependency instead of a normal one, which completely makes sense!

So @holazz to solve the issue, use rollup.inlineDependencies and make your ESM-only dependency a development dependency.

Alternatively, as @pi0 said, find the same lib exported as CJS (ora v5.x), or finally, use dynamic imports.

Hopefully this solves the issue for anyone stumbling upon it.

@holazz
Copy link
Author

holazz commented Jun 3, 2022

Anthony Fu helped me, I just needed to make execa a development dependency instead of a normal one, which completely makes sense!

So @holazz to solve the issue, use rollup.inlineDependencies and make your ESM-only dependency a development dependency.

Alternatively, as @pi0 said, find the same lib exported as CJS (ora v5.x), or finally, use dynamic imports.

Hopefully this solves the issue for anyone stumbling upon it.

Thank You Kindly! rollup.inlineDependencies should not be what I want, I am currently using the 5.x version of ora.

@pi0 pi0 closed this as completed Jul 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants