Skip to content

حزمة Bun تنفذ العلم --compile لإنشاء ملف ثنائي مستقل من ملف TypeScript أو JavaScript.

bash
bun build ./cli.ts --compile --outfile mycli
ts
console.log("Hello world!");

هذا يحزم cli.ts إلى ملف تنفيذي يمكن تنفيذه مباشرة:

bash
./mycli
txt
Hello world!

جميع الملفات والحزم المستوردة يتم حزمها في الملف التنفيذي، جنبًا إلى جنب مع نسخة من وقت تشغيل Bun. جميع واجهات برمجة التطبيقات المدمجة في Bun و Node.js مدعومة.


الترجمة المتقاطعة لمنصات أخرى

العلم --target يسمح لك بترجمة ملفك التنفيذي المستقل لنظام تشغيل أو بنية أو إصدار مختلف من Bun عن الجهاز الذي تشغل عليه bun build.

للبناء لـ Linux x64 (معظم الخوادم):

bash
bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp

# لدعم وحدات المعالجة المركزية من قبل 2013، استخدم إصدار baseline (nehalem)
bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp

# لدعم فقط وحدات المعالجة المركزية من 2013 وما بعد، استخدم إصدار modern (haswell)
# modern أسرع، لكن baseline أكثر توافقًا.
bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myapp

للبناء لـ Linux ARM64 (مثل Graviton أو Raspberry Pi):

bash
# ملاحظة: البنية الافتراضية هي x64 إذا لم يتم تحديد بنية.
bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myapp

للبناء لـ Windows x64:

bash
bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp

# لدعم وحدات المعالجة المركزية من قبل 2013، استخدم إصدار baseline (nehalem)
bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp

# لدعم فقط وحدات المعالجة المركزية من 2013 وما بعد، استخدم إصدار modern (haswell)
bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp

# ملاحظة: إذا لم يتم توفير امتداد .exe، سيضيفه Bun تلقائيًا لملفات Windows التنفيذية

للبناء لـ macOS arm64:

bash
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp

للبناء لـ macOS x64:

bash
bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp

الأهداف المدعومة

ترتيب العلم --target لا يهم، طالما أنها محددة بـ -.

--targetنظام التشغيلالبنيةModernBaselineLibc
bun-linux-x64Linuxx64glibc
bun-linux-arm64Linuxarm64N/Aglibc
bun-windows-x64Windowsx64-
bun-windows-arm64Windowsarm64-
bun-darwin-x64macOSx64-
bun-darwin-arm64macOSarm64N/A-
bun-linux-x64-muslLinuxx64musl
bun-linux-arm64-muslLinuxarm64N/Amusl

ثوابت وقت البناء

استخدم العلم --define لحقن ثوابت وقت البناء في ملفك التنفيذي، مثل أرقام الإصدار أو طوابع البناء أو قيم التكوين:

bash
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 يقرأ ويترجم ملفات JavaScript و TypeScript عند import و require. هذا جزء مما يجعل الكثير من Bun "يعمل فقط"، لكنه ليس مجانيًا. يكلف وقتًا وذاكرة لقراءة الملفات من القرص، وحل مسارات الملفات، والتحليل، والترجمة، وطباعة كود المصدر.

مع الملفات التنفيذية المترجمة، يمكنك نقل هذه التكلفة من وقت التشغيل إلى وقت البناء.

عند النشر للإنتاج، نوصي بالتالي:

bash
bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp

ترجمة البايت كود

لتحسين وقت البدء، فعّل ترجمة البايت كود:

bash
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp

باستخدام ترجمة البايت كود، tsc يبدأ أسرع بمقدار 2x:

ترجمة البايت كود تنقل نفقات التحليل لملفات الإدخال الكبيرة من وقت التشغيل إلى وقت الحزمة. تطبيقك يبدأ بشكل أسرع، مقابل جعل أمر bun build أبطأ قليلاً. لا يحجب كود المصدر.

ماذا تفعل هذه الأعلام؟

