Esbuild configuration documentation

Esbuild

Why choose esbuild?

In short: esbuild is written in go language, the compilation speed is fast, and it supports many environments.
Exactly how fast: Its compilation speed is more than 100 times
that of ordinary compilation plugins Its API can be accessed in three ways: command line, JavaScript and Go, and the document is still only one

Install

npm install esbuild

basic command

version

esbuild --version

Construct

esbuild app.jsx --bundle --outfile=out.js

quick conversion

echo 'let x: number = 1' | npx esbuild --loader=ts
# let x = 1;

API

Transform API

The conversion API calls only operate on a single string and do not access the file system. This makes it ideal for use in environments without a filesystem (like a browser), or as part of another toolchain. Here is a simple transformation:

echo 'let x: number = 1' | npx esbuild --loader=ts
# let x = 1;

Basic options:

advanced options:

Build API

Build API calls to operate on one or more files in the file system. This allows files to reference each other and be bundled together. Here's a simple build:

echo 'let x: number = 1' > in.ts
esbuild in.ts --outfile=out.js
cat out.js
# let x = 1;

Basic options:

advanced options:

basic option

Bundle

After enabling, package your delegates into a package (file)
For example,
you have the following files
/src/index.js

import {
    
     doSomething } from './utils'
doSomething()

/src/utils.js

export function doSomething() {
    
    }

Excuting an order

npx esbuild ./src/index.js --bundle --outfile=bundle.js

packaged is abundle.js

function doSomething() {
    
    }
doSomething()

If the bundle is not enabled, it will be packaged bundle.jslike this

import {
    
     doSomething } from "./utils";
doSomething();
Define

Define a globally accessible variable
as an example
index.js

console.log(**DEFINE**)

Excuting an order

npx esbuild ./src/index.js --bundle --outfile=./bundle.js "--define:__DEFINE__=\"define\"

Package result
bundle.js

console.log("define")
Entry points

It is the entry file list, the parameters followed by esbuild
are examples
index.js

console.log('index')

utils.js

console.log('utils')

execute script

