Skip to content
Back to blog

ESBuild Common Pitfalls Guide

Notes on esbuild alias resolution, plugin cascade handling, and decorator compatibility, plus how to adjust default exports for Vue class components.

Alias Resolution

ESBuild has its own alias configuration, and in a ts project, ESBuild also directly uses the aliases from tsconfig.json.

As a result, aliases in tsconfig do not only take effect when building types; this is different from mainstream build tools such as Vite, Rollup, and webpack.

If the tsconfig configuration is messy, the build may look up the wrong files, causing the build to fail or producing incorrect output.

transform

ESBuild has no separate transform stage, only resolve and load.

Once a file has been handled by a plugin's load and a non-undefined or non-null value is returned, the onLoad callbacks of other plugins will no longer receive that file, so they cannot continue processing it.

Therefore you need an external cascade plugin, such as esbuild-plugin-pipe or esbuild-plugin-transform, to chain plugins together.

Decorators

Syntax Parsing

In ESBuild, only ts and tsx syntax supports decorators, and the decorator feature must be enabled in tsconfig.

Code written in .js files is not processed by ts, so decorators cannot be used directly.

The solution is to configure loader, pointing .js syntax parsing to the ts parser and .jsx to the .tsx parser.

When handling single-file syntax such as vue, the syntax cannot be mapped directly, so you need a plugin that uses plugin cascading to modify the loader after plugins like esbuild-vue have finished processing, for example:

export default {
  name: 'fix-vue-syntax-loader',
  setup(build) {
    build.onLoad(/\.vue$/, async (args) => {
      const contents = await readFile(args)

      return {
        contents,
        loader: 'tsx',
      }
    })
  },
}

Default Export Decorators

When using vue-class in vue, the compilation turns export default class name into the form var name = class {}; export default name;, so esbuild cannot recognize a standard class, which causes the decorator application to fail.

If you need to support the vue-class style, change it to:

@Component
class name extends Vue {
  // xxx
}

export default name