執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

僅移除空白字元

使用 Bun 的 JavaScript 和 TypeScript 壓縮器減少包大小

Bun 內建了一個快速的 JavaScript 和 TypeScript 壓縮器。根據程式碼庫的不同,它可以將包體積減少 80% 或更多。它還可以讓輸出程式碼執行得更快。壓縮器會執行數十種最佳化,包括常量摺疊、死程式碼消除和語法轉換。與其他壓縮器不同,Bun 的壓縮器能讓 bun build 執行得更快,因為需要列印的程式碼更少。

CLI 用法

啟用所有壓縮

使用 --minify 標誌啟用所有壓縮模式:

bash
bun build ./index.ts --minify --outfile=out.js

--minify 標誌啟用:

  • 空白字元壓縮
  • 語法壓縮
  • 識別符號壓縮

生產模式

--production 標誌會自動啟用壓縮:

bash
bun build ./index.ts --production --outfile=out.js

--production 標誌還會:

  • 將 process.env.NODE_ENV 設定為 production
  • 啟用生產模式下的 JSX 匯入和轉換

細粒度控制

分別啟用特定的壓縮模式:

bash
# 僅移除空白字元
bun build ./index.ts --minify-whitespace --outfile=out.js

# 僅壓縮語法
bun build ./index.ts --minify-syntax --outfile=out.js

# 僅壓縮識別符號
bun build ./index.ts --minify-identifiers --outfile=out.js

# 組合特定模式
bun build ./index.ts --minify-whitespace --minify-syntax --outfile=out.js

JavaScript API

使用 Bun 的打包器進行程式設計時,通過 minify 選項設定壓縮:

TypeScript
await Bun.build({
  entrypoints: ["./index.ts"],
  outdir: "./out",
  minify: true, // 啟用所有壓縮模式
});

細粒度控制則傳入物件:

TypeScript
await Bun.build({
  entrypoints: ["./index.ts"],
  outdir: "./out",
  minify: {
    whitespace: true,
    syntax: true,
    identifiers: true,
  },
});

壓縮模式

Bun 的壓縮器有三種彼此獨立的模式,你可以分別或同時啟用。

空白字元壓縮(--minify-whitespace)

移除輸出中的所有多餘空白字元、換行和格式。

語法壓縮(--minify-syntax)

將 JavaScript 語法重寫為更短的等效形式,並執行常量摺疊、死程式碼消除及其他最佳化。

識別符號壓縮(--minify-identifiers)

根據使用頻率重新命名區域性變數和函式名為更短的識別符號。

所有轉換。

布林字面量縮短

模式: --minify-syntax

將布林字面量轉換為更短的表示式。

Input
true
false
Output
!0
!1

布林代數最佳化

模式: --minify-syntax

通過邏輯規則簡化布林表示式。

Input
if (!!x) y;
if (x && true) y;
if (x || false) y;
!true
!false
Output
if(x)y;
if(x)y;
if(x)y;
!1
!0

undefined 縮短

模式: --minify-syntax

用更短的等效表示式替換 undefined。

Input
undefined
let x = undefined;
Output
void 0
let x=void 0;

undefined 相等性最佳化

模式: --minify-syntax

最佳化與 undefined 的寬鬆相等檢查。

Input
x == undefined
x != undefined
Output
x == null
x != null

Infinity 縮短

模式: --minify-syntax

將 Infinity 轉換為數學表示式。

輸入
Infinity
-Infinity
輸出
1/0
-1/0

typeof 最佳化

模式: --minify-syntax

最佳化 typeof 對比並求值常量 typeof 表示式。

Input
typeof x === 'undefined'
typeof x !== 'undefined'
typeof require
typeof null
typeof true
typeof 123
typeof "str"
typeof 123n
Output
typeof x>'u'
typeof x<'u'
"function"
"object"
"boolean"
"number"
"string"
"bigint"

數字格式化

模式: --minify-syntax

以最緊湊形式格式化數字。

Input
10000
100000
1000000
1.0
-42.0
Output
1e4
1e5
1e6
1
-42

算術常量摺疊

模式: --minify-syntax

編譯時計算算術運算。

Input
1 + 2
10 - 5
3 * 4
10 / 2
10 % 3
2 ** 3
Output
3
5
12
5
1
8

位運算常量摺疊

模式: --minify-syntax

編譯時計算位運算。