npx esbuild index.js utils.js --outdir=out
# 或者
npx esbuild ./** --outdir=out
# 或者
npx esbuild out1=index.js out2=utils.js --outdir=out
External

Mark a file or package as an external file, which will be automatically excluded when building
an example
index.js

require("fsevents")

execute script

npx esbuild index.js --bundle --external:fsevents --platform=node --outfile=bundle.js

illustrate

This api is generally used for commenJs packages.
For example, the packaged bundle.js is used for the code of the node environment, so the content we packaged should not package the content of the node_modules package into bundle.js, but should use the bundle .js, you should include its dependencies in the local node_modules

Format

Determine the output format of the generated JavaScript file
Currently supports three parameters

  • iife
    self-invoking function
    !(function() { // ...do something })();
  • cjs
    startJs
    const xx = require("xx")
  • esm
    esModule
    import xx from "xx"
Inject

Allows you to replace global variables with imports from another file
process-shim.js

export let process = {
    
    
  cwd: () => ''
}

entry.js

console.log(process.cwd())

Excuting an order

npx esbuild entry.js --bundle --inject:./process-shim.js --outfile=bundle.js

bundle.js

let process = {
    
    cwd: () => ""};
console.log(process.cwd());

illustrate

You can inject the parsing function of jsx syntax through this api.
For example, you can automatically import react and provide functions such as React.createElement.
For details, please refer to JSX DOC

Loader

This option changes how a given input file is interpreted. For example, the js loader interprets the file as JavaScript and the css loader interprets the file as css

npx esbuild index.js --bundle --loader:.png=dataurl --loader:.svg=text
# 或者
echo 'import index = require("./index")' | npx esbuild --loader=ts --bundle
# 或者
echo 'let x: number = 1' | npx esbuild --loader=ts
# let x = 1;

Notice

esbuild only converts ts syntax to js syntax without type verification

Minify

Generated code will be minimized

echo 'fn = obj => { return obj.x }' | npx esbuild --minify
# fn=n=>n.x;
# 或者
echo 'fn = obj => { return obj.x }' | npx esbuild --minify-whitespace
# fn=obj=>{return obj.x};
# 或者
echo 'fn = obj => { return obj.x }' | npx esbuild --minify-identifiers
#fn = (n) => {
    
    
#  return n.x;
#};
# 或者
echo 'fn = obj => { return obj.x }' | npx esbuild --minify-syntax
#fn = (obj) => obj.x;

Notice

  • When minification is enabled, you should probably also set the target option
    By default, esbuild takes advantage of modern JavaScript features to make your code smaller
    eg: a === undefined || a === = null ? 1 : a is ok Minified to a??1
    If you don't want esbuild to take advantage of modern JavaScript features when minified, you should use an older language like:--target=es6
  • In JavaScript template literals, the character escape sequence \n will be replaced with a newline
    character String literals are also converted to template literals if the target supports them and doing so results in smaller output
    . Not a bug, narrowing means you're asking for smaller output, the escape sequence \n takes two bytes, and the newline character takes one byte
  • By default, esbuild will not minify the names of top-level declarations.
    This is because esbuild has no idea what you're going to do with the output.
    You might be injecting the minified code into some other code, in which case the minified top-level declaration names would be Unsafe
    setting the output format (or enabling the binding, which will choose an output format for you if you haven't set it already) tells esbuild that the output will operate in its own scope, which means it can safely reduce top-level declaration names .
  • Minification is not 100% safe for JavaScript code.
    This is true for esbuild as well as other popular JavaScript minifiers such as terser. In
    particular, esbuild is not designed to preserve the value of a function call .tostring()
    so The reason for doing this is that if all the code in all functions has to be kept verbatim, the minification does almost nothing and is effectively useless However, this means that JavaScript
    code that depends on the return value of .tostring() is in the May break when minimized
    For example, some modes in the AngularJS framework are in
  • By default, esbuild does not preserve the value of .name on function and class objects.
    This is because most code does not depend on this attribute, and using shorter names is an important size optimization.
    However, some code does depend on .name Attributes are registered and bound
    If you need to rely on this option, you should enable the keep names option.
  • Certain JavaScript features can disable esbuild's optimizations, including minification.
    Specifically, using direct eval or with statements can prevent esbuild from renaming identifiers to smaller names, as these features cause identifier binding to happen at runtime, instead of compile time
    which is probably irrelevant since most people don't do
Out is

The output directory for the build operation

npx esbuild index.js --bundle --outdir=out
Outfile

The output file of the build operation

npx esbuild index.js --bundle --outfile=bundle.js
Platform

By default, esbuild's binder is configured to generate code for the browser.
If your packaged code is intended to run in node, you should set platform to node.

# 自调用函数 (默认)
npx esbuild index.js --bundle --platform=browser
# 或者 commenJs
npx esbuild index.js --bundle --platform=node
# 或者 Es module
npx esbuild index.js --bundle --platform=neutral
Serve


An http server similar to webpack-server, which means that you don't have to execute esbuild execution commands all the time after changing the code

npx esbuild src/index.js --servedir=www --outdir=www/js --bundle

Then create the www directory, createindex.html

<script script src="js/index.js"></script>

or you just need to serve your js

npx esbuild src/index.js --outfile=out.js --bundle --serve=8000

index.html

<script src="http://localhost:8000/out.js"></script>

parameter

 interface ServeOptions {
    
    
    port?: number;
    host?: string;
    servedir?: string;
    onRequest?: (args: ServeOnRequestArgs) => void;
  }

Proxy server example

const esbuild = require('esbuild');
const http = require('http');

// 在一个随机的本地端口上启动esbuild服务器
esbuild.serve(
  {
    servedir: __dirname,
  }, 
  {
    // ... 构建选项 ...
  }
).then(result => {
  // result 告诉我们 esbuild 的本地服务器在哪里
  const {host, port} = result

  // 然后在端口上启动代理服务器 3000
  http.createServer((req, res) => {
    const options = {
      hostname: host,
      port: port,
      path: req.url,
      method: req.method,
      headers: req.headers,
    }

    // 将每个传入的请求转发给esbuild
    const proxyReq = http.request(options, proxyRes => {
      // 如果esbuild返回“未找到”,发送一个自定义404页面
      if (proxyRes.statusCode === 404) {
        res.writeHead(404, { 'Content-Type': 'text/html' });
        res.end('<h1>A custom 404 page</h1>');
        return;
      }

      // 否则,将响应从esbuild转发到客户端
      res.writeHead(proxyRes.statusCode, proxyRes.headers);
      proxyRes.pipe(res, { end: true });
    });

    // 将请求体转发给esbuild
    req.pipe(proxyReq, { end: true });
  }).listen(3000);
});
Sourcemap

Let the packaged code have a source code mapping file, that is to say, you can view the source code when debugging in the browser

# linked (默认)
# 生成为一个单独的 .js.map 源映射, 输出文件 bundle.js 包含一个特殊的 //# sourceMappingURL= 注释,该注释指向 .js.map。这样,当您打开调试器时,浏览器就知道在哪里找到给定文件的源映射
npx esbuild index.js --sourcemap --outfile=bundle.js

# external
# 生成为一个单独的 .js.map 源映射, 但与 linked 模式不同的是, 输出文件 bundle.js 不包含 //# sourceMappingURL=
npx esbuild index.js --sourcemap=external --outfile=bundle.js

# inline
# 不生成 .js.map 文件,注解 //# sourceMappingURL= 后边跟着一串映射的 base64 数据
npx esbuild index.js --sourcemap=inline --outfile=bundle.js

# both
# inline 和 external 的结合
npx esbuild index.js --sourcemap=both --outfile=bundle.js

Notice

In the browser, you need to turn on the Enable source maps button in the settings
In nodejs, v12.12.0 has built-in support for the original map
node --enable-source-maps index.js

Splitting

Code splitting, packaging the same code into a common js
note: this api is still under development, currently only applicable to esm output format

npx esbuild index.js utils.js --bundle --splitting --outdir=out --format=esm
Target

The environment that the packaged js needs to support, the default is esnext, which is the latest javascript and css syntax and features, which means that the code packaged by default does not naturally support ie (that's good)

npx esbuild index.js --target=es2020,chrome58,firefox57,safari11,edge16,node12
Watch

esbuild listens for changes on the file system and rebuilds if a file change might invalidate the build

npx esbuild index.js --outfile=bundle.js --bundle --watch

When you use it in js, watch can be an object, for example:

require('esbuild').build({
    
    
  entryPoints: ['index.js'],
  outfile: 'bundle.js',
  bundle: true,
  watch: {
    
    
    onRebuild(error, result) {
    
    
      if (error) console.error('监听失败:', error)
      else console.log('监听成功:', result)
      // result.stop() 可以停止监听
    },
  },
}).then(result => {
    
    
  console.log('监听中...')
})
Write

By default, the build api will automatically write the built content to the system file, write: false can prevent this behavior
for example

let result = require('esbuild').buildSync({
    
    
  entryPoints: ['app.js'],
  sourcemap: 'external',
  write: false,
  outdir: 'out',
})

for (let out of result.outputFiles) {
    
    
  console.log(out.path, out.contents)
}

advanced options

Allow overwrite

Allow output files to overwrite input files (I guess no one would do that)
for example

npx esbuild index.js --outdir=. --allow-overwrite
# 这样你的 index.js 源代码会消失
Analyze

Generates an easy-to-read report on the bundle contents

npx esbuild --bundle index.js --outfile=bundle.js --minify --analyze
Asset names

When the loader option is file, add additional information to the packaged resource

# [name], [hash], [dir], [ext] 这四个顾名思义,任意组合
npx esbuild index.js --asset-names=assets/[name]-[hash] --loader:.png=file --bundle --outdir=out
Banner

Insert arbitrary strings at the beginning of generated JavaScript and CSS files, usually used to insert comments
There may be some problems running on git bash: https://github.com/evanw/esbuild/issues/2150

npx esbuild index.js --banner:js=//comment --banner:css=/*comment*/ --outfile=bundle.js
Charset

