esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Issue with hybrid module import when using cjs

Open euberdeveloper opened this issue 1 year ago • 5 comments

I am building a module with esbuild. It uses euberlog as a dependency, which is an hybrid module providing both esm and cjs support.

In my code I therefore use:

import logger from 'euberlog';

And then I compile it with esbuild:

const shared = {
        platform: 'node',
        entryPoints: ['source/index.ts'],
        bundle: true,
        minify: true,
        treeShaking: true,
        sourcemap: true
    };

    build({
        ...shared,
        outfile: 'bundled/lib/commonjs/index.js',
        format: 'cjs',
        external: getExternalDependencies()
    });

It is actually built both for esm and cjs. The problem is that if I import the cjs module somewhere, I have the error:

TypeError: i.default.info is not a function

and then if I patch the code and print i, I see that the result is:

{ default: { Logger: [Getter], default: [Getter] }, Logger: [Getter] }

It seems like that esbuild translates the first import (import logger from 'euberlog') as import * as logger from 'euberlog', but this does not make sense.

euberdeveloper avatar Mar 09 '23 22:03 euberdeveloper

I don't think I can reproduce this given your description. Here's the code I tried:

import logger_esm from 'euberlog'
logger_esm.info('esm')

const logger_cjs = require('euberlog').default
logger_cjs.info('cjs')

Bundling that with esbuild --bundle index.ts --outfile=out.js --platform=node produces a file that prints this:

[INFO] esm
[INFO] cjs

So everything seems fine. You have to provide a way to independently reproduce your issue in your issue report.

evanw avatar Mar 09 '23 23:03 evanw

The source code for the cjs does not use require, it uses import logger from 'euberlog'

Then, via typescript, it is built in a wrong way, I think by esbuild

Here is the repo I'm using, the command is npm run bundle and the cjs output is in /bundled/lib/commonjs

euberdeveloper avatar Mar 10 '23 01:03 euberdeveloper

The source code for the cjs does not use require, it uses import logger from 'euberlog'

Then, via typescript, it is built in a wrong way, I think by esbuild

Here is the repo I'm using, the command is npm run bundle and the cjs output is in /bundled/lib/commonjs

Does this add enough information to replicate the issue?

euberdeveloper avatar Mar 10 '23 18:03 euberdeveloper

I think I'm experiencing this breaking behavior with my packages. If I have the following code in my package:

// example-cjs
export default function example() {
  // some code
}

and import it like this

import example from 'example-cjs';

console.log(example);

It logs { default: [Getter] } which doesn't makes sense at all. I'll try to make a repro soon.

Edit: Here's the repro: https://gist.github.com/lxsmnsyc/e7746ed2ebd31c421eaf4bc33c1962a3

lxsmnsyc avatar Mar 30 '23 10:03 lxsmnsyc

Any news?

euberdeveloper avatar Jan 10 '24 23:01 euberdeveloper