Input
5 & 3
5 | 3
5 ^ 3
8 << 2
32 >> 2
~5
Output
1
7
6
32
8
-6

字串拼接

模式: --minify-syntax

編譯時合併字串字面量。

Input
"a" + "b"
"x" + 123
"foo" + "bar" + "baz"
Output
"ab"
"x123"
"foobarbaz"

字串索引

模式: --minify-syntax

編譯時計算字串字元訪問。

Input
"foo"[2]
"hello"[0]
Output
"o"
"h"

模板字面量摺疊

模式: --minify-syntax

編譯時計算帶常量表達式的模板字面量。

Input
`a${123}b`
`result: ${5 + 10}`
Output
"a123b"
"result: 15"

模板字面量轉字串

模式: --minify-syntax

將不包含插值的模板字面量轉換為普通字串。

輸入
`Hello World`
`Line 1
Line 2`
輸出
"Hello World"
"Line 1\nLine 2"

字串引號最佳化

模式: --minify-syntax

選擇最優引號以減少轉義。

Input
"It's a string"
'He said "hello"'
`Simple string`
Output
"It's a string"
'He said "hello"'
"Simple string"

陣列展開內聯

模式: --minify-syntax

內聯對常量陣列的陣列展開操作。

Input
[1, ...[2, 3], 4]
[...[a, b]]
Output
[1,2,3,4]
[a,b]

陣列索引

模式: --minify-syntax

編譯時計算常量陣列訪問。

Input
[x][0]
['a', 'b', 'c'][1]
['a', , 'c'][1]
Output
x
'b'
void 0

屬性訪問最佳化

模式: --minify-syntax

可用時將括號訪問轉換為點訪問。

Input
obj["property"]
obj["validName"]
obj["123"]
obj["invalid-name"]
Output
obj.property
obj.validName
obj["123"]
obj["invalid-name"]

比較摺疊

模式: --minify-syntax

編譯時計算常量比較。

Input
3 < 5
5 > 3
3 <= 3
5 >= 6
"a" < "b"
Output
!0
!0
!0
!1
!0

邏輯操作摺疊

模式: --minify-syntax

簡化帶常量值的邏輯操作。

Input
true && x
false && x
true || x
false || x
Output
x
!1
!0
x

空值合併摺疊

模式: --minify-syntax

編譯時計算已知值的空值合併操作。

Input
null ?? x
undefined ?? x
42 ?? x
Output
x
x
42

逗號表示式簡化

模式: --minify-syntax

移除無副作用的逗號序列表達式。

Input
(0, x)
(123, "str", x)
Output
x
x

三元條件摺疊

模式: --minify-syntax

編譯時計算常量條件的三元表示式。

輸入
true ? a : b
false ? a : b
x ? true : false
x ? false : true
輸出
a
b
x ? !0 : !1
x ? !1 : !0

一元表示式摺疊

模式: --minify-syntax

簡化一元操作。

Input
+123
+"123"
-(-x)
~~x
!!x
Output
123
123
- -x
~~x
!!x

雙重否定移除

模式: --minify-syntax

移除不必要的雙重否定。

Input
if (!!x) y;
!!!x
Output
if(x)y;
!x

if 語句最佳化

模式: --minify-syntax

最佳化常量條件的 if 語句。

Input
if (true) x;
if (false) x;
if (x) { a; }
if (x) {} else y;
Output
x;
// 移除
if(x)a;
if(!x)y;

死程式碼消除

模式: --minify-syntax

移除不可達和無副作用程式碼。

Input
if (false) {
  unreachable();
}
function foo() {
  return x;
  deadCode();
}
Output
function foo(){return x}

不可達分支移除

模式: --minify-syntax

移除永遠不會執行的分支。

Input
while (false) {
  neverRuns();
}
Output
// 完全移除

空塊移除

模式: --minify-syntax

移除空塊和多餘的大括號。

Input
{ }
if (x) { }
Output
;
// 移除

單語句塊展開

模式: --minify-syntax

移除單語句塊多餘的大括號。

Input
if (condition) {
  doSomething();
}
Output
if(condition)doSomething();

TypeScript 列舉內聯

模式: --minify-syntax

編譯時內聯 TypeScript 列舉值。

Input
enum Color { Red, Green, Blue }
const x = Color.Red;
Output
const x=0;

純淨標註支援

模式: 始終生效

遵循 /*@__PURE__*/ 標註以進行搖樹最佳化(移除未使用的程式碼)。

