How to get esbuild to include internal dependencies when using typescript

Viewed 2543

I am working on a vscode extension and am using esbuild to do the bundling/minification. I want to use the jsonc-parser NPM module. When I do this, esbuild runs OK but the extension won't load, giving an error "Activating extension failed: Cannot find module './impl/format'". I can reproduce this in a smaller example than the whole vscode extension, see the following:

Main file

import * as jsonc from 'jsonc-parser'
const example = '// Some comment\n{"a":1,"b":2}'
console.log(`Parsing ${example}`)
const errors = []
const mexample = jsonc.parse(example, errors)
console.log(`Result: ${JSON.stringify(mexample, null, 2)}`)
console.log(`Errors: ${JSON.stringify(errors)}`)

Relevant bits of package.json

"scripts": {
    "run-bundle": "node out.js",
    "bundle": "esbuild index.ts --bundle --platform=node --outfile=out.js"
  },
  "dependencies": {
    "jsonc-parser": "^3.0.0"
  },
  "devDependencies": {
    "esbuild": "^0.12.28"
  }

In the bundled out.js I can see

      var formatter = require2("./impl/format");
      var edit = require2("./impl/edit");
      var scanner = require2("./impl/scanner");
      var parser = require2("./impl/parser");

So it looks like esbuild hasn't picked these 'internal dependencies' up for bundling.

I've tried some options in tsconfig.json and package.json with no success.

1 Answers

I raised an issue on GitHub and received the following explanation and work-around from user hyrious

This is because the jsonc-parser library exports a UMD file which uses require() indirectly, which prevents esbuild to analyze and bundle these dependencies. As a quick solution, you could use its ESM target in the module field by appending this option: --main-fields=module,main.

and from evanw

Having esbuild handle this automatically is out of scope since esbuild only handles require calls that can be statically-evaluated at compile time without partially-evaluating the input JavaScript code. The package not being bundler-friendly is a problem with the package, not with esbuild. As mentioned above, workarounds are:

  • Use --main-fields=module,main (may cause issues with other packages)
  • Write an esbuild plugin using onResolve to swap out just this one file (won't affect other packages)
  • Get Microsoft to make their code bundler-friendly
Related