import Build from "/snippets/cli/build.mdx";
يمكن استخدام حزمة Bun السريعة الأصلية عبر أمر CLI bun build أو واجهة برمجة تطبيقات JavaScript Bun.build().
نظرة سريعة
- واجهة برمجة تطبيقات JS:
await Bun.build({ entrypoints, outdir }) - CLI:
bun build <entry> --outdir ./out - المراقبة:
--watchلإعادة البناء التدريجي - الأهداف:
--target browser|bun|node - التنسيقات:
--format esm|cjs|iife(تجريبي لـ cjs/iife)
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './build',
});CLI
bun build ./index.tsx --outdir ./buildإنها سريعة. الأرقام أدناه تمثل الأداء على معيار three.js لـ esbuild.

لماذا الحزمة؟
الحزمة هي قطعة أساسية من البنية التحتية في نظام JavaScript البيئي. كنظرة موجزة على سبب أهمية الحزمة:
- تقليل طلبات HTTP. حزمة واحدة في
node_modulesقد تتكون من مئات الملفات، والتطبيقات الكبيرة قد يكون لديها عشرات من هذه التبعيات. تحميل كل من هذه الملفات بطلب HTTP منفصل يصبح غير عملي بسرعة، لذا تُستخدم الحزم لتحويل كود مصدر تطبيقنا إلى عدد أقل من "الحزم" ذاتية الاحتواء التي يمكن تحميلها بطلب واحد. - تحويلات الكود. التطبيقات الحديثة تُبنى عادةً بلغات أو أدوات مثل TypeScript و JSX ووحدات CSS، وكلها يجب تحويلها إلى JavaScript و CSS عادي قبل أن يمكن استهلاكها من قبل المتصفح. الحزمة هي المكان الطبيعي لتكوين هذه التحويلات.
- ميزات الإطار. تعتمد الأطر على مكونات إضافية للحزمة وتحويلات الكود لتنفيذ أنماط شائعة مثل توجيه نظام الملفات، ومشاركة كود العميل-الخادم (فكر في
getServerSidePropsأو محملات Remix)، ومكونات الخادم. - تطبيقات المكدس الكامل. يمكن لحزمة Bun التعامل مع كود الخادم والعميل في أمر واحد، مما يمكّن من بناء الإنتاج المحسّنة والملفات التنفيذية ذات الملف الواحد. مع واردات HTML في وقت البناء، يمكنك حزمة تطبيقك بالكامل - أصول الواجهة الأمامية وخادم الخلفية - في وحدة نشر واحدة.
لننتقل إلى واجهة برمجة تطبيقات الحزمة.
NOTE
حزمة Bun ليست مخصصة لاستبدال `tsc` للتحقق من النوع أو إنشاء إعلانات النوع.مثال أساسي
لنبنِ حزمتنا الأولى. لديك الملفان التاليان، اللذان ينفذان تطبيق React بسيط يتم عرضه من جانب العميل.
import * as ReactDOM from "react-dom/client";
import { Component } from "./Component";
const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(<Component message="Sup!" />);export function Component(props: { message: string }) {
return <h1>{props.message}</h1>;
}هنا، index.tsx هو "نقطة الدخول" لتطبيقنا. عادةً، سيكون هذا برنامجًا نصيًا يؤدي بعض الآثار الجانبية، مثل بدء خادم أو - في هذه الحالة - تهيئة جذر React. لأننا نستخدم TypeScript و JSX، نحتاج إلى حزمة كودنا قبل أن يمكن إرساله إلى المتصفح.
لإنشاء حزمتنا:
await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
});bun build ./index.tsx --outdir ./outلكل ملف محدد في entrypoints، ستنشئ Bun حزمة جديدة. سيتم كتابة هذه الحزمة على القرص في دليل ./out (كما تم حلها من دليل العمل الحالي). بعد تشغيل البناء، يبدو نظام الملفات هكذا:
.
├── index.tsx
├── Component.tsx
└── out
└── index.jsمحتويات out/index.js ستبدو شيئًا مثل هذا:
// out/index.js
// ...
// ~20k سطر من الكود
// بما في ذلك محتويات `react-dom/client` وجميع تبعياتها
// هنا حيث يتم تعريف دوال $jsxDEV و $createRoot
// Component.tsx
function Component(props) {
return $jsxDEV(
"p",
{
children: props.message,
},
undefined,
false,
undefined,
this,
);
}
// index.tsx
var rootNode = document.getElementById("root");
var root = $createRoot(rootNode);
root.render(
$jsxDEV(
Component,
{
message: "Sup!",
},
undefined,
false,
undefined,
this,
),
);وضع المراقبة
مثل وقت التشغيل ومشغل الاختبار، تدعم الحزمة وضع المراقبة أصلاً.
bun build ./index.tsx --outdir ./out --watchأنواع المحتوى
مثل وقت تشغيل Bun، تدعم الحزمة مجموعة من أنواع الملفات خارج الصندوق. الجدول التالي يقسم مجموعة "المحملات" القياسية للحزمة. راجع الحزمة > أنواع الملفات للوثائق الكاملة.
| الامتدادات | التفاصيل |
|---|---|
.js .jsx .cjs .mjs .mts .cts .ts .tsx | يستخدم مترجم Bun المدمج لتحليل الملف وترجمة صيغة TypeScript/JSX إلى JavaScript عادي. تنفذ الحزمة مجموعة من التحويلات الافتراضية بما في ذلك إزالة الكود الميت وهز الشجرة. في الوقت الحالي لا تحاول Bun تحويل الصيغة لأسفل؛ إذا استخدمت صيغة ECMAScript حديثة، سينعكس ذلك في الكود المحزم. |
.json | يتم تحليل ملفات JSON وتضمينها في الحزمة ككائن JavaScript.js<br/>import pkg from "./package.json";<br/>pkg.name; // => "my-package"<br/> |
.jsonc | JSON مع تعليقات. يتم تحليل الملفات وتضمينها في الحزمة ككائن JavaScript.js<br/>import config from "./config.jsonc";<br/>config.name; // => "my-config"<br/> |
.toml | يتم تحليل ملفات TOML وتضمينها في الحزمة ككائن JavaScript.js<br/>import config from "./bunfig.toml";<br/>config.logLevel; // => "debug"<br/> |
.yaml .yml | يتم تحليل ملفات YAML وتضمينها في الحزمة ككائن JavaScript.js<br/>import config from "./config.yaml";<br/>config.name; // => "my-app"<br/> |
.txt | يتم قراءة محتويات الملف النصي وتضمينها في الحزمة كسلسلة.js<br/>import contents from "./file.txt";<br/>console.log(contents); // => "Hello, world!"<br/> |
.html | تتم معالجة ملفات HTML ويتم حزمة أي أصول مرجعية (برامج نصية، أوراق أنماط، صور). |
.css | يتم حزمة ملفات CSS معًا في ملف .css واحد في دليل الإخراج. |
.node .wasm | هذه الملفات مدعومة من وقت تشغيل Bun، لكن أثناء الحزمة يتم التعامل معها كأصول. |
الأصول
إذا صادفت الحزمة استيراد بامتداد غير معترف به، تتعامل مع الملف المستورد كملف خارجي. يتم نسخ الملف المرجعي كما هو إلى outdir، ويتم حل الاستيراد كمسار إلى الملف.
// نقطة دخول الحزمة
import logo from "./logo.svg";
console.log(logo);// الإخراج المحزم
var logo = "./logo-a7305bdef.svg";
console.log(logo);السلوك الدقيق لمحمل الملفات يتأثر أيضًا بـ naming و publicPath.
المكونات الإضافية
يمكن تجاوز أو تمديد السلوك الموصوف في هذا الجدول باستخدام المكونات الإضافية. راجع صفحة الحزمة > المحملات للوثائق الكاملة.
واجهة برمجة التطبيقات
entrypoints
مصفوفة من المسارات المقابلة لنقاط دخول تطبيقنا. سيتم إنشاء حزمة واحدة لكل نقطة دخول.
JavaScript
const result = await Bun.build({
entrypoints: ["./index.ts"]
});CLI
bun build ./index.tsoutdir
الدليل حيث سيتم كتابة ملفات الإخراج.
JavaScript
const result = await Bun.build({
entrypoints: ['./index.ts'],
outdir: './out'
});
// => { success: boolean, outputs: `BuildArtifact[]`, logs: `BuildMessage[]` }CLI
bun build ./index.ts --outdir ./outإذا لم يتم تمرير outdir إلى واجهة برمجة تطبيقات JavaScript، لن يتم كتابة الكود المحزم على القرص. يتم إرجاع الملفات المحزمة في مصفوفة من كائنات BuildArtifact. هذه الكائنات هي Blobs مع خصائص إضافية؛ راجع المخرجات للوثائق الكاملة.
const result = await Bun.build({
entrypoints: ["./index.ts"],
});
for (const res of result.outputs) {
// يمكن استهلاكها كـ blobs
await res.text();
// Bun ستعين رؤوس Content-Type و Etag
new Response(res);
// يمكن كتابتها يدويًا، لكن يجب استخدام `outdir` في هذه الحالة.
Bun.write(path.join("out", res.path), res);
}عند تعيين outdir، ستكون خاصية path على BuildArtifact هي المسار المطلق إلى حيث تم كتابته.
target
بيئة التنفيذ المقصودة للحزمة.
JavaScript
await Bun.build({
entrypoints: ['./index.ts'],
outdir: './out',
target: 'browser', // افتراضي
})CLI
bun build ./index.ts --outdir ./out --target browserاعتمادًا على الهدف، ستطبق Bun قواعد حل وحدات وتحسينات مختلفة.
افتراضي. لإنشاء حزم مخصصة للتنفيذ بواسطة متصفح. يعطي أولوية لشرط التصدير "browser" عند حل الواردات. استيراد أي وحدات مدمجة، مثل node:events أو node:path سيعمل، لكن استدعاء بعض الدوال، مثل fs.readFile لن يعمل.
لإنشاء حزم مخصصة للتشغيل بواسطة وقت تشغيل Bun. في كثير من الحالات، ليس من الضروري حزمة كود جانب الخادم؛ يمكنك تنفيذ كود المصدر مباشرة بدون تعديل. ومع ذلك، حزمة كود الخادم الخاص بك يمكن أن تقلل أوقات البدء وتحسن أداء التشغيل. هذا هو الهدف لاستخدامه لبناء تطبيقات المكدس الكامل مع واردات HTML في وقت البناء، حيث يتم حزمة كود الخادم والعميل معًا.
جميع الحزم التي تم إنشاؤها باستخدام target: "bun" معلمة بـ // @bun خاص، مما يشير إلى وقت تشغيل Bun أنه لا حاجة لإعادة ترجمة الملف قبل التنفيذ.
إذا كانت أي نقاط الدخول تحتوي على shebang Bun (#!/usr/bin/env bun) فستستخدم الحزمة افتراضيًا target: "bun" بدلاً من "browser".
عند استخدام target: "bun" و format: "cjs" معًا، تتم إضافة // @bun @bun-cjs ودالة غلاف CommonJS غير متوافقة مع Node.js.
لإنشاء حزم مخصصة للتشغيل بواسطة Node.js. يعطي أولوية لشرط التصدير "node" عند حل الواردات، ويخرج .mjs. في المستقبل، سيقوم هذا تلقائيًا بتعبئة Bun العالمي ووحدات bun:* المدمجة الأخرى، رغم أن هذا لم ينفذ بعد.
format
يحدد تنسيق الوحدة المراد استخدامه في الحزم التي تم إنشاؤها.
تستخدم Bun افتراضيًا "esm"، وتوفر دعمًا تجريبيًا لـ "cjs" و "iife".
format: "esm" - وحدة ES
هذا هو التنسيق الافتراضي، الذي يدعم صيغة وحدة ES بما في ذلك انتظار المستوى العلوي و import.meta وأكثر.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
format: "esm",
})CLI
bun build ./index.tsx --outdir ./out --format esmلاستخدام صيغة وحدة ES في المتصفحات، اضبط format على "esm" وتأكد من أن وسم <script type="module"> لديه type="module" مضبوط.
format: "cjs" - CommonJS
لبناء وحدة CommonJS، اضبط format على "cjs". عند اختيار "cjs"، يتغير الهدف الافتراضي من "browser" (esm) إلى "node" (cjs). وحدات CommonJS المترجمة مع format: "cjs" و target: "node" يمكن تنفيذها في كل من Bun و Node.js (بافتراض أن واجهات برمجة التطبيقات المستخدمة مدعومة من كليهما).
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
format: "cjs",
})CLI
bun build ./index.tsx --outdir ./out --format cjsformat: "iife" - IIFE
TODO: توثيق IIFE بمجرد دعم globalNames.
jsx
تكوين سلوك تحويل JSX. يسمح بالتحكم الدقيق في كيفية تجميع JSX.
مثال وقت التشغيل الكلاسيكي (يستخدم factory و fragment):
await Bun.build({
entrypoints: ["./app.tsx"],
outdir: "./out",
jsx: {
factory: "h",
fragment: "Fragment",
runtime: "classic",
},
});# تكوين JSX يتم التعامل معه عبر bunfig.toml أو tsconfig.json
bun build ./app.tsx --outdir ./outمثال وقت التشغيل التلقائي (يستخدم importSource):
await Bun.build({
entrypoints: ["./app.tsx"],
outdir: "./out",
jsx: {
importSource: "preact",
runtime: "automatic",
},
});# تكوين JSX يتم التعامل معه عبر bunfig.toml أو tsconfig.json
bun build ./app.tsx --outdir ./outsplitting
ما إذا كان سيتم تمكين تقسيم الكود.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
splitting: false, // افتراضي
})CLI
bun build ./index.tsx --outdir ./out --splittingعند true، ستمكن الحزمة تقسيم الكود. عندما تستورد نقاط دخول متعددة نفس الملف أو الوحدة أو مجموعة من الملفات/الوحدات، غالبًا ما يكون من المفيد تقسيم الكود المشترك إلى حزمة منفصلة. تُعرف هذه الحزمة المشتركة باسم chunk. ضع في اعتبارك الملفات التالية:
import { shared } from "./shared.ts";import { shared } from "./shared.ts";export const shared = "shared";لحزمة entry-a.ts و entry-b.ts مع تمكين تقسيم الكود:
JavaScript
await Bun.build({
entrypoints: ['./entry-a.ts', './entry-b.ts'],
outdir: './out',
splitting: true,
})CLI
bun build ./entry-a.ts ./entry-b.ts --outdir ./out --splittingتشغيل هذا البناء سينتج الملفات التالية:
.
├── entry-a.tsx
├── entry-b.tsx
├── shared.tsx
└── out
├── entry-a.js
├── entry-b.js
└── chunk-2fce6291bf86559d.jsالملف chunk-2fce6291bf86559d.js الذي تم إنشاؤه يحتوي على الكود المشترك. لتجنب التصادمات، يتضمن اسم الملف تلقائيًا تجزئة محتوى افتراضيًا. يمكن تخصيص هذا باستخدام naming.
plugins
قائمة المكونات الإضافية لاستخدامها أثناء الحزمة.
await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
plugins: [
/* ... */
],
});Bun تنفذ نظام مكونات إضافية عالمي لكل من وقت التشغيل والحزمة في Bun. راجع وثائق المكونات الإضافية للوثائق الكاملة.
env
يتحكم في كيفية التعامل مع متغيرات البيئة أثناء الحزمة. داخليًا، يستخدم هذا define لحقن متغيرات البيئة في الحزمة، لكن يجعل من الأسهل تحديد متغيرات البيئة لحقنها.
env: "inline"
يحقق متغيرات البيئة في الإخراج المحزم عن طريق تحويل مراجع process.env.FOO إلى سلاسل حرفية تحتوي على قيم متغيرات البيئة الفعلية.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
env: "inline",
})CLI
bun build ./index.tsx --outdir ./out --env inlineللمدخلات أدناه:
// input.js
console.log(process.env.FOO);
console.log(process.env.BAZ);الحزمة التي تم إنشاؤها ستحتوي على الكود التالي:
// output.js
console.log("bar");
console.log("123");env: "PUBLIC_*" (بادئة)
يحقق متغيرات البيئة المطابقة للبادئة المعطاة (الجزء قبل حرف *)، ويستبدل process.env.FOO بقيمة متغير البيئة الفعلية. هذا مفيد لتحقق انتقائي لمتغيرات البيئة لأشياء مثل URLs العامة أو رموز جانب العميل، دون القلق بشأن حقن بيانات اعتماد خاصة في حزم الإخراج.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
// تحقق جميع متغيرات البيئة التي تبدأ بـ "ACME_PUBLIC_"
env: "ACME_PUBLIC_*",
})CLI
bun build ./index.tsx --outdir ./out --env ACME_PUBLIC_*على سبيل المثال، مع متغيرات البيئة التالية:
FOO=bar BAZ=123 ACME_PUBLIC_URL=https://acme.comوكود المصدر:
console.log(process.env.FOO);
console.log(process.env.ACME_PUBLIC_URL);
console.log(process.env.BAZ);الحزمة التي تم إنشاؤها ستحتوي على الكود التالي:
console.log(process.env.FOO);
console.log("https://acme.com");
console.log(process.env.BAZ);env: "disable"
تعطيل حقن متغيرات البيئة بالكامل.
sourcemap
يحدد نوع خريطة المصدر المراد إنشاؤها.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
sourcemap: 'linked', // افتراضي 'none'
})CLI
bun build ./index.tsx --outdir ./out --sourcemap linked| القيمة | الوصف |
|---|---|
"none" | افتراضي. لا يتم إنشاء خريطة مصدر. |
"linked" | يتم إنشاء ملف *.js.map منفصل بجانب كل حزمة *.js باستخدام تعليق //# sourceMappingURL لربط الاثنين. يتطلب تعيين --outdir. يمكن تخصيص URL الأساسي هذا باستخدام --public-path.js<br/>// <الكود المحزم هنا><br/><br/>//# sourceMappingURL=bundle.js.map<br/> |
"external" | يتم إنشاء ملف *.js.map منفصل بجانب كل حزمة *.js بدون إدراج تعليق //# sourceMappingURL.الحزم التي تم إنشاؤها تحتوي على معرف تصحيح يمكن استخدامه لربط الحزمة بخريطة المصدر المقابلة الخاصة بها. تتم إضافة debugId هذا كتعليق في أسفل الملف.js<br/>// <كود الحزمة الذي تم إنشاؤه><br/><br/>//# debugId=<DEBUG ID><br/> |
"inline" | يتم إنشاء خريطة مصدر وإلحاقها بنهاية الحزمة التي تم إنشاؤها كحمولة base64.js<br/>// <الكود المحزم هنا><br/><br/>//# sourceMappingURL=data:application/json;base64,<encoded sourcemap here><br/> |
خريطة المصدر *.js.map المرتبطة ستكون ملف JSON يحتوي على خاصية debugId مكافئة.
minify
ما إذا كان سيتم تمكين التصغير. افتراضي false.
NOTE
عند استهداف `bun`، سيتم تصغير المعرفات افتراضيًا.لتمكين جميع خيارات التصغير:
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
minify: true, // افتراضي false
})CLI
bun build ./index.tsx --outdir ./out --minifyلتمكين تصغيرات معينة بشكل دقيق:
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
minify: {
whitespace: true,
identifiers: true,
syntax: true,
},
})CLI
bun build ./index.tsx --outdir ./out --minify-whitespace --minify-identifiers --minify-syntaxexternal
قائمة من مسارات الاستيراد لاعتبارها خارجية. افتراضي [].
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
external: ["lodash", "react"], // افتراضي: []
})CLI
bun build ./index.tsx --outdir ./out --external lodash --external reactالاستيراد الخارجي هو الذي لن يتم تضمينه في الحزمة النهائية. بدلاً من ذلك، سيتم ترك بيان الاستيراد كما هو، ليتم حله في وقت التشغيل.
على سبيل المثال، ضع في اعتبارك ملف نقطة الدخول التالي:
import _ from "lodash";
import { z } from "zod";
const value = z.string().parse("Hello world!");
console.log(_.upperCase(value));عادةً، حزمة index.tsx ستنشئ حزمة تحتوي على كود المصدر الكامل لحزمة "zod". إذا أردنا بدلاً من ذلك ترك بيان الاستيراد كما هو، يمكننا تعليمه كخارجي:
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
external: ['zod'],
})CLI
bun build ./index.tsx --outdir ./out --external zodالحزمة التي تم إنشاؤها ستبدو شيئًا مثل هذا:
import { z } from "zod";
// ...
// محتويات حزمة "lodash"
// بما في ذلك دالة `_.upperCase`
var value = z.string().parse("Hello world!");
console.log(_.upperCase(value));لتعليم جميع الواردات كخارجية، استخدم البدل *:
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
external: ['*'],
})CLI
bun build ./index.tsx --outdir ./out --external '*'packages
التحكم في ما إذا كانت تبعيات الحزمة مُضمنة في الحزمة أم لا. القيم الممكنة: bundle (افتراضي)، external. تعامل Bun مع أي استيراد مساره لا يبدأ بـ . أو .. أو / كحزمة.
JavaScript
await Bun.build({
entrypoints: ['./index.ts'],
packages: 'external',
})CLI
bun build ./index.ts --packages externalnaming
يخصص أسماء الملفات التي تم إنشاؤها. افتراضي ./[dir]/[name].[ext].
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
naming: "[dir]/[name].[ext]", // افتراضي
})CLI
bun build ./index.tsx --outdir ./out --entry-naming "[dir]/[name].[ext]"افتراضيًا، تستند أسماء الحزم التي تم إنشاؤها إلى اسم نقطة الدخول المرتبطة.
.
├── index.tsx
└── out
└── index.jsمع نقاط دخول متعددة، سيعكس تسلسل الملفات الذي تم إنشاؤه هيكل الدليل لنقاط الدخول.
.
├── index.tsx
└── nested
└── index.tsx
└── out
├── index.js
└── nested
└── index.jsيمكن تخصيص أسماء ومواقع الملفات التي تم إنشاؤها باستخدام حقل naming. يقبل هذا الحقل سلسلة قالب تُستخدم لإنشاء أسماء الملفات لجميع الحزم المقابلة لنقاط الدخول. حيث يتم استبدال الرموز التالية بقيمها المقابلة:
[name]- اسم ملف نقطة الدخول، بدون الامتداد.[ext]- امتداد الحزمة التي تم إنشاؤها.[hash]- تجزئة لمحتويات الحزمة.[dir]- المسار النسبي من جذر المشروع إلى الدليل الأصلي للملف المصدر.
على سبيل المثال:
| Token | [name] | [ext] | [hash] | [dir] |
|---|---|---|---|---|
./index.tsx | index | js | a1b2c3d4 | "" (سلسلة فارغة) |
./nested/entry.ts | entry | js | c3d4e5f6 | "nested" |
يمكننا دمج هذه الرموز لإنشاء سلسلة قالب. على سبيل المثال، لتضمين التجزئة في أسماء الحزم التي تم إنشاؤها:
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
naming: 'files/[dir]/[name]-[hash].[ext]',
})CLI
bun build ./index.tsx --outdir ./out --entry-naming 'files/[dir]/[name]-[hash].[ext]'هذا البناء سينتج هيكل الملفات التالي:
.
├── index.tsx
└── out
└── files
└── index-a1b2c3d4.jsعند تقديم سلسلة لحقل naming، تُستخدم فقط للحزم التي تقابل نقاط الدخول. لا تتأثر أسماء chunks والأصول المنسوخة. باستخدام واجهة برمجة تطبيقات JavaScript، يمكن تحديد سلاسل قالب منفصلة لكل نوع من الملفات التي تم إنشاؤها.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
naming: {
// قيم افتراضية
entry: '[dir]/[name].[ext]',
chunk: '[name]-[hash].[ext]',
asset: '[name]-[hash].[ext]',
},
})CLI
bun build ./index.tsx --outdir ./out \
--entry-naming '[dir]/[name].[ext]' \
--chunk-naming '[name]-[hash].[ext]' \
--asset-naming '[name]-[hash].[ext]'root
دليل جذر المشروع.
JavaScript
await Bun.build({
entrypoints: ['./pages/a.tsx', './pages/b.tsx'],
outdir: './out',
root: '.',
})CLI
bun build ./pages/a.tsx ./pages/b.tsx --outdir ./out --root .إذا لم يتم تحديده، يتم حسابه ليكون أول سلف مشترك لجميع ملفات نقطة الدخول. ضع في اعتبارك هيكل الملفات التالي:
.
└── pages
└── index.tsx
└── settings.tsxيمكننا بناء كلتا نقطتي الدخول في دليل pages:
JavaScript
await Bun.build({
entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
outdir: './out',
})CLI
bun build ./pages/index.tsx ./pages/settings.tsx --outdir ./outهذا سينتج هيكل ملفات مثل هذا:
.
└── pages
└── index.tsx
└── settings.tsx
└── out
└── index.js
└── settings.jsبما أن دليل pages هو أول سلف مشترك لملفات نقطة الدخول، يُعتبر جذر المشروع. هذا يعني أن الحزم التي تم إنشاؤها تعيش في المستوى الأعلى من دليل out؛ لا يوجد دليل out/pages.
يمكن تجاوز هذا السلوك عن طريق تحديد خيار root:
JavaScript
await Bun.build({
entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
outdir: './out',
root: '.',
})CLI
bun build ./pages/index.tsx ./pages/settings.tsx --outdir ./out --root .عن طريق تحديد . كـ root، سيبدو هيكل الملفات الذي تم إنشاؤه هكذا:
.
└── pages
└── index.tsx
└── settings.tsx
└── out
└── pages
└── index.js
└── settings.jspublicPath
بادئة تُضاف إلى أي مسارات استيراد في الكود المحزم.
في كثير من الحالات، لن تحتوي الحزم التي تم إنشاؤها على أي بيانات استيراد. بعد كل شيء، هدف الحزمة هو دمج كل الكود في ملف واحد. ومع ذلك هناك عدد من الحالات التي ستحتوي فيها الحزم التي تم إنشاؤها على بيانات استيراد.
- واردات الأصول - عند استيراد نوع ملف غير معترف به مثل
*.svg، تفوض الحزمة إلى محمل الملفات، الذي ينسخ الملف إلىoutdirكما هو. يتم تحويل الاستيراد إلى متغير - الوحدات الخارجية - يمكن تعليم الملفات والوحدات كخارجية، وفي هذه الحالة لن يتم تضمينها في الحزمة. بدلاً من ذلك، سيتم ترك بيان الاستيراد في الحزمة النهائية.
- التقسيم. عند تمكين
splitting، قد تنشئ الحزمة ملفات "chunk" منفصلة تمثل الكود المشترك بين نقاط دخول متعددة.
في أي من هذه الحالات، قد تحتوي الحزم النهائية على مسارات إلى ملفات أخرى. افتراضيًا هذه الواردات نسبية. هنا مثال على استيراد أصل بسيط:
import logo from "./logo.svg";
console.log(logo);var logo = "./logo-a7305bdef.svg";
console.log(logo);تعيين publicPath سيقوم ببادئة جميع مسارات الملفات بالقيمة المحددة.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
publicPath: 'https://cdn.example.com/', // افتراضي غير معرّف
})CLI
bun build ./index.tsx --outdir ./out --public-path 'https://cdn.example.com/'ملف الإخراج سيبدو الآن شيئًا مثل هذا.
var logo = "https://cdn.example.com/logo-a7305bdef.svg";define
خريطة من المعرفات العامة لاستبدالها في وقت البناء. مفاتيح هذا الكائن هي أسماء معرفات، والقيم هي سلاسل JSON سيتم تضمينها.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
define: {
STRING: JSON.stringify("value"),
"nested.boolean": "true",
},
})CLI
bun build ./index.tsx --outdir ./out --define STRING='"value"' --define nested.boolean=trueloader
خريطة من امتدادات الملفات إلى أسماء المحملات المدمجة. يمكن استخدام هذا لتخصيص كيفية تحميل ملفات معينة بسرعة.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
loader: {
".png": "dataurl",
".txt": "file",
},
})CLI
bun build ./index.tsx --outdir ./out --loader .png:dataurl --loader .txt:filebanner
راية تُضاف إلى الحزمة النهائية، يمكن أن تكون توجيهًا مثل use client لـ react أو كتلة تعليق مثل ترخيص للكود.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
banner: 'use client;'
})CLI
bun build ./index.tsx --outdir ./out --banner 'use client";'footer
تذييل يُضاف إلى الحزمة النهائية، يمكن أن يكون شيئًا مثل كتلة تعليق لترخيص أو مجرد بيضة عيد مضحكة.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
footer: '// built with love in SF'
})CLI
bun build ./index.tsx --outdir ./out --footer '// built with love in SF'drop
إزالة استدعاءات الدوال من الحزمة. على سبيل المثال، --drop=console ستزيل جميع استدعاءات console.log. سيتم أيضًا إزالة وسيطات الاستدعاءات، بغض النظر عما إذا كانت تلك الوسائط قد يكون لها آثار جانبية. إسقاط debugger سيزيل جميع بيانات debugger.
JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
drop: ["console", "debugger", "anyIdentifier.or.propertyAccess"],
})CLI
bun build ./index.tsx --outdir ./out --drop console --drop debuggerالمخرجات
دالة Bun.build ترجع Promise<BuildOutput>، معرّف كالتالي:
interface BuildOutput {
outputs: BuildArtifact[];
success: boolean;
logs: Array<object>; // راجع الوثائق للتفاصيل
}
interface BuildArtifact extends Blob {
kind: "entry-point" | "chunk" | "asset" | "sourcemap";
path: string;
loader: Loader;
hash: string | null;
sourcemap: BuildArtifact | null;
}مصفوفة outputs تحتوي على جميع الملفات التي تم إنشاؤها بواسطة البناء. كل أثر ينفذ واجهة Blob.
const build = await Bun.build({
/* */
});
for (const output of build.outputs) {
await output.arrayBuffer(); // => ArrayBuffer
await output.bytes(); // => Uint8Array
await output.text(); // string
}كل أثر يحتوي أيضًا على الخصائص التالية:
| الخاصية | الوصف |
|---|---|
kind | نوع مخرج البناء هذا. البناء ينشئ نقاط دخول محزمة و "chunks" مقسمة للكود وخرائط مصدر وbytecode وأصول منسوخة (مثل الصور). |
path | المسار المطلق إلى الملف على القرص |
loader | المحمل المستخدم لتفسير الملف. راجع الحزمة > المحملات لمعرفة كيف تربط Bun امتدادات الملفات بالمحمل المدمج المناسب. |
hash | تجزئة لمحتويات الملف. معرّف دائمًا للأصول. |
sourcemap | ملف خريطة المصدر المقابل لهذا الملف، إذا تم إنشاؤه. معرّف فقط لنقاط الدخول و chunks. |
مشابه لـ BunFile، يمكن تمرير كائنات BuildArtifact مباشرة إلى new Response().
const build = await Bun.build({
/* */
});
const artifact = build.outputs[0];
// يتم تعيين رأس Content-Type تلقائيًا
return new Response(artifact);وقت تشغيل Bun ينفذ طباعة خاصة جميلة لكائن BuildArtifact لتسهيل التصحيح.
// build.ts
const build = await Bun.build({
/* */
});
const artifact = build.outputs[0];
console.log(artifact);bun run build.ts
BuildArtifact (entry-point) {
path: "./index.js",
loader: "tsx",
kind: "entry-point",
hash: "824a039620219640",
Blob (74756 bytes) {
type: "text/javascript;charset=utf-8"
},
sourcemap: BuildArtifact (sourcemap) {
path: "./index.js.map",
loader: "file",
kind: "sourcemap",
hash: "e7178cda3e72e301",
Blob (24765 bytes) {
type: "application/json;charset=utf-8"
},
sourcemap: null
}
}Bytecode
يمكن استخدام خيار bytecode: boolean لإنشاء bytecode لأي نقاط دخول JavaScript/TypeScript. هذا يمكن أن يحسن بشكل كبير أوقات البدء للتطبيقات الكبيرة. مدعوم فقط لتنسيق "cjs"، يدعم فقط "target": "bun" ويعتمد على إصدار مطابق من Bun. هذا يضيف ملف .jsc مقابل لكل نقطة دخول.
JavaScript
await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
bytecode: true,
})CLI
bun build ./index.tsx --outdir ./out --bytecodeالملفات التنفيذية
Bun تدعم "تجميع" نقطة دخول JavaScript/TypeScript إلى ملف تنفيذي مستقل. هذا الملف التنفيذي يحتوي على نسخة من ثنائي Bun.
bun build ./cli.tsx --outfile mycli --compile
./mycliراجع الحزمة > الملفات التنفيذية للوثائق الكاملة.
السجلات والأخطاء
عند الفشل، ترجع Bun.build promise مرفوض مع AggregateError. يمكن تسجيل هذا إلى console للطباعة الجميلة لقائمة الأخطاء، أو قراءته برمجيًا مع كتلة try/catch.
try {
const result = await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
});
} catch (e) {
// TypeScript لا يسمح بالتعليقات على بند catch
const error = e as AggregateError;
console.error("Build Failed");
// مثال: استخدام التنسيق المدمج
console.error(error);
// مثال: تسلسل الفشل كسلسلة JSON.
console.error(JSON.stringify(error, null, 2));
}في معظم الوقت، لا حاجة لـ try/catch صريح، لأن Bun ستطبع بشكل أنيق الاستثناءات غير الممسوكة. يكفي فقط استخدام انتظار على مستوى العلوي لاستدعاء Bun.build.
كل عنصر في error.errors هو مثيل من BuildMessage أو ResolveMessage (فئات فرعية من Error)، تحتوي على معلومات مفصلة لكل خطأ.
class BuildMessage {
name: string;
position?: Position;
message: string;
level: "error" | "warning" | "info" | "debug" | "verbose";
}
class ResolveMessage extends BuildMessage {
code: string;
referrer: string;
specifier: string;
importKind: ImportKind;
}عند نجاح البناء، الكائن المرتجع يحتوي على خاصية logs، التي تحتوي على تحذيرات الحزمة ورسائل المعلومات.
const result = await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
});
if (result.logs.length > 0) {
console.warn("Build succeeded with warnings:");
for (const message of result.logs) {
// Bun ستطبع كائن الرسالة بشكل جميل
console.warn(message);
}
}المرجع
interface Bun {
build(options: BuildOptions): Promise<BuildOutput>;
}
interface BuildConfig {
entrypoints: string[]; // قائمة مسار الملف
outdir?: string; // دليل الإخراج
target?: Target; // افتراضي: "browser"
/**
* تنسيق وحدة الإخراج. انتظار المستوى العلوي مدعوم فقط لـ `"esm"`.
*
* يمكن أن يكون:
* - `"esm"`
* - `"cjs"` (**تجريبي**)
* - `"iife"` (**تجريبي**)
*
* @default "esm"
*/
format?: "esm" | "cjs" | "iife";
/**
* كائن تكوين JSX للتحكم في سلوك تحويل JSX
*/
jsx?: {
runtime?: "automatic" | "classic";
importSource?: string;
factory?: string;
fragment?: string;
sideEffects?: boolean;
development?: boolean;
};
naming?:
| string
| {
chunk?: string;
entry?: string;
asset?: string;
};
root?: string; // جذر المشروع
splitting?: boolean; // افتراضي true، تمكين تقسيم الكود
plugins?: BunPlugin[];
external?: string[];
packages?: "bundle" | "external";
publicPath?: string;
define?: Record<string, string>;
loader?: { [k in string]: Loader };
sourcemap?: "none" | "linked" | "inline" | "external" | boolean; // افتراضي: "none"، true -> "inline"
/**
* شروط `exports` في package.json المستخدمة عند حل الواردات
*
* مكافئ لـ `--conditions` في `bun build` أو `bun run`.
*
* https://nodejs.org/api/packages.html#exports
*/
conditions?: Array<string> | string;
/**
* يتحكم في كيفية التعامل مع متغيرات البيئة أثناء الحزمة.
*
* يمكن أن يكون واحدًا من:
* - `"inline"`: يحقن متغيرات البيئة في الإخراج المحزم عن طريق تحويل مراجع `process.env.FOO`
* إلى سلاسل حرفية تحتوي على قيم متغيرات البيئة الفعلية
* - `"disable"`: يعطل حقن متغيرات البيئة بالكامل
* - سلسلة تنتهي بـ `*`: تحقق متغيرات البيئة التي تطابق البادئة المعطاة.
* على سبيل المثال، `"MY_PUBLIC_*"` ستتضمن فقط متغيرات البيئة التي تبدأ بـ "MY_PUBLIC_"
*/
env?: "inline" | "disable" | `${string}*`;
minify?:
| boolean
| {
whitespace?: boolean;
syntax?: boolean;
identifiers?: boolean;
};
/**
* تجاهل إعلانات إزالة الكود الميت/هز الشجرة مثل @__PURE__ وحقول "sideEffects" في package.json.
* يجب استخدام هذا فقط كحل مؤقت للإعلانات غير الصحيحة في المكتبات.
*/
ignoreDCEAnnotations?: boolean;
/**
* فرض إصدار إعلانات @__PURE__ حتى لو كان minify.whitespace true.
*/
emitDCEAnnotations?: boolean;
/**
* إنشاء bytecode للإخراج. هذا يمكن أن يحسن بشكل كبير
* أوقات البدء البارد، لكن سيجعل الإخراج النهائي أكبر ويزيد قليلاً
* استخدام الذاكرة.
*
* Bytecode مدعوم حاليًا فقط لـ CommonJS (`format: "cjs"`).
*
* يجب أن يكون `target: "bun"`
* @default false
*/
bytecode?: boolean;
/**
* إضافة راية إلى الكود المحزم مثل "use client";
*/
banner?: string;
/**
* إضافة تذييل إلى الكود المحزم مثل كتلة تعليق مثل
*
* `// made with bun!`
*/
footer?: string;
/**
* إسقاط استدعاءات الدوال إلى وصولات الخصائص المطابقة.
*/
drop?: string[];
/**
* - عند تعيينه إلى `true`، يرفض promise المرتجع مع AggregateError عند حدوث فشل في البناء.
* - عند تعيينه إلى `false`، يرجع {@link BuildOutput} مع `{success: false}`
*
* @default true
*/
throw?: boolean;
/**
* مسار ملف tsconfig.json مخصص لاستخدامه لحل المسار.
* مكافئ لـ `--tsconfig-override` في CLI.
*/
tsconfig?: string;
outdir?: string;
}
interface BuildOutput {
outputs: BuildArtifact[];
success: boolean;
logs: Array<BuildMessage | ResolveMessage>;
}
interface BuildArtifact extends Blob {
path: string;
loader: Loader;
hash: string | null;
kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode";
sourcemap: BuildArtifact | null;
}
type Loader =
| "js"
| "jsx"
| "ts"
| "tsx"
| "css"
| "json"
| "jsonc"
| "toml"
| "yaml"
| "text"
| "file"
| "napi"
| "wasm"
| "html";
interface BuildOutput {
outputs: BuildArtifact[];
success: boolean;
logs: Array<BuildMessage | ResolveMessage>;
}
declare class ResolveMessage {
readonly name: "ResolveMessage";
readonly position: Position | null;
readonly code: string;
readonly message: string;
readonly referrer: string;
readonly specifier: string;
readonly importKind:
| "entry_point"
| "stmt"
| "require"
| "import"
| "dynamic"
| "require_resolve"
| "at"
| "at_conditional"
| "url"
| "internal";
readonly level: "error" | "warning" | "info" | "debug" | "verbose";
toString(): string;
}