Input
const x = /*@__PURE__*/ expensive();
// 如果 x 未使用...
Output
// 完全移除

識別符號重新命名

模式: --minify-identifiers

根據使用頻率重新命名區域性變數為更短的名稱。

Input
function calculateSum(firstNumber, secondNumber) {
  const result = firstNumber + secondNumber;
  return result;
}
Output
function n(t,u){const c=t+u;return c}

命名策略:

  • 使用頻率最高的識別符號會獲得最短的名稱;Bun 會根據每個字元在原始碼中的出現頻率對字母排序,因此最先使用的名稱通常是 t、e 和 n 這樣的字母,而不是 a、b、c
  • 單字元:a-z、A-Z 和 _(共 53 個名稱;單獨的 $ 已保留)
  • 雙字元:第二個字元也可以是數字(最多 3,456 個名稱)
  • 根據需要使用三個或更多字元

保留識別符號:

  • JavaScript 關鍵字和保留字
  • 全域性識別符號
  • 命名匯出(保持 API 穩定)
  • CommonJS 名稱:exports、module。

空白字元移除

模式: --minify-whitespace

移除所有多餘空白。

Input
function add(a, b) {
    return a + b;
}
let x = 10;
Output
function add(a,b){return a+b}let x=10;

分號最佳化

模式: --minify-whitespace

僅在必要時插入分號。

Input
let a = 1;
let b = 2;
return a + b;
Output
let a=1;let b=2;return a+b

運算子空格移除

模式: --minify-whitespace

移除運算子周圍空格。

Input
a + b
x = y * z
foo && bar || baz
Output
a+b
x=y*z
foo&&bar||baz

註釋移除

模式: --minify-whitespace

移除註釋,但保留重要的許可證註釋。

Input
// 該註釋被移除
/* 這個也是 */
/*! 但該許可證註釋被保留 */
function test() { /* 內聯註釋 */ }
Output
/*! 但該許可證註釋被保留 */
function test(){}

物件和陣列格式化

模式: --minify-whitespace

移除物件和陣列字面量內空白。

Input
const obj = {
    name: "John",
    age: 30
};
const arr = [1, 2, 3];
Output
const obj={name:"John",age:30};const arr=[1,2,3];

控制流格式化

模式: --minify-whitespace

移除控制結構內空白。

Input
if (condition) {
    doSomething();
}
for (let i = 0; i < 10; i++) {
    console.log(i);
}
Output
if(condition)doSomething();for(let i=0;i<10;i++)console.log(i);

函式格式化

模式: --minify-whitespace

移除函式宣告內空白。

Input
function myFunction(param1, param2) {
    return param1 + param2;
}
const arrow = (a, b) => a + b;
Output
function myFunction(param1,param2){return param1+param2}const arrow=(a,b)=>a+b;

括號最小化

模式: 始終生效

僅在優先順序需要時新增括號。

Input
(a + b) * c
a + (b * c)
((x))
Output
(a+b)*c
a+b*c
x

模板字面量值摺疊

模式: --minify-syntax

將非字串插值值轉為字串並摺疊進模板。

Input
`hello ${123}`
`value: ${true}`
`result: ${null}`
`status: ${undefined}`
`big: ${10n}`
Output
"hello 123"
"value: true"
"result: null"
"status: undefined"
"big: 10"

字串長度常量摺疊

模式: --minify-syntax

編譯時計算字串字面量的 .length 屬性。

Input
"hello world".length
"test".length
Output
11
4

建構函式呼叫簡化

模式: --minify-syntax

簡化內建型別的建構函式呼叫。

Input
new Object()
new Object(null)
new Object({a: 1})
new Array()
new Array(x, y)
Output
{}
{}
{a:1}
[]
[x,y]

單屬性物件內聯

模式: --minify-syntax

內聯只有單個屬性的物件的屬性訪問。

Input
({fn: () => console.log('hi')}).fn
Output
() => console.log('hi')

字串 charCodeAt 常量摺疊

模式: 始終生效

對 ASCII 字串字面量計算 charCodeAt()。

輸入
"hello".charCodeAt(1)
"A".charCodeAt(0)
輸出
101
65

void 0 等價 null 相等轉換

模式: --minify-syntax

將與 void 0 的寬鬆相等轉換為 null,因為兩者等價。

Input
x == void 0
x != void 0
Output
x == null
x != null

