內容類型
所有內建的內容類型都列在下方。每個內容類型都有關聯的「載入器」,用來告訴 esbuild 如何詮釋檔案內容。有些檔案副檔名已經預設設定了載入器,不過預設值可以被覆寫。
#JavaScript
載入器:js
此載入器預設啟用於 .js
、.cjs
和 .mjs
檔案。.cjs
副檔名由節點用於 CommonJS 模組,而 .mjs
副檔名由節點用於 ECMAScript 模組。
請注意,預設情況下,esbuild 的輸出將利用所有現代 JS 功能。例如,a !==
將會在啟用縮小時變成 a ?? b
,這會使用來自 ES2020 版本 JavaScript 的語法。如果這不是你想要的,你必須指定 esbuild 的 target 設定,來說明你的輸出需要在哪些瀏覽器中正確運作。然後 esbuild 將避免使用對那些瀏覽器來說太新的 JavaScript 功能。
esbuild 支援所有現代 JavaScript 語法。不過,較新的語法可能不受較舊瀏覽器支援,因此你可能需要設定 target 選項,以適當地告訴 esbuild 將較新的語法轉換為較舊的語法。
這些語法功能永遠都會轉換為舊瀏覽器
語法轉換 | 語言版本 | 範例 |
---|---|---|
函數參數清單和呼叫中的尾隨逗號 | es2017 |
foo(a, b, ) |
數字分隔符號 | esnext |
1_000_000 |
這些語法功能會根據已設定的語言 目標 有條件地轉換為舊瀏覽器
語法轉換 | 當 --target 低於以下版本時轉換 |
範例 |
---|---|---|
指數運算子 | es2016 |
a ** b |
非同步函數 | es2017 |
async () => {} |
非同步迭代 | es2018 |
for await (let x of y) {} |
非同步產生器 | es2018 |
async function* foo() {} |
擴散屬性 | es2018 |
let x = {...y} |
剩餘屬性 | es2018 |
let {...x} = y |
可選的 catch 繫結 | es2019 |
try {} catch {} |
可選的鏈結 | es2020 |
a?.b |
空值合併 | es2020 |
a ?? b |
import.meta |
es2020 |
import.meta |
邏輯指派運算子 | es2021 |
a ??= b |
類別實例欄位 | es2022 |
class { x } |
靜態類別欄位 | es2022 |
class { static x } |
私有實例方法 | es2022 |
class { #x() {} } |
私有實例欄位 | es2022 |
class { #x } |
私有靜態方法 | es2022 |
class { static #x() {} } |
私有靜態欄位 | es2022 |
class { static #x } |
人體工學品牌檢查 | es2022 |
#x in y |
類別靜態區塊 | es2022 |
class { static {} } |
匯入斷言 | esnext |
import "x" assert {} |
自動存取器 | esnext |
class { accessor x } |
using 宣告 |
esnext |
using x = y |
這些語法功能目前永遠都會傳遞為未轉換
語法轉換 | 當 --target 低於以下版本時不支援 |
範例 |
---|---|---|
正規表示法 dotAll 旗標 |
es2018 |
/./s 1 |
正規表示法後向斷言 | es2018 |
/(?<=x)y/ 1 |
正規表示法命名擷取群組 | es2018 |
/(?<foo>\d+)/ 1 |
正規表示法 Unicode 屬性跳脫字元 | es2018 |
/\p{ASCII}/u 1 |
BigInt | es2020 |
123n |
頂層 await | es2022 |
await import(x) |
任意模組命名空間識別碼 | es2022 |
export {foo as 'f o o'} |
RegExp 比對索引 | es2022 |
/x(.+)y/d 1 |
Hashbang 語法 | esnext |
#!/usr/bin/env node |
裝飾器 | esnext |
@foo class Bar {} |
RegExp 集合表示法 | esnext |
/[\w--\d]/ 1 |
另請參閱 已完成 ECMAScript 提案清單 和 正在進行中的 ECMAScript 提案清單。請注意,雖然支援轉換包含頂層 await 的程式碼,但僅當 輸出格式 設定為 esm
時才支援套件化包含頂層 await 的程式碼。
#JavaScript 注意事項
使用 esbuild 搭配 JavaScript 時,您應注意以下事項
#ES5 支援不佳
目前不支援將 ES6+ 語法轉換為 ES5。不過,如果您使用 esbuild 轉換 ES5 程式碼,您仍應將 目標 設定為 es5
。這可防止 esbuild 在您的 ES5 程式碼中引入 ES6 語法。例如,沒有這個 flag,物件文字 {x: x}
會在縮小時變成 {x}
,字串 "a\nb"
會變成多行範本文字。這兩個替換都是因為產生的程式碼較短,但如果 目標 是 es5
,則不會執行這些替換。
#私有成員效能
私有成員轉換(針對 #name
語法)使用 WeakMap
和 WeakSet
來保留此功能的私有特性。這與 Babel 和 TypeScript 編譯器中的對應轉換類似。大多數現代 JavaScript 引擎(V8、JavaScriptCore 和 SpiderMonkey,但 ChakraCore 除外)對於大型 WeakMap
和 WeakSet
物件可能沒有良好的效能特性。
建立許多具有私有欄位或私有方法的類別實例,並使用此語法轉換,可能會為垃圾收集器造成大量負擔。這是因為現代引擎(ChakraCore 除外)將弱值儲存在實際的 map 物件中,而不是將其儲存在鍵本身的隱藏屬性中,而大型 map 物件可能會對垃圾收集造成效能問題。請參閱 此參考 以取得更多資訊。
#匯入遵循 ECMAScript 模組行為
您可能會嘗試在匯入需要該全域狀態的模組之前修改全域狀態,並預期它會正常運作。然而,JavaScript(因此 esbuild)實際上會將所有 import
陳述式「提升」到檔案的頂端,因此這樣做不會奏效
window.foo = {}
import './something-that-needs-foo'
有一些 ECMAScript 模組的破損實作(例如 TypeScript 編譯器)不遵循 JavaScript 規格的這方面規定。使用這些工具編譯的程式碼可能會「運作」,因為 import
已替換為對 require()
的內嵌呼叫,而後者忽略了提升的要求。但此類程式碼無法與真實的 ECMAScript 模組實作(例如 node、瀏覽器或 esbuild)搭配使用,因此撰寫此類程式碼並不可移植,也不建議這麼做。
正確的做法是將全域狀態修改移至其自己的 import 中。這樣它會在其他 import 之前執行
import './assign-to-foo-on-window'
import './something-that-needs-foo'
#打包時避免直接 eval
儘管表達式 eval(x)
看起來像一般的函式呼叫,但它實際上在 JavaScript 中具有特殊行為。以這種方式使用 eval
表示儲存在 x
中的評估程式碼可以按名稱參照任何包含範圍中的任何變數。例如,程式碼 let y =
會傳回 123
。
這稱為「直接 eval」,在打包程式碼時會造成許多問題
現代打包器包含稱為「範圍提升」的最佳化,它會將所有打包檔案合併成單一檔案,並重新命名變數以避免名稱衝突。但是,這表示由直接
eval
評估的程式碼可以讀取和寫入打包中任何檔案中的變數!這是一個正確性問題,因為評估的程式碼可能會嘗試存取全域變數,但可能會意外存取來自其他檔案的同名私人變數。如果其他檔案中的私人變數含有敏感資料,甚至可能會造成安全性問題。當評估的程式碼參照使用
import
陳述式匯入的變數時,可能無法正常運作。匯入的變數是對其他檔案中變數的動態繫結。它們並非這些變數的副本。因此,當 esbuild 打包程式碼時,匯入會替換為對匯入檔案中變數的直接參照。但該變數可能具有不同的名稱,在這種情況下,由直接eval
評估的程式碼將無法按預期的名稱參照它。使用直接
eval
會強制 esbuild 對所有包含對直接eval
的呼叫的所有範圍中的所有程式碼進行反最佳化。為了正確性,它必須假設評估的程式碼可能需要存取從該eval
呼叫可達到的檔案中的任何其他程式碼。這表示其中任何程式碼都不會被消除為無用程式碼,也不會被壓縮。由於由直接
eval
評估的程式碼可能需要按名稱參照任何可達變數,因此 esbuild 無法重新命名由評估的程式碼可達到的所有變數。這表示它無法重新命名變數以避免與打包中其他變數的名稱衝突。因此,直接eval
會導致 esbuild 將檔案包裝在 CommonJS 閉包中,它會透過引入新的範圍來避免名稱衝突。但是,這會使產生的程式碼更大且更慢,因為匯出的變數使用執行時期動態繫結,而不是編譯時期靜態繫結。
幸運的是,通常很容易避免使用直接的 eval
。有兩個常用的替代方案可以避免上述所有缺點
(0, eval)('x')
這稱為「間接 eval」,因為
eval
沒有被直接呼叫,因此不會觸發 JavaScript VM 中直接 eval 的語法特殊情況。你可以使用任何語法呼叫間接 eval,但不能使用eval('x')
這種精確形式的表達式。例如,var eval2 =
和eval; eval2('x') [eval][0]('x')
和window.
都是間接 eval 呼叫。當你使用間接 eval 時,程式碼會在全域範圍內評估,而不是在呼叫者的內聯範圍內評估。eval('x') new Function('x')
這會在執行階段建構一個新的函式物件。這就像你在全域範圍內寫入
function()
,但{ x } x
可以是任意字串的程式碼。這種形式有時很方便,因為你可以將參數新增到函式中,並使用這些參數將變數公開給評估的程式碼。例如,(new Function('env',
就像你寫入'x'))( someEnv) (function(env)
。當評估的程式碼需要存取區域變數時,這通常是直接{ x })( someEnv) eval
的替代方案,因為你可以將區域變數作為參數傳遞。
#toString()
的值不會保留在函式(和類別)上
在 JavaScript 函式物件上呼叫 toString()
,然後將該字串傳遞給某種形式的 eval
以取得新的函式物件,這有點常見。這會有效地將函式從包含的檔案中「移除」,並中斷該檔案中所有變數的連結。使用 esbuild 執行此操作不受支援,而且可能無法正常運作。特別是,esbuild 通常使用輔助方法來實作某些功能,並且假設 JavaScript 範圍規則沒有被竄改。例如
let pow = (a, b) => a ** b;
let pow2 = (0, eval)(pow.toString());
console.log(pow2(2, 3));
當此程式碼編譯為 ES6 時,其中沒有 **
算子,**
算子會被替換為呼叫 __pow
輔助函式
let __pow = Math.pow;
let pow = (a, b) => __pow(a, b);
let pow2 = (0, eval)(pow.toString());
console.log(pow2(2, 3));
如果您嘗試執行此程式碼,您將會收到一個錯誤,例如 ReferenceError:
,因為函式 (a, b)
取決於區域作用域符號 __pow
,而它在全域作用域中不可用。這是許多 JavaScript 語言功能的情況,包括 async
函式,以及一些 esbuild 特定的功能,例如 保留名稱 設定。
這個問題最常出現在人們使用 .toString()
取得函式的原始碼,然後嘗試將它用作 網頁工作執行緒 的主體時。如果您正在執行此操作,並且您想使用 esbuild,您應該在一個獨立的建置步驟中建置網頁工作執行緒的原始碼,然後將網頁工作執行緒原始碼作為字串插入到建立網頁工作執行緒的程式碼中。 define 功能是建置時插入字串的一種方式。
#從模組命名空間物件呼叫的函式不會保留 this
的值
在 JavaScript 中,函式中的 this
的值會根據函式的呼叫方式自動填入。例如,如果使用 obj.fn()
呼叫函式,函式呼叫期間 this
的值會是 obj
。esbuild 會尊重此行為,但有一個例外:如果您從模組命名空間物件呼叫函式,this
的值可能不正確。例如,考慮這段從模組命名空間物件 ns
呼叫 foo
的程式碼
import * as ns from './foo.js'
ns.foo()
如果 foo.js
嘗試使用 this
參照模組命名空間物件,那麼在使用 esbuild 將程式碼綑綁後,它不一定會運作
// foo.js
export function foo() {
this.bar()
}
export function bar() {
console.log('bar')
}
原因是 esbuild 會自動將使用模組命名空間物件的大部分程式碼改寫為直接匯入事物的程式碼。這表示上面的範例程式碼會被轉換成這樣,這會移除函式呼叫的 this
內容
import { foo } from './foo.js'
foo()
此轉換大幅改善了 樹狀搖晃(又稱移除無用程式碼),因為它讓 esbuild 能夠了解哪些已匯出的符號未被使用。它的缺點是這會改變使用 this
存取模組匯出的程式碼的行為,但這不是問題,因為一開始就不應該有人撰寫這種奇怪的程式碼。如果您需要從同一個檔案存取已匯出的函式,請直接呼叫它(例如,在上面的範例中呼叫 bar()
,而不是 this.bar()
)。
#default
匯出可能會導致錯誤
ES 模組格式(即 ESM)有一個稱為 default
的特殊匯出,它的行為有時與所有其他匯出名稱不同。當具有 default
匯出的 ESM 格式程式碼轉換成 CommonJS 格式,然後將該 CommonJS 程式碼匯入到 ESM 格式的另一個模組中時,對於應該發生什麼事有兩種不同的解釋,而且這兩種解釋都被廣泛使用(Babel 方式和 Node 方式)。這非常不幸,因為它會造成無止盡的相容性問題,特別是因為 JavaScript 函式庫通常以 ESM 編寫並以 CommonJS 發布。
當 esbuild 綑綁執行此操作的程式碼時,它必須決定要使用哪種詮釋,而沒有完美的答案。esbuild 使用的啟發法與 Webpack 使用的啟發法相同(詳情請見下文)。由於 Webpack 是使用最廣泛的綑綁器,這表示 esbuild 在這個相容性問題上與現有生態系統相容性最高。因此,好消息是,如果您能讓有此問題的程式碼與 esbuild 一起運作,它也應該可以與 Webpack 一起運作。
以下是一個展示問題的範例
// index.js
import foo from './somelib.js'
console.log(foo)
// somelib.js
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = 'foo';
以下則是兩種廣泛使用的詮釋
Babel 詮釋
如果使用 Babel 詮釋,此程式碼將會列印
foo
。他們的理由是somelib.js
已從 ESM 轉換為 CommonJS(您可以從__esModule
標記看出),而原始程式碼看起來像這樣// somelib.js export default 'foo'
如果
somelib.js
尚未從 ESM 轉換為 CommonJS,則此程式碼將會列印foo
,因此它應該會不論模組格式為何而列印foo
。這是透過偵測 CommonJS 模組是否曾經透過__esModule
標記(所有模組轉換工具都設定,包括 Babel、TypeScript、Webpack 和 esbuild)成為 ES 模組,並在存在__esModule
標記時將預設匯入設定為exports.
來完成的。此行為很重要,因為它必須在 CommonJS 環境中正確執行跨編譯的 ESM,而且在 Node 最終新增原生 ESM 支援之前,這很長一段時間都是執行 ESM 程式碼於 Node 中的唯一方法。default Node 詮釋
如果使用 Node 詮釋,此程式碼將會列印
{ default:
。他們的理由是 CommonJS 程式碼使用動態匯出,而 ESM 程式碼使用靜態匯出,因此將 CommonJS 匯入 ESM 的普遍方法是以某種方式公開 CommonJS'foo' } exports
物件本身。例如,CommonJS 程式碼可以執行exports[
,這在 ESM 語法中沒有等效的語法。Math. random() ] = 'foo' default
匯出用於此目的,因為這實際上是提出 ES 模組規格的人員最初設計它的目的。此詮釋對於一般的 CommonJS 模組來說是完全合理的。它只會對曾經是 ES 模組的 CommonJS 模組(即存在__esModule
時)造成相容性問題,在這種情況下,行為會與 Babel 詮釋不同。
如果您是函式庫作者:在撰寫新程式碼時,您應該強烈考慮完全避免使用 default
匯出。不幸的是,它已被相容性問題所玷污,而使用它可能會在某個時間點對您的使用者造成問題。
如果您是函式庫使用者:預設情況下,esbuild 會使用 Babel 解譯。如果您希望 esbuild 使用 Node 解譯,您需要將您的程式碼放入以 .mts
或 .mjs
結尾的檔案中,或者您需要將 "type":
新增到您的 package.json
檔案中。原因是 Node 的原生 ESM 支援只能在檔案副檔名為 .mjs
或存在 "type":
時執行 ESM 程式碼,因此這樣做是一個良好的訊號,表示程式碼打算在 Node 中執行,因此應使用 default
匯入的 Node 解譯。這是 Webpack 使用的相同啟發法。
#TypeScript
載入器:ts
或 tsx
此載入器預設啟用 .ts
、.tsx
、.mts
和 .cts
檔案,這表示 esbuild 內建支援剖析 TypeScript 語法並捨棄類型註解。然而,esbuild 不會 進行任何類型檢查,因此您仍需要與 esbuild 並行執行 tsc -noEmit
來檢查類型。這不是 esbuild 本身會做的事。
下列這些 TypeScript 類型宣告會被剖析並忽略(非詳盡清單)
語法功能 | 範例 |
---|---|
介面宣告 | interface Foo {} |
類型宣告 | type Foo = number |
函式宣告 | function foo(): void; |
環境宣告 | declare module 'foo' {} |
僅類型匯入 | import type {Type} from 'foo' |
僅類型匯出 | export type {Type} from 'foo' |
僅類型匯入指定子 | import {type Type} from 'foo' |
僅類型匯出指定子 | export {type Type} from 'foo' |
支援僅 TypeScript 語法擴充,並始終轉換為 JavaScript(非詳盡清單)
語法功能 | 範例 | 備註 |
---|---|---|
命名空間 | namespace Foo {} |
|
列舉 | enum Foo { A, B } |
|
常數列舉 | const enum Foo { A, B } |
|
泛型類型參數 | <T>(a: T): T => a |
必須使用 tsx 載入器撰寫 <T,>( ... |
具有類型的 JSX | <Element<T>/> |
|
類型轉換 | a as B 和 <B>a |
|
類型匯入 | import {Type} from 'foo' |
透過移除所有未使用的匯入來處理 |
類型匯出 | export {Type} from 'foo' |
透過忽略 TypeScript 檔案中遺失的匯出處理 |
實驗裝飾器 | @sealed class Foo {} |
需要 experimentalDecorators , 不支援 emitDecoratorMetadata |
實例化表達式 | Array<number> |
TypeScript 4.7+ |
extends 在 infer 上 |
infer A extends B |
TypeScript 4.7+ |
變異註解 | type A<out B> = () => B |
TypeScript 4.7+ |
satisfies 算子 |
a satisfies T |
TypeScript 4.9+ |
const 類型參數 |
class Foo<const T> {} |
TypeScript 5.0+ |
#TypeScript 注意事項
在將 TypeScript 與 esbuild 搭配使用時,您應注意以下事項(除了 JavaScript 注意事項 之外)
#檔案獨立編譯
即使只轉譯單一模組,TypeScript 編譯器實際上仍會剖析匯入的檔案,以便判斷匯入的名稱是類型還是值。然而,esbuild 和 Babel(以及 TypeScript 編譯器的 transpileModule
API)等工具會獨立編譯每個檔案,因此無法判斷匯入的名稱是類型還是值。
因此,如果您將 TypeScript 與 esbuild 搭配使用,應啟用 isolatedModules
TypeScript 設定選項。此選項可避免您使用可能導致在 esbuild 等環境中編譯錯誤的功能,因為這些環境會獨立編譯每個檔案,而不會追蹤跨檔案的類型參照。例如,它會避免您使用 export
從其他模組重新匯出類型(您需要改用 export
)。
#匯入遵循 ECMAScript 模組行為
由於歷史原因,TypeScript 編譯器預設會將 ESM(ECMAScript 模組)語法編譯為 CommonJS 語法。例如,import *
會編譯為 const foo =
。推測這是因為 TypeScript 採用此語法時,ECMAScript 模組仍是提案。然而,這是一種舊有行為,與此語法在 node 等實際平台上的行為不符。例如,require
函式可以傳回任何 JavaScript 值,包括字串,但 import * as
語法總是會傳回物件,且無法是字串。
若要避免因這項舊有功能而產生的問題,請在將 TypeScript 與 esbuild 搭配使用時,啟用 esModuleInterop
TypeScript 設定選項。啟用此選項會停用這項舊有行為,並使 TypeScript 的類型系統與 ESM 相容。此選項預設未啟用,因為這會對現有的 TypeScript 專案造成重大變更,但 Microsoft 強烈建議將其套用至新舊專案(然後更新您的程式碼),以提升與其他生態系統的相容性。
具體來說,這表示從 CommonJS 模組匯入非物件值時,必須使用預設匯入,而非使用 import * as
。因此,如果 CommonJS 模組透過 module.
匯出函式,您需要使用 import
,而非 import *
。
#需要類型系統的功能不受支援
esbuild 會將 TypeScript 類型視為註解並加以忽略,因此 TypeScript 會被視為「類型檢查的 JavaScript」。類型註解的詮釋由 TypeScript 類型檢查器負責,如果您使用 TypeScript,您應該除了 esbuild 之外,也執行類型檢查器。這是 Babel 的 TypeScript 實作所使用的相同編譯策略。不過,這表示某些需要類型詮釋才能運作的 TypeScript 編譯功能無法與 esbuild 搭配使用。
具體來說
TypeScript 設定選項
emitDecoratorMetadata
不受支援。此功能會將對應 TypeScript 類型的 JavaScript 表示傳遞給附加的裝飾器函式。由於 esbuild 沒有複製 TypeScript 的類型系統,因此它沒有足夠的資訊來實作此功能。TypeScript 設定選項
declaration
(即產生.d.ts
檔案)不受支援。如果您正在 TypeScript 中撰寫函式庫,而且您想要將已編譯的 JavaScript 程式碼發布為套件供其他人使用,您可能也想要發布類型宣告。這不是 esbuild 能夠為您執行的動作,因為它不會保留任何類型資訊。您可能需要使用 TypeScript 編譯器來產生類型宣告,或是自行手動撰寫。
#僅尊重特定 tsconfig.json
欄位
在綑綁期間,esbuild 中的路徑解析演算法會考慮包含該檔案的最接近父目錄中的 tsconfig.json
檔案內容,並根據內容調整其行為。您也可以使用 esbuild 的 tsconfig
設定,透過建置 API 明確設定 tsconfig.json
路徑,並使用 esbuild 的 tsconfigRaw
設定,透過轉換 API 明確傳入 tsconfig.json
檔案內容。不過,esbuild 目前僅會檢查 tsconfig.json
檔案中的下列欄位
experimentalDecorators
此選項啟用 TypeScript 檔案中裝飾器語法的轉換。此轉換遵循 TypeScript 本身在啟用
experimentalDecorators
時遵循的過時裝飾器設計。請注意,有一個更新的裝飾器設計已新增到 JavaScript,以及在停用
experimentalDecorators
時新增到 TypeScript。這不是 esbuild 目前實作的內容,因此當experimentalDecorators
停用時,esbuild 目前不會轉換裝飾器。target
useDefineForClassFields
這些選項控制 TypeScript 檔案中的類別欄位是否使用「定義」語義或「指派」語義編譯
定義語義(esbuild 的預設行為):TypeScript 類別欄位會像一般的 JavaScript 類別欄位一樣運作。欄位初始化器不會觸發基底類別上的設定器。您應該以後都使用這種方式撰寫所有新程式碼。
指派語義(您必須明確啟用):esbuild 模擬 TypeScript 的舊版類別欄位行為。欄位初始化器將觸發基底類別設定器。這可能是讓舊版程式碼執行的必要條件。
使用 esbuild 停用定義語義(因此啟用指派語義)的方式與使用 TypeScript 停用的方式相同:在
tsconfig.json
檔案中將useDefineForClassFields
設為false
。為了與 TypeScript 相容,當未指定
useDefineForClassFields
時,esbuild 也會複製 TypeScript 的行為,當tsconfig.json
包含早於ES2022
的target
時,預設為false
。但我建議在需要時明確設定useDefineForClassFields
,而不是依賴來自target
設定值的這個預設值。請注意,tsconfig.json
中的target
設定僅由 esbuild 用於判斷useDefineForClassFields
的預設值。它不會影響 esbuild 本身的target
設定,即使它們有相同的名稱。baseUrl
paths
這些選項會影響 esbuild 將
import
/require
路徑解析為檔案系統上的檔案的方式。您可以使用它來定義套件別名,並以其他方式改寫匯入路徑。請注意,使用 esbuild 進行匯入路徑轉換需要啟用綑綁
,因為 esbuild 的路徑解析僅在綑綁期間發生。另請注意,esbuild 也有原生別名
功能,您可能想改用它。jsx
jsxFactory
jsxFragmentFactory
jsxImportSource
這些選項會影響 esbuild 將 JSX 語法轉換為 JavaScript 的方式。它們等於 esbuild 針對這些設定的原生選項:
jsx
、jsxFactory
、jsxFragment
和jsxImportSource
。alwaysStrict
strict
如果啟用其中任一選項,esbuild 會將所有 TypeScript 檔案中的所有程式碼視為 嚴格模式,並在產生的程式碼前加上
"use strict"
,除非輸出format
設為esm
(因為所有 ESM 檔案都自動處於嚴格模式)。verbatimModuleSyntax
importsNotUsedAsValues
preserveValueImports
預設情況下,TypeScript 編譯器會在將 TypeScript 轉換為 JavaScript 時刪除未使用的匯入。這樣一來,意外變成僅類型匯入的匯入在執行時不會導致錯誤。esbuild 也實作了此行為。
這些選項允許您停用此行為並保留未使用的匯入,這在匯入的檔案具有有用的副作用時很有用。您應該使用
verbatimModuleSyntax
,因為它取代了舊的importsNotUsedAsValues
和preserveValueImports
設定(TypeScript 現已將其棄用)。extends
此選項允許您將
tsconfig.json
檔案分割成多個檔案。此值可以是單一繼承的字串,或多重繼承的陣列(TypeScript 5.0+ 的新功能)。
所有其他 tsconfig.json
欄位(即上述清單中沒有的欄位)都將被忽略。
#您無法對 *.ts
檔案使用 tsx
載入器
tsx
載入器不是 ts
載入器的超集。它們是兩個不同的部分不相容的語法。例如,字元序列 <a>1</a>/g
在 ts
載入器中會解析為 <a>(1 < (/a>/g))
,在 tsx
載入器中會解析為 (<a>1</a>) / g
。
這導致的最常見問題是無法在箭頭函式表達式上使用泛型類型參數,例如 <T>() => {}
和 tsx
載入器。這是故意的,並符合官方 TypeScript 編譯器的行為。tsx
語法中的那個空格是保留給 JSX 元素的。
#JSX
載入器:jsx
或 tsx
JSX 是 JavaScript 的 XML 類似語法擴充,為 React 而建立。它的目的是由您的建置工具轉換為一般 JavaScript。每個 XML 元素都會變成一般的 JavaScript 函式呼叫。例如,下列 JSX 程式碼
import Button from './button'
let button = <Button>Click me</Button>
render(button)
會轉換為下列 JavaScript 程式碼
import Button from "./button";
let button = React.createElement(Button, null, "Click me");
render(button);
此載入器預設會針對 .jsx
和 .tsx
檔案啟用。請注意,預設情況下不會在 .js
檔案中啟用 JSX 語法。如果您想啟用,您需要設定它
esbuild app.js --bundle --loader:.js=jsx
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.js': 'jsx' },
outfile: 'out.js',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".js": api.LoaderJSX,
},
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
#JSX 自動匯入
使用 JSX 語法通常需要手動匯入您正在使用的 JSX 函式庫。例如,如果您使用 React,預設您需要像這樣將 React 匯入每個 JSX 檔案
import * as React from 'react'
render(<div/>)
這是因為 JSX 轉換會將 JSX 語法轉換為對 React.
的呼叫,但它本身並不會匯入任何東西,因此 React
變數不會自動存在。
如果您想避免手動將 JSX 函式庫 import
到每個檔案,您可以透過將 esbuild 的 JSX 轉換設定為 automatic
,它會為您產生匯入陳述式。請記住,這也會完全改變 JSX 轉換的工作方式,因此如果您使用 React 以外的 JSX 函式庫,它可能會損壞您的程式碼。這樣做看起來像這樣
esbuild app.jsx --jsx=automatic
require('esbuild').buildSync({
entryPoints: ['app.jsx'],
jsx: 'automatic',
outfile: 'out.js',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.jsx"},
JSX: api.JSXAutomatic,
Outfile: "out.js",
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
#在沒有 React 的情況下使用 JSX
如果您使用 React 以外的函式庫(例如 Preact)使用 JSX,您可能需要設定 JSX 工廠 和 JSX 片段 設定,因為它們預設為 React
和 React
esbuild app.jsx --jsx-factory=h --jsx-fragment=Fragment
require('esbuild').buildSync({
entryPoints: ['app.jsx'],
jsxFactory: 'h',
jsxFragment: 'Fragment',
outfile: 'out.js',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.jsx"},
JSXFactory: "h",
JSXFragment: "Fragment",
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
或者,如果您使用 TypeScript,您可以透過將此新增到您的 tsconfig.json
檔案來設定 TypeScript 的 JSX,esbuild 應該會自動擷取它而不需要設定
{
"compilerOptions": {
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
}
}
您還必須在包含 JSX 語法的檔案中新增 import
,除非您使用如上所述的自動匯入。
#JSON
json
此載入器預設啟用 .json
檔案。它在建置時將 JSON 檔案解析為 JavaScript 物件,並將物件匯出為預設匯出。使用它看起來像這樣
import object from './example.json'
console.log(object)
除了預設匯出之外,JSON 物件中的每個頂層屬性也有命名匯出。直接匯入命名匯出表示 esbuild 可以自動從套件中移除 JSON 檔案中未使用的部分,只留下您實際使用的命名匯出。例如,此程式碼在套件中時只會包含 version
欄位
import { version } from './package.json'
console.log(version)
#CSS
載入器:css
(對於 CSS 模組 還有 global-css
和 local-css
)
css
載入器預設啟用 .css
檔案,而 local-css
載入器預設啟用 .module.css
檔案。這些載入器將檔案載入為 CSS 語法。CSS 是 esbuild 中的一等內容類型,這表示 esbuild 可以直接 套件 CSS 檔案,而不需要從 JavaScript 程式碼匯入您的 CSS
esbuild --bundle app.css --outfile=out.css
require('esbuild').buildSync({
entryPoints: ['app.css'],
bundle: true,
outfile: 'out.css',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.css"},
Bundle: true,
Outfile: "out.css",
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
您可以使用 url()
@import
其他 CSS 檔案並參考影像和字型檔案,esbuild 會將所有內容套件在一起。請注意,您必須為影像和字型檔案設定載入器,因為 esbuild 沒有任何預先設定的載入器。通常這是 資料 URL 載入器或 外部檔案 載入器。
這些語法功能會根據已設定的語言 目標 有條件地轉換為舊瀏覽器
語法轉換 | 範例 |
---|---|
巢狀宣告 | a { &:hover { color: red } } |
現代 RGB/HSL 語法 | #F008 |
inset 縮寫 |
inset: 0 |
hwb() |
hwb(120 30% 50%) |
lab() 和 lch() |
lab(60 -5 58) |
oklab() 和 oklch() |
oklab(0.5 -0.1 0.1) |
color() |
color(display-p3 1 0 0) |
具有兩個位置的顏色停止 | linear-gradient(red 2% 4%, blue) |
漸層轉換提示 | linear-gradient(red, 20%, blue) 1 |
漸層色彩空間 | linear-gradient(in hsl, red, blue) 1 |
漸層色調模式 | linear-gradient(in hsl longer hue, red, blue) 1 |
請注意,預設情況下,esbuild 的輸出將利用現代 CSS 功能。例如,當啟用縮小功能時,color:
將變成 color:
,這會使用 CSS Color Module Level 4 中的語法。如果不需要這樣,您必須指定 esbuild 的 target 設定,以說明您需要輸出在哪些瀏覽器中正確運作。然後,esbuild 將避免使用對這些瀏覽器來說過於現代的 CSS 功能。
當您使用 target 設定提供瀏覽器版本清單時,esbuild 還會自動插入供應商前綴,以便您的 CSS 能在這些瀏覽器中於這些版本或更新版本中運作。目前,esbuild 會對下列 CSS 屬性執行此操作
appearance
backdrop-filter
background-clip: text
box-decoration-break
clip-path
font-kerning
hyphens
initial-letter
mask-composite
mask-image
mask-origin
mask-position
mask-repeat
mask-size
position: sticky
print-color-adjust
tab-size
text-decoration-color
text-decoration-line
text-decoration-skip
text-emphasis-color
text-emphasis-position
text-emphasis-style
text-orientation
text-size-adjust
user-select
#從 JavaScript 匯入
您也可以從 JavaScript 匯入 CSS。當您這樣做時,esbuild 將收集從給定進入點引用的所有 CSS 檔案,並將其打包到 JavaScript 進入點的 JavaScript 輸出檔案旁的兄弟 CSS 輸出檔案中。因此,如果 esbuild 產生 app.js
,它也會產生 app.css
,其中包含 app.js
引用的所有 CSS 檔案。以下是從 JavaScript 匯入 CSS 檔案的範例
import './button.css'
export let Button = ({ text }) =>
<div className="button">{text}</div>
esbuild 所產生的 JavaScript 捆綁檔不會自動將產生的 CSS 匯入到 HTML 頁面中。相反地,您應該自行將產生的 CSS 匯入到 HTML 頁面中,連同產生的 JavaScript。這表示瀏覽器可以並行下載 CSS 和 JavaScript 檔案,這是最有效率的方式。如下所示
<html>
<head>
<link href="app.css" rel="stylesheet">
<script src="app.js"></script>
</head>
</html>
如果產生的輸出名稱不直觀(例如,如果您已將 [hash]
新增到 輸入名稱 設定,而輸出檔案名稱包含內容雜湊),則您可能需要在 元檔案 中查詢產生的輸出名稱。為此,請先透過尋找具有相符 entryPoint
屬性的輸出,來尋找 JS 檔案。此檔案會放入 <script>
標籤中。然後可以使用 cssBundle
屬性找到關聯的 CSS 檔案。此檔案會放入 <link>
標籤中。
#CSS 模組
CSS 模組 是一種 CSS 預處理器技術,用於避免意外的 CSS 名稱衝突。CSS 類別名稱通常是全域性的,但 CSS 模組提供一種方法,可以讓 CSS 類別名稱僅限於它們出現的檔案中。如果兩個獨立的 CSS 檔案使用相同的本地類別名稱 .button
,esbuild 會自動重新命名其中一個,以避免衝突。這類似於 esbuild 如何自動重新命名不同 JS 模組中具有相同名稱的本地變數,以避免名稱衝突。
esbuild 支援使用 CSS 模組進行捆綁。要使用它,您需要啟用 捆綁,為您的 CSS 檔案使用 local-css
載入器(例如,使用 .module.css
檔案副檔名),然後將您的 CSS 模組程式碼匯入到 JS 檔案中。該檔案中的每個本地 CSS 名稱都可以匯入到 JS 中,以取得 esbuild 將其重新命名的名稱。以下是一個範例
// app.js
import { outerShell } from './app.module.css'
const div = document.createElement('div')
div.className = outerShell
document.body.appendChild(div)
/* app.module.css */
.outerShell {
position: absolute;
inset: 0;
}
當您使用 esbuild app.js
對此進行捆綁時,您會得到以下結果(請注意本地 CSS 名稱 outerShell
已重新命名)
// out/app.js
(() => {
// app.module.css
var outerShell = "app_outerShell";
// app.js
var div = document.createElement("div");
div.className = outerShell;
document.body.appendChild(div);
})();
/* out/app.css */
.app_outerShell {
position: absolute;
inset: 0;
}
此功能只有在啟用捆綁時才有意義,因為您的程式碼需要 import
重新命名的本地名稱才能使用它們,而且因為 esbuild 需要能夠在單一捆綁作業中處理所有包含本地名稱的 CSS 檔案,才能成功將衝突的本地名稱重新命名以避免衝突。
esbuild 為本地 CSS 名稱產生的名稱是實作細節,不應在任何地方硬式編碼。您在 JS 或 HTML 中參照本地 CSS 名稱的唯一方式是使用與 esbuild 捆綁在一起的 JS 中的 import 陳述式,如上所示。例如,當啟用 縮小 時,esbuild 會使用不同的名稱產生演算法,產生盡可能短的名稱(類似於 esbuild 如何縮小 JS 中的本地識別碼)。
#使用全域名稱
local-css
載入器預設會讓檔案中的所有 CSS 名稱都變成區域性的。不過,有時你會想要在同一個檔案中混合區域性和全域性名稱。有幾種方法可以做到這一點
- 你可以用
:global(...)
包住類別名稱,讓它們變成全域性的,用:local(...)
讓它們變成區域性的。 - 你可以使用
:global
讓名稱預設為全域性,使用:local
讓名稱預設為區域性。 - 你可以使用
global-css
載入器,讓區域性 CSS 功能仍然啟用,但讓名稱預設為全域性。
以下是一些範例
/* * This is a local name with the "local-css" loader * and a global name with the "global-css" loader */ .button { } /* This is a local name with both loaders */ :local(.button) { } /* This is a global name with both loaders */ :global(.button) { } /* "foo" is global and "bar" is local */ :global .foo :local .bar { } /* "foo" is global and "bar" is local */ :global { .foo { :local { .bar {} } } }
#composes
指令
CSS 模組規範也說明了 composes
指令。它允許具有區域性名稱的類別選擇器參照其他類別選擇器。這可以用來區分常見的屬性集合,以避免重複。而且,透過 from
關鍵字,它也可以用來參照其他檔案中具有區域性名稱的類別選擇器。以下是一個範例
// app.js
import { submit } from './style.css'
const div = document.createElement('div')
div.className = submit
document.body.appendChild(div)
/* style.css */
.button {
composes: pulse from "anim.css";
display: inline-block;
}
.submit {
composes: button;
font-weight: bold;
}
/* anim.css */
@keyframes pulse {
from, to { opacity: 1 }
50% { opacity: 0.5 }
}
.pulse {
animation: 2s ease-in-out infinite pulse;
}
將此與 esbuild
捆綁在一起,你會得到類似這樣的東西
(() => {
// style.css
var submit = "anim_pulse style_button style_submit";
// app.js
var div = document.createElement("div");
div.className = submit;
document.body.appendChild(div);
})();
/* anim.css */
@keyframes anim_pulse {
from, to {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.anim_pulse {
animation: 2s ease-in-out infinite anim_pulse;
}
/* style.css */
.style_button {
display: inline-block;
}
.style_submit {
font-weight: bold;
}
請注意,使用 composes
會導致匯入 JavaScript 的字串變成一個空白分隔的清單,其中包含所有組合在一起的區域性名稱。這是為了傳遞給 DOM 元素上的 className
屬性。另外,請注意,將 composes
與 from
搭配使用,可以讓你(間接地)參照其他 CSS 檔案中的區域性名稱。
請注意,來自不同檔案的組合 CSS 類別在捆綁的輸出檔案中出現的順序在設計上是故意未定義的(詳細資訊請參閱 規範)。你不應該在兩個不同的類別選擇器中宣告相同的 CSS 屬性,然後再將它們組合在一起。你只能組合宣告非重疊 CSS 屬性的 CSS 類別選擇器。
#CSS 注意事項
使用 esbuild 的 CSS 時,你應該記住以下事項
#受限的 CSS 驗證
CSS 有 一般語法規格,所有 CSS 處理器都會使用,然後還有 許多規格 定義特定 CSS 規則的意義。雖然 esbuild 了解一般的 CSS 語法,並且可以了解一些 CSS 規則(足以將 CSS 檔案打包在一起,並將 CSS 縮小到合理大小),但 esbuild 並不包含完整的 CSS 知識。這表示 esbuild 對 CSS 採取「垃圾進,垃圾出」的哲學。如果你想要驗證已編譯的 CSS 沒有錯字,你應該使用 CSS linter,以及 esbuild。
#@import
順序與瀏覽器相符
CSS 中的 @import
規則與 JavaScript 中的 import
關鍵字行為不同。在 JavaScript 中,import
大致上表示「確保在評估此檔案之前,已評估匯入的檔案」,但在 CSS 中,@import
大致上表示「在此重新評估匯入的檔案」。例如,考慮下列檔案
entry.css
@import "foreground.css";
@import "background.css";foreground.css
@import "reset.css";
body {
color: white;
}background.css
@import "reset.css";
body {
background: black;
}reset.css
body {
color: black;
background: white;
}
根據你對 JavaScript 的直覺,你可能會認為這段程式碼會先將主體重設為白色背景上的黑色文字,然後再覆寫為黑色背景上的白色文字。這不是會發生的事。 相反地,主體會完全變為黑色(前景和背景都是)。這是因為 @import
應該表現得好像匯入規則已由匯入的檔案取代(有點像 C/C++ 中的 #include
),這會導致瀏覽器看到下列程式碼
/* reset.css */
body {
color: black;
background: white;
}
/* foreground.css */
body {
color: white;
}
/* reset.css */
body {
color: black;
background: white;
}
/* background.css */
body {
background: black;
}
最終會簡化成這樣
body { color: black; background: black; }
這種行為很不幸,但 esbuild 會這樣做,因為這是 CSS 的指定方式,而且這是 CSS 在瀏覽器中的運作方式。這很重要,因為一些其他常用的 CSS 處理工具,例如 postcss-import
,會錯誤地以 JavaScript 順序而不是 CSS 順序來解析 CSS 匯入。如果你要將為這些工具編寫的 CSS 程式碼移植到 esbuild(或甚至只是切換為在瀏覽器中原生執行 CSS 程式碼),如果你的程式碼依賴於錯誤的匯入順序,你的程式碼可能會出現外觀變更。
#文字
載入器:text
此載入器在預設情況下會針對 .txt
檔案啟用。它會在建置時將檔案載入為字串,並將字串匯出為預設匯出。使用它的方式如下所示
import string from './example.txt'
console.log(string)
#二進制
載入器:binary
此載入器會在建置時將檔案載入為二進制緩衝區,並使用 Base64 編碼將其內嵌到套件中。檔案的原始位元組會在執行時從 Base64 解碼,並使用預設匯出作為 Uint8Array
匯出。使用方式如下
import uint8array from './example.data'
console.log(uint8array)
如果您需要 ArrayBuffer
,您只要存取 uint8array
即可。請注意,此載入器並未預設啟用。您需要為適當的檔案副檔名進行設定,如下所示
esbuild app.js --bundle --loader:.data=binary
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.data': 'binary' },
outfile: 'out.js',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".data": api.LoaderBinary,
},
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
#Base64
載入器:base64
此載入器會在建置時將檔案載入為二進制緩衝區,並使用 Base64 編碼將其內嵌到套件中作為字串。此字串使用預設匯出進行匯出。使用方式如下
import base64string from './example.data'
console.log(base64string)
請注意,此載入器並未預設啟用。您需要為適當的檔案副檔名進行設定,如下所示
esbuild app.js --bundle --loader:.data=base64
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.data': 'base64' },
outfile: 'out.js',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".data": api.LoaderBase64,
},
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
如果您打算將此轉換為 Uint8Array
或 ArrayBuffer
,您應該改用 binary
載入器。它使用經過最佳化的 Base64 轉二進制轉換器,比一般的 atob
轉換程序更快。
#資料 URL
載入器:dataurl
此載入器會在建置時將檔案載入為二進制緩衝區,並將其內嵌到套件中作為 Base64 編碼的資料 URL。此字串使用預設匯出進行匯出。使用方式如下
import url from './example.png'
let image = new Image
image.src = url
document.body.appendChild(image)
資料 URL 會根據檔案副檔名和/或檔案內容,盡可能猜測 MIME 類型,對於二進制資料,會看起來像這樣
data:image/png;base64,iVBORw0KGgo=
...或對於文字資料,會看起來像這樣
data:image/svg+xml,<svg></svg>%0A
請注意,此載入器並未預設啟用。您需要為適當的檔案副檔名進行設定,如下所示
esbuild app.js --bundle --loader:.png=dataurl
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.png': 'dataurl' },
outfile: 'out.js',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".png": api.LoaderDataURL,
},
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
#外部檔案
有兩種不同的載入器可用於外部檔案,具體取決於您要尋找的行為。兩種載入器如下所述
#file
載入器
載入器:file
此載入器會將檔案複製到輸出目錄,並將檔案名稱作為字串內嵌到套件中。此字串使用預設匯出進行匯出。使用方式如下
import url from './example.png'
let image = new Image
image.src = url
document.body.appendChild(image)
此行為故意與 Webpack 的 file-loader
套件類似。請注意,此載入器並未預設啟用。您需要為適當的檔案副檔名進行設定,如下所示
esbuild app.js --bundle --loader:.png=file --outdir=out
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.png': 'file' },
outdir: 'out',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".png": api.LoaderFile,
},
Outdir: "out",
Write: true,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
預設情況下,匯出的字串僅為檔案名稱。如果您想在匯出的字串前面加上基本路徑,可以使用 公開路徑 API 選項來執行此操作。
#copy
載入器
載入器:copy
此載入器會將檔案複製到輸出目錄,並改寫匯入路徑以指向已複製的檔案。這表示匯入仍會存在於最終的套件中,而最終的套件仍會參照檔案,而不是將檔案包含在套件內。如果你在 esbuild 的輸出上執行其他套件工具,或者想要從套件中省略一個鮮少使用的資料檔案以加快啟動效能,或者想要依賴由匯入觸發的執行時期的特定行為,這可能會很有用。例如
import json from './example.json' assert { type: 'json' }
console.log(json)
如果你使用以下指令套件上述程式碼
esbuild app.js --bundle --loader:.json=copy --outdir=out --format=esm
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.json': 'copy' },
outdir: 'out',
format: 'esm',
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".json": api.LoaderCopy,
},
Outdir: "out",
Write: true,
Format: api.FormatESModule,
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
產生的 out/app.js
檔案可能看起來像這樣
// app.js
import json from "./example-PVCBWCM4.json" assert { type: "json" };
console.log(json);
請注意匯入路徑已改寫為指向已複製的檔案 out/example-PVCBWCM4.json
(由於 資產名稱 設定的預設值,已新增內容雜湊),以及 JSON 的 匯入斷言 已保留,因此執行時期將能夠載入 JSON 檔案。
#空檔案
載入器:empty
此載入器會指示 esbuild 將檔案視為空值。在某些情況下,這可能是從套件中移除內容的有用方法。例如,你可以設定 .css
檔案使用 empty
載入,以防止 esbuild 套件匯入 JavaScript 檔案中的 CSS 檔案
esbuild app.js --bundle --loader:.css=empty
require('esbuild').buildSync({
entryPoints: ['app.js'],
bundle: true,
loader: { '.css': 'empty' },
})
package main
import "github.com/evanw/esbuild/pkg/api"
import "os"
func main() {
result := api.Build(api.BuildOptions{
EntryPoints: []string{"app.js"},
Bundle: true,
Loader: map[string]api.Loader{
".css": api.LoaderEmpty,
},
})
if len(result.Errors) > 0 {
os.Exit(1)
}
}
此載入器也允許你從 CSS 檔案中移除匯入的資產。例如,你可以設定 .png
檔案使用 empty
載入,以便 CSS 程式碼中對 .png
檔案的參照(如 url(image.png)
)會被替換為 url()
。