Bun 의 번들러는 TypeScript 또는 JavaScript 파일에서 독립적인 바이너리를 생성하기 위한 --compile 플래그를 구현합니다.
bun build ./cli.ts --compile --outfile mycliconsole.log("Hello world!");이것은 cli.ts 를 직접 실행할 수 있는 실행 파일로 번들링합니다:
./mycliHello world!모든 가져온 파일과 패키지는 Bun 런타임의 사본과 함께 실행 파일에 번들링됩니다. 모든 내장 Bun 및 Node.js API 가 지원됩니다.
다른 플랫폼으로 크로스 컴파일
--target 플래그를 사용하면 bun build 를 실행하는 머신과 다른 운영 체제, 아키텍처 또는 Bun 버전을 위해 독립적인 실행 파일을 컴파일할 수 있습니다.
Linux x64 용으로 빌드하려면 (대부분의 서버):
bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp
# 2013 년 이전 CPU 를 지원하려면 baseline 버전 (nehalem) 사용
bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp
# 2013 년 이후 CPU 만 명시적으로 지원하려면 modern 버전 (haswell) 사용
# modern 이 더 빠르지만 baseline 이 더 호환성이 좋습니다.
bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myappLinux ARM64 용으로 빌드하려면 (예: Graviton 또는 Raspberry Pi):
# 참고: 아키텍처를 지정하지 않으면 기본 아키텍처는 x64 입니다.
bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myappWindows x64 용으로 빌드하려면:
bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp
# 2013 년 이전 CPU 를 지원하려면 baseline 버전 (nehalem) 사용
bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp
# 2013 년 이후 CPU 만 명시적으로 지원하려면 modern 버전 (haswell) 사용
bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp
# 참고: .exe 확장자가 제공되지 않으면 Bun 이 Windows 실행 파일에 자동으로 추가합니다macOS arm64 용으로 빌드하려면:
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myappmacOS x64 용으로 빌드하려면:
bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp지원되는 타겟
--target 플래그의 순서는 - 로 구분되는 한 중요하지 않습니다.
| --target | 운영 체제 | 아키텍처 | Modern | Baseline | Libc |
|---|---|---|---|---|---|
| bun-linux-x64 | Linux | x64 | ✅ | ✅ | glibc |
| bun-linux-arm64 | Linux | arm64 | ✅ | N/A | glibc |
| bun-windows-x64 | Windows | x64 | ✅ | ✅ | - |
| ❌ | ❌ | - | |||
| bun-darwin-x64 | macOS | x64 | ✅ | ✅ | - |
| bun-darwin-arm64 | macOS | arm64 | ✅ | N/A | - |
| bun-linux-x64-musl | Linux | x64 | ✅ | ✅ | musl |
| bun-linux-arm64-musl | Linux | arm64 | ✅ | N/A | musl |
빌드 타임 상수
--define 플래그를 사용하여 버전 번호, 빌드 타임스탬프 또는 구성 값과 같은 빌드 타임 상수를 실행 파일에 주입하세요:
bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycli이러한 상수는 빌드 시점에 컴파일된 바이너리에 직접 임베드되어 런타임 오버헤드를 제로로 하고 데드 코드 제거 최적화를 가능하게 합니다.
NOTE
포괄적인 예제 및 고급 패턴은 [빌드 타임 상수 가이드](/guides/runtime/build-time-constants) 를 참조하세요.프로덕션 배포
컴파일된 실행 파일은 메모리 사용을 줄이고 Bun 의 시작 시간을 개선합니다.
일반적으로 Bun 은 import 및 require 시 JavaScript 및 TypeScript 파일을 읽고 트랜스파일합니다. 이는 Bun 의 많은 부분이 "그냥 작동"하는 이유의 일부이지만 공짜는 아닙니다. 디스크에서 파일을 읽고, 파일 경로를 해결하고, 파싱하고, 트랜스파일하고, 소스 코드를 출력하는 데 시간과 메모리가 듭니다.
컴파일된 실행 파일을 사용하면 런타임에서 빌드 타임으로 해당 비용을 이동할 수 있습니다.
프로덕션에 배포할 때 다음을 권장합니다:
bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp바이트코드 컴파일
시작 시간을 개선하려면 바이트코드 컴파일을 활성화하세요:
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp바이트코드 컴파일을 사용하면 tsc 가 2 배 더 빠르게 시작됩니다:
바이트코드 컴파일은 큰 입력 파일에 대한 파싱 오버헤드를 런타임에서 번들 타임으로 이동합니다. 앱이 더 빠르게 시작되는 대신 bun build 명령이 조금 더 느려집니다. 소스 코드를 난독화하지는 않습니다.
이 플래그들은 무엇을 하나요?
--minify 인수는 트랜스파일된 출력 코드의 크기를 최적화합니다. 큰 애플리케이션이 있다면 메가바이트의 공간을 절약할 수 있습니다. 작은 애플리케이션의 경우 시작 시간을 조금 개선할 수도 있습니다.
--sourcemap 인수는 zstd 로 압축된 소스맵을 임베드하여 오류 및 스택 트레이스가 트랜스파일된 위치 대신 원래 위치를 가리키도록 합니다. Bun 은 오류 발생 시 자동으로 소스맵을 분해하고 해결합니다.
--bytecode 인수는 바이트코드 컴파일을 활성화합니다. Bun 에서 JavaScript 코드를 실행할 때마다 JavaScriptCore(엔진) 는 소스 코드를 바이트코드로 컴파일합니다. 이 파싱 작업을 런타임에서 번들 타임으로 이동하여 시작 시간을 절약할 수 있습니다.
런타임 인수 임베드
--compile-exec-argv="args" - process.execArgv 를 통해 사용할 수 있는 런타임 인수를 임베드합니다:
bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp// 컴파일된 앱에서
console.log(process.execArgv); // ["--smol", "--user-agent=MyBot"]자동 구성 로딩 비활성화
기본적으로 독립 실행형 실행 파일은 실행 파일이 실행되는 디렉터리에서 .env 및 bunfig.toml 파일을 찾습니다. 사용자의 작업 디렉터리에 관계없이 결정론적 실행을 위해 빌드 시점에 이 동작을 비활성화할 수 있습니다.
# .env 로딩 비활성화
bun build --compile --no-compile-autoload-dotenv ./app.ts --outfile myapp
# bunfig.toml 로딩 비활성화
bun build --compile --no-compile-autoload-bunfig ./app.ts --outfile myapp
# 둘 다 비활성화
bun build --compile --no-compile-autoload-dotenv --no-compile-autoload-bunfig ./app.ts --outfile myappJavaScript API 를 통해 이를 구성할 수도 있습니다:
await Bun.build({
entrypoints: ["./app.ts"],
compile: {
autoloadDotenv: false, // .env 로딩 비활성화
autoloadBunfig: false, // bunfig.toml 로딩 비활성화
},
});Bun CLI 로 작동
NOTE
Bun v1.2.16 에서 새로 추가됨BUN_BE_BUN=1 환경 변수를 설정하면 독립 실행형 실행 파일을 bun CLI 자체인 것처럼 실행할 수 있습니다. 이 변수가 설정되면 실행 파일은 번들된 진입점을 무시하고 Bun CLI 의 모든 기능을 대신 노출합니다.
예를 들어, 간단한 스크립트에서 컴파일된 실행 파일을 고려해 보세요:
echo "console.log(\"you shouldn't see this\");" > such-bun.js
bun build --compile ./such-bun.js[3ms] bundle 1 modules
[89ms] compile such-bun일반적으로 ./such-bun 을 인수로 실행하면 스크립트가 실행됩니다.
# 기본적으로 실행 파일은 자체 진입점을 실행합니다
./such-bun installyou shouldn't see this하지만 BUN_BE_BUN=1 환경 변수를 사용하면 bun 바이너리처럼 작동합니다:
# 환경 변수를 사용하면 실행 파일이 `bun` CLI 처럼 작동합니다
BUN_BE_BUN=1 ./such-bun installbun install v1.2.16-canary.1 (1d1db811)
Checked 63 installs across 64 packages (no changes) [5.00ms]이는 별도의 바이너리를 다운로드하거나 bun 을 설치하지 않고도 패키지를 설치하거나, 종속성을 번들링하거나, 다른 또는 로컬 파일을 실행하는 등 Bun 을 기반으로 CLI 도구를 빌드하는 데 유용합니다.
풀스택 실행 파일
NOTE
Bun v1.2.17 에서 새로 추가됨Bun 의 --compile 플래그는 서버와 클라이언트 코드를 모두 포함하는 독립 실행형 실행 파일을 생성할 수 있어 풀스택 애플리케이션에 이상적입니다. 서버 코드에서 HTML 파일을 가져오면 Bun 은 모든 프론트엔드 자산 (JavaScript, CSS 등) 을 자동으로 번들링하고 실행 파일에 임베드합니다. Bun 이 서버에서 HTML 가져오기를 감지하면 JavaScript, CSS 및 기타 자산을 번들링하기 위한 프론트엔드 빌드 프로세스가 시작됩니다.
import { serve } from "bun";
import index from "./index.html";
const server = serve({
routes: {
"/": index,
"/api/hello": { GET: () => Response.json({ message: "Hello from API" }) },
},
});
console.log(`Server running at http://localhost:${server.port}`);<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<h1>Hello World</h1>
<script src="./app.ts"></script>
</body>
</html>console.log("Hello from the client!");body {
background-color: #f0f0f0;
}이것을 단일 실행 파일로 빌드하려면:
bun build --compile ./server.ts --outfile myapp이것은 다음을 포함하는 자체 완결 바이너리를 생성합니다:
- 서버 코드
- Bun 런타임
- 모든 프론트엔드 자산 (HTML, CSS, JavaScript)
- 서버에서 사용하는 모든 npm 패키지
결과는 Node.js, Bun 또는 설치된 종속성 없이도 어디에서나 배포할 수 있는 단일 파일입니다. 그냥 실행하면 됩니다:
./myappBun 은 적절한 MIME 타입 및 캐시 헤더와 함께 프론트엔드 자산을 제공하는 것을 자동으로 처리합니다. HTML 가져오기는 Bun.serve 가 사전 번들링된 자산을 효율적으로 제공하는 데 사용하는 매니페스트 객체로 대체됩니다.
Bun 으로 풀스택 애플리케이션 빌드에 대한 자세한 내용은 풀스택 가이드 를 참조하세요.
Worker
독립 실행형 실행 파일에서 worker 를 사용하려면 CLI 인수에 worker 의 진입점을 추가하세요:
bun build --compile ./index.ts ./my-worker.ts --outfile myapp그런 코드에서 worker 를 참조하세요:
console.log("Hello from Bun!");
// 이 중 어느 것이든 작동합니다:
new Worker("./my-worker.ts");
new Worker(new URL("./my-worker.ts", import.meta.url));
new Worker(new URL("./my-worker.ts", import.meta.url).href);독립 실행형 실행 파일에 여러 진입점을 추가하면 실행 파일 내에서 별도로 번들링됩니다.
미래에는 new Worker(path) 에서 정적으로 알려진 경로 사용을 자동으로 감지하고 실행 파일에 번들링할 수 있지만 현재는 위의 예제와 같이 셸 명령에 수동으로 추가해야 합니다.
독립 실행형 실행 파일에 포함되지 않은 파일에 대한 상대 경로를 사용하면 프로세스의 현재 작업 디렉터리를 기준으로 디스크에서 해당 경로를 로드하려고 시도합니다 (그리고 존재하지 않으면 오류가 발생함).
SQLite
bun:sqlite 가져오기를 bun build --compile 과 함께 사용할 수 있습니다.
기본적으로 데이터베이스는 프로세스의 현재 작업 디렉터리를 기준으로 해결됩니다.
import db from "./my.db" with { type: "sqlite" };
console.log(db.query("select * from users LIMIT 1").get());이는 실행 파일이 /usr/bin/hello 에 있고 사용자의 터미널이 /home/me/Desktop 에 있으면 /home/me/Desktop/my.db 를 찾습니다.
cd /home/me/Desktop
./hello자산 및 파일 임베드
독립 실행형 실행 파일은 파일 임베드를 지원합니다.
bun build --compile 로 실행 파일에 파일을 임베드하려면 코드에서 파일을 가져오세요.
// 이것은 내부 파일 경로가 됩니다
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
export default {
fetch(req) {
// 임베드된 파일은 Response 객체에서 스트리밍될 수 있습니다
return new Response(file(icon));
},
};임베드된 파일은 Bun.file 의 함수나 Node.js fs.readFile 함수 ("node:fs" 에서) 를 사용하여 읽을 수 있습니다.
예를 들어, 임베드된 파일의 내용을 읽으려면:
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
const bytes = await file(icon).arrayBuffer();
// await fs.promises.readFile(icon)
// fs.readFileSync(icon)SQLite 데이터베이스 임베드
애플리케이션이 SQLite 데이터베이스를 임베드하려면 가져오기 속성에서 type: "sqlite" 를 설정하고 embed 속성을 "true" 로 설정하세요.
import myEmbeddedDb from "./my.db" with { type: "sqlite", embed: "true" };
console.log(myEmbeddedDb.query("select * from users LIMIT 1").get());이 데이터베이스는 읽기 - 쓰기이지만 실행 파일이 종료되면 모든 변경 사항이 손실됩니다 (메모리에 저장되므로).
N-API 애드온 임베드
.node 파일을 실행 파일에 임베드할 수 있습니다.
const addon = require("./addon.node");
console.log(addon.hello());불행히도 @mapbox/node-pre-gyp 또는 기타 유사한 도구를 사용하는 경우 .node 파일이 직접 require 되지 않으면 올바르게 번들링되지 않습니다.
디렉터리 임베드
bun build --compile 로 디렉터리를 임베드하려면 bun build 명령에서 셸 글롭을 사용하세요:
bun build --compile ./index.ts ./public/**/*.png그런 코드에서 파일을 참조할 수 있습니다:
import icon from "./public/assets/icon.png" with { type: "file" };
import { file } from "bun";
export default {
fetch(req) {
// 임베드된 파일은 Response 객체에서 스트리밍될 수 있습니다
return new Response(file(icon));
},
};이것은 솔직히 우회 방법이며, 미래에는 더 직접적인 API 로 이를 개선할 것으로 예상합니다.
임베드된 파일 나열
임베드된 모든 파일의 목록을 얻으려면 Bun.embeddedFiles 를 사용하세요:
import "./icon.png" with { type: "file" };
import { embeddedFiles } from "bun";
console.log(embeddedFiles[0].name); // `icon-${hash}.png`Bun.embeddedFiles 는 파일의 크기, 내용 및 기타 속성을 얻는 데 사용할 수 있는 Blob 객체의 배열을 반환합니다.
embeddedFiles: Blob[]임베드된 파일 목록에는 .ts 및 .js 파일과 같은 번들된 소스 코드는 제외됩니다.
콘텐츠 해시
기본적으로 임베드된 파일에는 이름에 콘텐츠 해시가 추가됩니다. 이는 URL 또는 CDN 에서 파일을 제공하고 캐시 무효화 문제를 줄이고자 할 때 유용합니다. 하지만 때로는 예상치 못한 경우이며 원래 이름 대신 사용할 수 있습니다:
콘텐츠 해시를 비활성화하려면 --asset-naming 을 bun build --compile 에 다음과 같이 전달하세요:
bun build --compile --asset-naming="[name].[ext]" ./index.ts축소
실행 파일의 크기를 조금 줄이려면 --minify 를 bun build --compile 에 전달하세요. 이는 코드의 크기를 줄이기 위해 Bun 의 축소를 사용합니다. 전반적으로 Bun 의 바이너리는 여전히 너무 크며 더 작게 만들어야 합니다.
Windows 특정 플래그
Windows 에서 독립 실행형 실행 파일을 컴파일할 때 생성된 .exe 파일의 메타데이터를 사용자 지정하는 데 사용할 수 있는 두 가지 플랫폼별 옵션이 있습니다:
- 실행 파일 아이콘을 사용자 지정하려면
--windows-icon=path/to/icon.ico - TTY 가 필요 없는 애플리케이션에 사용할 수 있는 배경 터미널을 비활성화하려면
--windows-hide-console
macOS 에서 코드 서명
macOS 에서 독립 실행형 실행 파일에 코드 서명하려면 (Gatekeeper 경고 수정) codesign 명령을 사용하세요.
codesign --deep --force -vvvv --sign "XXXXXXXXXX" ./myappJIT 권한이 있는 entitlements.plist 파일 포함을 권장합니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>JIT 지원으로 코드 서명하려면 codesign 에 --entitlements 플래그를 전달하세요.
codesign --deep --force -vvvv --sign "XXXXXXXXXX" --entitlements entitlements.plist ./myapp코드 서명 후 실행 파일을 확인하세요:
codesign -vvv --verify ./myapp
./myapp: valid on disk
./myapp: satisfies its Designated Requirement코드 분할
독립 실행형 실행 파일은 코드 분할을 지원합니다. --splitting 과 함께 --compile 을 사용하여 런타임에 코드 분할 청크를 로드하는 실행 파일을 만드세요.
bun build --compile --splitting ./src/entry.ts --outdir ./buildconsole.log("Entrypoint loaded");
const lazy = await import("./lazy.ts");
lazy.hello();export function hello() {
console.log("Lazy module loaded");
}./build/entryEntrypoint loaded
Lazy module loaded지원되지 않는 CLI 인수
현재 --compile 플래그는 한 번에 하나의 진입점만 받을 수 있으며 다음 플래그를 지원하지 않습니다:
--outdir— 대신outfile사용 (--splitting과 함께 사용하는 경우 제외).--public-path--target=node또는--target=browser--no-bundle- 실행 파일에 항상 모든 것을 번들링합니다.