As the name suggests, set the character encoding

echo 'let a = 你好' | npx esbuild
# let a = \u4F60\u597D;
echo 'let a = 你好' | npx esbuild --charset=utf8
# let a = 你好;
Chunk names

The filename of the shared code block that is automatically generated when code splitting is enabled

# [name], [hash], [ext]
esbuild index.js --chunk-names=chunks/[name]-[hash] --bundle --outdir=out --splitting --format=esm
Color

Whether to enable color when building

echo 'typeof x == "null"' | npx esbuild --color=true
Conditions

To be honest, I don’t really understand the meaning and usefulness of this api, so the explanation here is relatively simple.
conditions allow you to redirect the same import path to different file locations

npx esbuild index.js --bundle --conditions=custom1,custom2

For example,
when we import "pkg/foo", it points to ./imported.mjs
When we require("pkg/foo"), it points to ./required.cjs

{
    
    
  "name": "pkg",
  "exports": {
    
    
    "./foo": {
    
    
      "import": "./imported.mjs",
      "require": "./required.cjs",
      "default": "./fallback.js"
    }
  }
}
Drop

Content that needs to be deleted before building, such as the console in the page

# 删除 debugger
npx esbuild index.js --drop:debugger
# 删除 console
npx esbuild index.js --drop:console
Entry names

Modify the entry file name. Generally, modifying the file name allows our users to use the latest functions.

# [name], [hash], [dir], [ext]
npx esbuild index.js --entry-names=[dir]/[name]-[hash] --bundle --outdir=out
Footer

Same issue as Banner API
Inserts arbitrary strings at the end of generated JavaScript and CSS files, usually for inserting comments