取反運算子最佳化

模式: --minify-syntax

將取反運算子移至逗號表示式內。

Input
-(a, b)
-(x, y, z)
Output
a,-b
x,y,-z

Import.meta 屬性內聯

模式: 打包模式下

建置時內聯已知的 import.meta 屬性值。

Input
import.meta.dir
import.meta.file
import.meta.path
import.meta.url
Output
"/path/to/directory"
"filename.js"
"/full/path/to/file.js"
"file:///full/path/to/file.js"

變數宣告合併

模式: --minify-syntax

合併相鄰的相同型別變數宣告。

輸入
let a = 1;
let b = 2;
const c = 3;
const d = 4;
輸出
let a=1,b=2;
const c=3,d=4;

表示式語句合併

模式: --minify-syntax

使用逗號運算子合併相鄰表示式語句。

Input
console.log(1);
console.log(2);
console.log(3);
Output
console.log(1),console.log(2),console.log(3);

return 語句合併

模式: --minify-syntax

合併 return 前的表示式,使用逗號運算子。

輸入
console.log(x);
return y;
輸出
return console.log(x),y;

throw 語句合併

模式: --minify-syntax

合併 throw 前的表示式,使用逗號運算子。

Input
console.log(x);
throw new Error();
Output
throw(console.log(x),new Error());

TypeScript 列舉跨模組內聯

模式: --minify-syntax(打包模式)

跨模組邊界內聯列舉值。

輸入
// lib.ts
export enum Color { Red, Green, Blue }

// 輸入(main.ts)
import { Color } from './lib';
const x = Color.Red;
輸出
const x=0;

計算屬性列舉內聯

模式: --minify-syntax

內聯用作計算屬性物件屬性的列舉值。

Input
enum Keys { FOO = 'foo' }
const obj = { [Keys.FOO]: value }
Output
const obj={foo:value}

箭頭函式主體簡化

模式: --minify-syntax

當箭頭函式僅傳回值時,使用表示式主體語法。

輸入
() => { return x; }
(a) => { return a + 1; }
輸出
() => x
a => a + 1

物件屬性簡寫

模式: 始終生效

當屬性名與值的識別符號相同時,使用簡寫語法。

Input
{ x: x, y: y }
{ name: name, age: age }
Output
{ x, y }
{ name, age }

移除 debugger 語句

模式: --drop=debugger

移除程式碼中的 debugger 語句。

Input
function test() {
  debugger;
  return x;
}
Output
function test(){return x}

移除 console 呼叫

模式: --drop=console

移除所有 console.* 方法呼叫。

Input
console.log("debug");
console.warn("warning");
x = console.error("error");
Output
void 0;
void 0;
x=void 0;

移除自定義函式呼叫

模式: --drop=<name>

移除對指定全域性函式及其方法的呼叫。

輸入
assert(condition);
assert.equal(a, b);
輸出(使用
void 0;
void 0;

保留名稱

為了在壓縮識別符號的同時保留原始函式名和類名以便除錯,請使用 --keep-names 標誌:

bash
bun build ./index.ts --minify --keep-names --outfile=out.js

或者在 JavaScript API 中:

TypeScript
await Bun.build({
  entrypoints: ["./index.ts"],
  outdir: "./out",
  minify: {
    identifiers: true,
    keepNames: true,
  },
});

--keep-names 會在繼續壓縮識別符號的同時,保留函式和類的 .name 屬性。

組合範例

同時使用三種壓縮模式:

input.ts
const myVariable = 42;

const myFunction = () => {
  const isValid = true;
  const result = undefined;
  return isValid ? myVariable : result;
};

const output = myFunction();
output.js
// Output with --minify (20 bytes, 89% reduction)
var t=()=>42,e=t();

何時使用壓縮

適用 --minify 的場景:

  • 生產環境包
  • 降低 CDN 頻寬成本
  • 提升頁面載入速度

適用單獨模式的場景:

  • --minify-whitespace: 在不改變語義的情況下減小體積
  • --minify-syntax: 在保留可讀識別符號以便除錯的同時生成更小的輸出
  • --minify-identifiers: 最大限度地減小體積(結合 --keep-names 以獲得更好的堆疊跟蹤)

避免壓縮的場景:

  • 開發建置(除錯更困難)
  • 需要可讀錯誤資訊時
  • 程式碼庫供消費者閱讀原始碼的庫。