الوسيطة --minify تحسن حجم كود المخرجات المترجم. إذا كان لديك تطبيق كبير، هذا يمكن أن يوفر ميغابايت من المساحة. للتطبيقات الأصغر، قد لا تزال تحسن وقت البدء قليلاً.

الوسيطة --sourcemap تدمج خريطة مصدر مضغوطة بـ zstd، بحيث تشير الأخطاء وتتبعات المكدس إلى مواقعها الأصلية بدلاً من الموقع المترجم. Bun سيقوم تلقائيًا بفك الضغط وحل خريطة المصدر عند حدوث خطأ.

الوسيطة --bytecode تفعل ترجمة البايت كود. في كل مرة تشغل كود JavaScript في Bun، JavaScriptCore (المحرك) سيترجم كود المصدر إلى بايت كود. يمكننا نقل عمل التحليل هذا من وقت التشغيل إلى وقت الحزمة، مما يوفر لك وقت البدء.


تضمين وسائط وقت التشغيل

--compile-exec-argv="args" - تضمين وسائط وقت التشغيل المتاحة عبر process.execArgv:

bash
bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp
ts
// في التطبيق المترجم
console.log(process.execArgv); // ["--smol", "--user-agent=MyBot"]

تعطيل تحميل التكوين التلقائي

افتراضيًا، الملفات التنفيذية المستقلة تبحث عن ملفات .env و bunfig.toml في الدليل حيث يتم تشغيل الملف التنفيذي. يمكنك تعطيل هذا السلوك في وقت البناء لتنفيذ حتمي بغض النظر عن دليل عمل المستخدم.

bash
# تعطيل تحميل .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 myapp

يمكنك أيضًا تكوين هذا عبر واجهة برمجة تطبيقات JavaScript:

ts
await Bun.build({
  entrypoints: ["./app.ts"],
  compile: {
    autoloadDotenv: false, // تعطيل تحميل .env
    autoloadBunfig: false, // تعطيل تحميل bunfig.toml
  },
});

التصرف كـ Bun CLI

NOTE

جديد في Bun v1.2.16

يمكنك تشغيل ملف تنفيذي مستقل كما لو كان bun CLI نفسه عن طريق تعيين متغير البيئة BUN_BE_BUN=1. عند تعيين هذا المتغير، سيتجاهل الملف التنفيذي نقطة الدخول المحزمة ويعرض بدلاً من ذلك جميع ميزات Bun CLI.

على سبيل المثال، ضع في اعتبارك ملفًا تنفيذيًا مترجمًا من نص بسيط:

bash
echo "console.log(\"you shouldn't see this\");" > such-bun.js
bun build --compile ./such-bun.js
txt
[3ms] bundle 1 modules
[89ms] compile such-bun

عادةً، تشغيل ./such-bun مع وسائط سينفذ النص.

bash
# الملف التنفيذي يشغل نقطة الدخول الخاصة به افتراضيًا
./such-bun install
txt
you shouldn't see this

لكن، مع متغير البيئة BUN_BE_BUN=1، يتصرف تمامًا مثل ملف bun الثنائي:

bash
# مع متغير البيئة، الملف التنفيذي يتصرف مثل `bun` CLI
BUN_BE_BUN=1 ./such-bun install
txt
bun install v1.2.16-canary.1 (1d1db811)
Checked 63 installs across 64 packages (no changes) [5.00ms]

هذا مفيد لبناء أدوات CLI على قمة Bun التي قد تحتاج لتثبيت الحزم، وحزم التبعيات، وتشغيل ملفات مختلفة أو محلية وأكثر دون الحاجة لتنزيل ملف ثنائي منفصل أو تثبيت bun.


ملفات تنفيذية كاملة المكدس

NOTE

جديد في Bun v1.2.17

العلم --compile الخاص Bun يمكنه إنشاء ملفات تنفيذية مستقلة تحتوي على كود الخادم والعميل معًا، مما يجعلها مثالية للتطبيقات كاملة المكدس. عند استيراد ملف HTML في كود الخادم الخاص بك، Bun يحزم تلقائيًا جميع أصول الواجهة الأمامية (JavaScript، CSS، إلخ) ويضمنها في الملف التنفيذي. عندما يرى Bun استيراد HTML على الخادم، يبدأ عملية بناء الواجهة الأمامية لحزم JavaScript و CSS والأصول الأخرى.

