Tilted sphere with longitudinal stripes Modern Web Guides Docs Blog Toggle darkmode

Plugins: Esbuild

Plugin for using esbuild in Web Dev Server and Web Test Runner. esbuild is a blazing fast build tool.

It can be used for fast single-file transforms, for example to transform TS, JSX, TSX and JSON to JS, or to transform modern JS to an older version of JS for older browsers.


Install the package:

npm i --save-dev @web/dev-server-esbuild

Add the plugin in your configuration file:

import { esbuildPlugin } from '@web/dev-server-esbuild';

export default {
  plugins: [esbuildPlugin({ ts: true, target: 'auto' })],

Single file transforms

Note that the esbuild plugin uses the esbuild single file transform API, transforming files as they are requested by the browser. We don't use esbuild's bundling API, so some features like module transformation are not available.


We expose the following options for esbuild. Most of them are a mirror of the esbuild API, check the esbuild docs to learn more about them.

type Loader =
  | 'js'
  | 'jsx'
  | 'ts'
  | 'tsx'
  | 'json'
  | 'text'
  | 'base64'
  | 'file'
  | 'dataurl'
  | 'binary';

interface EsbuildPluginArgs {
  target?: string | string[];
  js?: boolean;
  ts?: boolean;
  json?: boolean;
  jsx?: boolean;
  tsx?: boolean;
  jsxFactory?: string;
  jsxFragment?: string;
  loaders?: Record<string, Loader>;
  define?: { [key: string]: string };
  tsconfig?: string;


The target option defines what version of javascript to compile down to. This is primarily to support older browsers.

Auto target

We recommended setting target to auto, this is the default when you turn on a loader but needs to be enabled explicitly for JS transforms.

When target is auto, we look at the browser's user agent. If you're on the latest version of a browser that adopts modern javascript syntax at a reasonable pace, we skip any compilation work.

The current set of browsers are Chrome, Firefox and Edge. Otherwise we transform the code to a compatible version of javascript specific to that browser. This transformation is very fast.

Always auto

The auto-always option looks at the user agent, but doesn't skip the latest versions of modern browsers. It will always compile to a compatible target for that browser. Use this when you're using features not yet supported in the latest version of one of the modern browsers.

Browser and language target

The target option can be set to one or more browser or language targetversions, for example chrome80 or es2020. The property can be an array, so you can set multiple browser targets. While the auto target options are specific to this plugin, the browser and language target come directly from esbuild. Check the docs for more information.

No target

If target is set to esnext, transformation is skipped entirely.


Loaders transform different kinds of file formats to JS. The loaders option takes a mapping from file extension to loader name:

import { esbuildPlugin } from '@web/dev-server-esbuild';

export default {
  plugins: [esbuildPlugin({ loaders: { '.ts': 'ts', '.data': 'json' } })],

For a few common loaders, there are boolean options which act like shorthand for setting the file extension and loader.

import { esbuildPlugin } from '@web/dev-server-esbuild';

export default {
  plugins: [
      // shorthand for loaders: { '.ts': 'ts' }
      ts: true,
      // shorthand for loaders: { '.json': 'json' }
      json: true,
      // shorthand for loaders: { '.jsx': 'jsx' }
      jsx: true,
      // shorthand for loaders: { '.tsx': 'tsx' }
      tsx: true,



Transform all .ts files to javascript:

esbuildPlugin({ ts: true });

Transform all .ts files to javascript using settings from tsconfig.json. (The tsconfig.json file is not read by default.)

import { fileURLToPath } from 'url';

  ts: true,
  tsconfig: fileURLToPath(new URL('./tsconfig.json', import.meta.url)),


Transform all .jsx files to javascript:

esbuildPlugin({ jsx: true });

By default, jsx gets transformed to React.createElement calls. You can change this to the JSX style you are using.

For example when importing from preact like this:

import { h, Fragment } from 'preact';
esbuildPlugin({ jsx: true, jsxFactory: 'h', jsxFragment: 'Fragment' });

If you want to use jsx inside .js files you need to set up a custom loader:

esbuildPlugin({ loaders: { ['.js']: 'jsx' }, jsxFactory: 'h', jsxFragment: 'Fragment' });


Transform all .tsx files to javascript:

esbuildPlugin({ tsx: true });
esbuildPlugin({ tsx: true, jsxFactory: 'h', jsxFragment: 'Fragment' });


Transform all JS to older versions of JS:

esbuildPlugin({ target: 'auto' });

Transform TS, but don't transform any syntax:

esbuildPlugin({ ts: true, target: 'esnext' });