esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

esbuild improperly follows tsconfig.json paths, causing duplicated imports

Open laverdet opened this issue 2 years ago • 3 comments

When running esbuild in --bundle mode it seems to apply the tsconfig.json paths mapping before looking at package.json. This causes a condition where both the compiled JS output and original TS source are included in the final bundle. I believe that this is a violation of node's package specification: https://nodejs.org/api/packages.html#self-referencing-a-package-using-its-name

I've put together a very simple example of the issue at https://github.com/laverdet/esbuild-issue.

-> % git clone [email protected]:laverdet/esbuild-issue.git
[...]
-> % cd esbuild-issue 

-> % npm run -s run
# node main.js
dist dist

-> % npm run -s build
# npx esbuild --bundle main.js | node --input-type module
dist source

We can see the execution result of the bundled esbuild output disagrees with nodejs's output. This causes very difficult to troubleshoot variation of the dual package hazard.

laverdet avatar Jul 13 '22 17:07 laverdet

I discovered a workaround for this issue by passing --resolve-extensions=.js.

laverdet avatar Jul 13 '22 17:07 laverdet

Is there a reason why that package is publishing a tsconfig.json?

evanw avatar Jul 19 '22 14:07 evanw

It's an internal package which is set up in a pnpm monorepo. TypeScript has emit enabled so that we can run tools which depend on this package via the nodejs cli. We also use esbuild to create bundles for deployment.

I also find this surprising:

-> % cat entry.js 
import wow from "wow";
console.log(wow);

-> % cat wow.js 
export default "wow";

-> % cat tsconfig.json 
{
  "compilerOptions": {
    "paths": { "wow": [ "./wow.js" ] }
  }
}

-> % npx esbuild --bundle entry.js
(() => {
  // wow.js
  var wow_default = "wow";

  // entry.js
  console.log(wow_default);
})();

I think that this should fail to build since the TypeScript resolution configuration should have no effect on plain .js files. I believe that these two situations are caused by the same underlying issue.

laverdet avatar Jul 19 '22 15:07 laverdet