ts
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}`);
html
<!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>
ts
console.log("Hello from the client!");
css
body {
  background-color: #f0f0f0;
}

لبناء هذا في ملف تنفيذي واحد:

bash
bun build --compile ./server.ts --outfile myapp

هذا ينشئ ملفًا ثنائيًا ذاتيًا يحتوي على:

  • كود الخادم الخاص بك
  • وقت تشغيل Bun
  • جميع أصول الواجهة الأمامية (HTML، CSS، JavaScript)
  • أي حزم npm يستخدمها خادمك

النتيجة هي ملف واحد يمكن نشره في أي مكان دون الحاجة لـ Node.js أو Bun أو أي تبعيات مثبتة. فقط شغّل:

bash
./myapp

Bun يتعامل تلقائيًا مع تقديم أصول الواجهة الأمامية مع أنواع MIME ورؤوس ذاكرة التخزين المؤقت المناسبة. يتم استبدال استيراد HTML بكائن بيان يستخدمه Bun.serve لتقديم الأصول المحزمة مسبقًا بكفاءة.

لمزيد من التفاصيل حول بناء تطبيقات كاملة المكدس مع Bun، راجع دليل المكدس الكامل.


Worker

لاستخدام workers في ملف تنفيذي مستقل، أضف نقطة دخول worker إلى وسائط سطر الأوامر:

bash
bun build --compile ./index.ts ./my-worker.ts --outfile myapp

ثم، ارجع إلى worker في كودك:

ts
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) ثم نحزمها في الملف التنفيذي، لكن حتى الآن، ستحتاج لإضافتها يدويًا لأمر shell مثل المثال أعلاه.

إذا استخدمت مسارًا نسبيًا لملف غير مدرج في الملف التنفيذي المستقل، سيحاول تحميل ذلك المسار من القرص نسبيًا لدليل العمل الحالي للعملية (ثم خطأ إذا لم يكن موجودًا).


SQLite

يمكنك استخدام واردات bun:sqlite مع bun build --compile.

افتراضيًا، قاعدة البيانات يتم حلها نسبيًا لدليل العمل الحالي للعملية.

ts
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.

bash
cd /home/me/Desktop
./hello

تضمين الأصول والملفات

الملفات التنفيذية المستقلة تدعم تضمين الملفات.

لتضمين ملفات في ملف تنفيذي مع bun build --compile، استورد الملف في كودك.

ts
// هذا يصبح مسار ملف داخلي
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";

export default {
  fetch(req) {
    // الملفات المضمنة يمكن بثها من كائنات Response
    return new Response(file(icon));
  },
};

الملفات المضمنة يمكن قراءتها باستخدام وظائف Bun.file أو وظيفة fs.readFile في Node.js (في "node:fs").

على سبيل المثال، لقراءة محتويات الملف المضمن:

ts
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".

ts
import myEmbeddedDb from "./my.db" with { type: "sqlite", embed: "true" };

console.log(myEmbeddedDb.query("select * from users LIMIT 1").get());

قاعدة البيانات هذه قابلة للقراءة والكتابة، لكن جميع التغييرات تضيع عند خروج الملف التنفيذي (لأنها مخزنة في الذاكرة).

تضمين إضافات N-API

يمكنك تضمين ملفات .node في الملفات التنفيذية.

ts
const addon = require("./addon.node");

console.log(addon.hello());

لسوء الحظ، إذا كنت تستخدم @mapbox/node-pre-gyp أو أدوات مماثلة أخرى، ستحتاج للتأكد من أن ملف .node مطلوب مباشرة أو لن يحزم بشكل صحيح.

تضمين الأدلة

لتضمين دليل مع bun build --compile، استخدم shell glob في أمر bun build:

bash
bun build --compile ./index.ts ./public/**/*.png

ثم، يمكنك الرجوع إلى الملفات في كودك:

ts
import icon from "./public/assets/icon.png" with { type: "file" };
import { file } from "bun";

export default {
  fetch(req) {
    // الملفات المضمنة يمكن بثها من كائنات Response
    return new Response(file(icon));
  },
};

هذا بصراحة حل بديل، ونتوقع تحسين هذا في المستقبل بواجهة برمجة تطبيقات أكثر مباشرة.

سرد الملفات المضمنة

للحصول على قائمة بجميع الملفات المضمنة، استخدم Bun.embeddedFiles:

ts
import "./icon.png" with { type: "file" };
import { embeddedFiles } from "bun";

console.log(embeddedFiles[0].name); // `icon-${hash}.png`

Bun.embeddedFiles يعيد مصفوفة من كائنات Blob التي يمكنك استخدامها للحصول على الحجم والمحتويات والخصائص الأخرى للملفات.

ts
embeddedFiles: Blob[]

قائمة الملفات المضمنة تستبعد كود المصدر المحزم مثل ملفات .ts و .js.

تجزئة المحتوى

افتراضيًا، الملفات المضمنة لديها تجزئة محتوى ملحقة باسمها. هذا مفيد للحالات التي تريد فيها تقديم الملف من URL أو CDN ولديك مشاكل إبطال ذاكرة تخزين مؤقت أقل. لكن أحيانًا، هذا غير متوقع وقد تريد الاسم الأصلي بدلاً من ذلك:

لتعطيل تجزئة المحتوى، مرر --asset-naming إلى bun build --compile هكذا:

bash
bun build --compile --asset-naming="[name].[ext]" ./index.ts

التصغير

لتقليل حجم الملف التنفيذي قليلاً، مرر --minify إلى bun build --compile. هذا يستخدم مصغر Bun لتقليل حجم الكود. بشكل عام، ملف Bun الثنائي لا يزال كبيرًا جدًا ونحتاج لجعله أصغر.


أعلام خاصة بـ Windows

عند تجميع ملف تنفيذي مستقل على Windows، هناك خياران خاصان بالمنصة يمكن استخدامهما لتخصيص البيانات الوصفية على ملف .exe المولد:

  • --windows-icon=path/to/icon.ico لتخصيص أيقونة الملف التنفيذي.
  • --windows-hide-console لتعطيل محطة الخلفية، والتي يمكن استخدامها للتطبيقات التي لا تحتاج TTY.

توقيع الكود على macOS

لتوقيع كود ملف تنفيذي مستقل على macOS (مما يصلح تحذيرات Gatekeeper)، استخدم أمر codesign.

bash
codesign --deep --force -vvvv --sign "XXXXXXXXXX" ./myapp

نوصي بتضمين ملف entitlements.plist مع أذونات JIT.

xml
<?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، مرر العلم --entitlements إلى codesign.

bash
codesign --deep --force -vvvv --sign "XXXXXXXXXX" --entitlements entitlements.plist ./myapp

بعد توقيع الكود، تحقق من الملف التنفيذي:

bash
codesign -vvv --verify ./myapp
./myapp: valid on disk
./myapp: satisfies its Designated Requirement

تقسيم الكود

الملفات التنفيذية المستقلة تدعم تقسيم الكود. استخدم --compile مع --splitting لإنشاء ملف تنفيذي يحمل قطع الكود المقسم في وقت التشغيل.

bash
bun build --compile --splitting ./src/entry.ts --outdir ./build
ts
console.log("Entrypoint loaded");
const lazy = await import("./lazy.ts");
lazy.hello();
ts
export function hello() {
  console.log("Lazy module loaded");
}
bash
./build/entry
txt
Entrypoint loaded
Lazy module loaded

وسائط سطر الأوامر غير المدعومة

حاليًا، العلم --compile يمكنه قبول نقطة دخول واحدة فقط في كل مرة ولا يدعم الأعلام التالية:

  • --outdir — استخدم outfile بدلاً من ذلك (إلا عند الاستخدام مع --splitting).
  • --public-path
  • --target=node أو --target=browser
  • --no-bundle - نحن نحزم دائمًا كل شيء في الملف التنفيذي.

Bun بواسطة www.bunjs.com.cn تحرير