npx esbuild index.js --footer:js=//comment --footer:css=/*comment*/ --outfile=bundle.js
Global name

It only works when formatis iife, setting the name of the global variable, that is, assigning iifethe self-invoking function to the variable

echo 'module.exports = "test"' | npx esbuild --format=iife --global-name=vue
# 或者
echo 'module.exports = "test"' | npx esbuild --format=iife --global-name='vue.test["xx"]'
Ignore annotations

Since JavaScript is a dynamic language, it can sometimes be very difficult for the compiler to identify unused code, so the community developed annotations to help tell the compiler which code should be considered side-effect free and can be removed. Currently esbuild supports two forms of side effect annotations

  • An inline /* @PURE * / comment before a function call tells esbuild that the function call can be removed if the resulting value is not used.
  • The sideEffects field of package.json is used to tell esbuild which files in your package can be deleted if all imported files in your package are not used in the end. This is a Webpack convention, and many libraries published to npm already include this field in their package definitions. You can read more about this field in the Webpack documentation.
npx esbuild index.js --bundle --ignore-annotations
Incremental

Call the build API of esbuild repeatedly with the same option to turn on this option

JSX

Handle JSX syntax, either convert JSX to JS (default), or keep JSX syntax in the output

echo '<div/>' | npx esbuild --jsx=preserve --loader=jsx
# <div />;

echo '<div/>' | npx esbuild --loader=jsx
# /* @__PURE__ */ React.createElement("div", null);
JSX factory

Sets the function called by the JSX element

echo '<div/>' | npx esbuild --jsx-factory=h --loader=jsx
# /* @__PURE__ */ h("div", null);
JSX fragment

Sets the function called by the JSX fragment

echo '<>content</>' | npx esbuild --jsx-fragment=Fragment --loader=jsx
# /* @__PURE__ */ React.createElement(Fragment, null, "content");
Keep names

Set the name attribute of the function to "fn", this API does not understand its meaning

npx esbuild index.js --minify --keep-names
Legal comments
  • none
    don't keep anylegal comment
  • inline
    keep alllegal comment
  • eof
    will legal commentmove to the end of the file.
  • linked
    moved legal commentinto the .LEGAL.txt file and linked it with a comment.
  • external
    will legal commentmove into the .LEGAL.txt file, but don't link it
npx esbuild index.js --legal-comments=eof
Log level

log level

  • silent
    Do not display any log output
  • error
    only displays errors
  • warning
    only displays warnings and errors
  • info
    shows warnings, errors, and output file summaries
  • debug
    logs all messages and some additional messages.
  • verbose
    generates lots of log messages
echo 'typeof x == "null"' | npx esbuild --log-level=error
Log limit

Control the number of printed logs, otherwise the console may be very stuck, the default is 10

npx esbuild index.js --log-limit=10
Main fields

When importing a package in node, define which field of package.json is imported

  • main
  • module
  • browser
npx esbuild index.js --bundle --main-fields=module,main
Mangle props

Pass a regular expression to esbuild, tell esbuild to automatically rewrite all properties that match this regular expression (very destructive api, use less) for
example
index.js

let x = {
    
     xx_: 'x' };
let y = {
    
     xx_: "y" };
# 它会将所有的以 _ 结尾的属性全部改掉
npx esbuild index.js --mangle-props=_$
# let x = { a: "x" };
# let y = { b: "y" };
Metafile

Generate some metadata about the build in JSON format

npx esbuild index.js --bundle --metafile=meta.json --outfile=out.js
Node paths

Global directory listing. These paths are searched in addition to looking for the node_modules directory in all parent directories

NODE_PATH=someDir npx esbuild index.js --bundle --outfile=bundle.js
Out extension

Customize the extension of the files generated by esbuild

npx esbuild index.js --bundle --outdir=dist --out-extension:.js=.mjs
Outbase

base path

npx esbuild src/pages/home/index.ts src/pages/about/index.ts --bundle --outdir=out --outbase=src
Preserve symlinks

This setting mirrors the --preserve-symlinks setting in node. If you use that setting (or the similar resolve.symlinks setting in Webpack), you will likely need to enable this setting in esbuild too. It can be enabled like this:

npx esbuild index.js --bundle --preserve-symlinks --outfile=bundle.js
Public path

loaderAdd a base path to the export string of each file loaded by this

npx esbuild index.js --bundle --loader:.png=file --public-path=https://www.example.com/v1 --outdir=out
Pure

Various JavaScript tools have a convention to precede a new or call expression with a special comment containing /* @ PURE / or / # PURE */, which means that the expression can be deleted if the resulting value is not used . It looks like this:

echo 'console.log("foo:", foo())' | npx esbuild --pure:console.log --minify
Resolve extensions

The file extension can be omitted when importing files after setting

npx esbuild index.js --bundle --resolve-extensions=.ts,.js
Source root

Set the mapping source code directory

npx esbuild index.js --sourcemap --source-root=https://raw.githubusercontent.com/some/repo/v1.2.3/
Sourcefile

Set up mapping source code files

cat index.js | npx esbuild --sourcefile=example.js --sourcemap
Sources content

Set the mapping source code content, do not know how to use

npx esbuild --bundle app.js --sourcemap --sources-content=false
Stdin

Usually used when there is no entry file, such as corresponding to piping a file to stdin on the command line

echo 'export * from "./another-file"' | npx esbuild --bundle --sourcefile=imaginary-file.js --loader=ts --format=cjs
Tree shaking

dead code removal

npx esbuild app.js --tree-shaking=true
Tsconfig

As the name suggests, setting tsconfig

npx esbuild index.ts --bundle --tsconfig=custom-tsconfig.json
Tsconfig raw
echo 'class Foo { foo }' | npx esbuild --loader=ts --tsconfig-raw='{"compilerOptions":{"useDefineForClassFields":true}}'
Working directory

Specify the working directory to use for the build

require('esbuild').buildSync({
    
    
  entryPoints: ['file.js'],
  absWorkingDir: process.cwd(),
  outfile: 'out.js',
})

Content Types

content type, each content type has an associated default loaderwhich you can override

  • JavaScript : js
    File extension: .js, .cjs,.mjs

You can configure targetproperties to control the version of the compiled code

Syntax transform Transformed when --target is below Example
Exponentiation operator es2016 a ** b
Async functions es2017 async () => {}
Spread properties es2018 let x = {…y}
Rest properties es2018 let {…x} = y
Optional catch binding es2019 try {} catch {}
Optional chaining es2020 a?.b
Nullish coalescing es2020 a ?? b
import.meta es2020 import.meta
Logical assignment operators es2021 a ??= b
Class instance fields esnext class { x }
Static class fields esnext class { static x }
Private instance methods esnext class { #x() {} }
Private instance fields esnext class { #x }
Private static methods esnext class { static #x() {} }
Private static fields esnext class { static #x }
Ergonomic brand checks esnext #x in y
Import assertions esnext import “x” assert {}
Class static blocks esnext class { static {} }

Also some syntax it won't convert

Syntax transform Unsupported when --target is below Example
Asynchronous iteration es2018 for await (let x of y) {}
Async generators es2018 async function* foo() {}
BigInt es2020 123n
Hashbang grammar esnext #!/usr/bin/env node
Top-level await esnext await import(x)
Arbitrary module namespace identifiers esnext export {foo as ‘f o o’}
  • TypeScript : tsor tsx
    file extensions: .ts, .tsx, .mts, .cts

TypeScript type declarations are parsed and ignored

Syntax feature Example
Interface declarations interface Foo {}
Type declarations type Foo = number
Function declarations function foo(): void;
Ambient declarations declare module ‘foo’ {}
Type-only imports import type {Type} from ‘foo’
Type-only exports export type {Type} from ‘foo’
Type-only import specifiers import {type Type} from ‘foo’
Type-only export specifiers export {type Type} from ‘foo’

Only typescript syntax extensions are supported and are always converted to JavaScript

Syntax feature Example Notes
Namespaces namespace Foo {}
Enums enum Foo { A, B }
Const enums const enum Foo { A, B }
Generic type parameters (a: T): T => a Not available with the tsx loader
JSX with types <Element/>
Type casts a as B and a
Type imports import {Type} from ‘foo’ Handled by removing all unused imports
Type exports export {Type} from ‘foo’ Handled by ignoring missing exports in TypeScript files
Experimental decorators @sealed class Foo {} The emitDecoratorMetadata flag is not supported
  • JSX: jsxtsx
  • JSON: json
  • CSS: css
  • Text: text
  • Binary: binary
  • Base64: base64
  • Data URL: dataurl
  • External file: file

Plugins

`Plugins`是新的,仍然处于实验阶段。在esbuild 1.0.0版本之前,它可能会随着新用例的出现而改变。您可以根据跟踪问题获得关于此特性的更新

Plugins 允许你将代码注入到构建过程的各个部分

寻找插件

https://github.com/esbuild/community-plugins

使用插件

一个esbuild插件是一个有名字和setup函数的对象。它们以数组的形式传递给构建API调用。每次构建API调用都运行一次setup函数

其他详情请查看Plugin

Guess you like

Origin blog.csdn.net/weixin_42335036/article/details/123960069