Skip to content

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

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './build',
});

CLI

bash
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 بسيط يتم عرضه من جانب العميل.

tsx
import * as ReactDOM from "react-dom/client";
import { Component } from "./Component";

const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(<Component message="Sup!" />);
tsx
export function Component(props: { message: string }) {
  return <h1>{props.message}</h1>;
}

هنا، index.tsx هو "نقطة الدخول" لتطبيقنا. عادةً، سيكون هذا برنامجًا نصيًا يؤدي بعض الآثار الجانبية، مثل بدء خادم أو - في هذه الحالة - تهيئة جذر React. لأننا نستخدم TypeScript و JSX، نحتاج إلى حزمة كودنا قبل أن يمكن إرساله إلى المتصفح.

لإنشاء حزمتنا:

ts
await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
});
bash
bun build ./index.tsx --outdir ./out

لكل ملف محدد في entrypoints، ستنشئ Bun حزمة جديدة. سيتم كتابة هذه الحزمة على القرص في دليل ./out (كما تم حلها من دليل العمل الحالي). بعد تشغيل البناء، يبدو نظام الملفات هكذا:

file system
text
.
├── index.tsx
├── Component.tsx
└── out
    └── index.js

محتويات out/index.js ستبدو شيئًا مثل هذا:

out/index.js
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,
  ),
);

وضع المراقبة

مثل وقت التشغيل ومشغل الاختبار، تدعم الحزمة وضع المراقبة أصلاً.

bash
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/>
.jsoncJSON مع تعليقات. يتم تحليل الملفات وتضمينها في الحزمة ككائن 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، ويتم حل الاستيراد كمسار إلى الملف.

ts
// نقطة دخول الحزمة
import logo from "./logo.svg";
console.log(logo);
ts
// الإخراج المحزم
var logo = "./logo-a7305bdef.svg";
console.log(logo);

السلوك الدقيق لمحمل الملفات يتأثر أيضًا بـ naming و publicPath.

المكونات الإضافية

يمكن تجاوز أو تمديد السلوك الموصوف في هذا الجدول باستخدام المكونات الإضافية. راجع صفحة الحزمة > المحملات للوثائق الكاملة.

واجهة برمجة التطبيقات

entrypoints

مصفوفة من المسارات المقابلة لنقاط دخول تطبيقنا. سيتم إنشاء حزمة واحدة لكل نقطة دخول.

JavaScript

ts
const result = await Bun.build({
  entrypoints: ["./index.ts"]
});

CLI

bash
bun build ./index.ts

outdir

الدليل حيث سيتم كتابة ملفات الإخراج.

JavaScript

ts
const result = await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './out'
});
// => { success: boolean, outputs: `BuildArtifact[]`, logs: `BuildMessage[]` }

CLI

bash
bun build ./index.ts --outdir ./out

إذا لم يتم تمرير outdir إلى واجهة برمجة تطبيقات JavaScript، لن يتم كتابة الكود المحزم على القرص. يتم إرجاع الملفات المحزمة في مصفوفة من كائنات BuildArtifact. هذه الكائنات هي Blobs مع خصائص إضافية؛ راجع المخرجات للوثائق الكاملة.

ts
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

ts
await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './out',
  target: 'browser', // افتراضي
})

CLI

bash
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

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  format: "esm",
})

CLI

bash
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

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  format: "cjs",
})

CLI

bash
bun build ./index.tsx --outdir ./out --format cjs

format: "iife" - IIFE

TODO: توثيق IIFE بمجرد دعم globalNames.

jsx

تكوين سلوك تحويل JSX. يسمح بالتحكم الدقيق في كيفية تجميع JSX.

مثال وقت التشغيل الكلاسيكي (يستخدم factory و fragment):

ts
await Bun.build({
  entrypoints: ["./app.tsx"],
  outdir: "./out",
  jsx: {
    factory: "h",
    fragment: "Fragment",
    runtime: "classic",
  },
});
bash
# تكوين JSX يتم التعامل معه عبر bunfig.toml أو tsconfig.json
bun build ./app.tsx --outdir ./out

مثال وقت التشغيل التلقائي (يستخدم importSource):

ts
await Bun.build({
  entrypoints: ["./app.tsx"],
  outdir: "./out",
  jsx: {
    importSource: "preact",
    runtime: "automatic",
  },
});
bash
# تكوين JSX يتم التعامل معه عبر bunfig.toml أو tsconfig.json
bun build ./app.tsx --outdir ./out

splitting

ما إذا كان سيتم تمكين تقسيم الكود.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  splitting: false, // افتراضي
})

CLI

bash
bun build ./index.tsx --outdir ./out --splitting

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

ts
import { shared } from "./shared.ts";
ts
import { shared } from "./shared.ts";
ts
export const shared = "shared";

لحزمة entry-a.ts و entry-b.ts مع تمكين تقسيم الكود:

JavaScript

ts
await Bun.build({
  entrypoints: ['./entry-a.ts', './entry-b.ts'],
  outdir: './out',
  splitting: true,
})

CLI

bash
bun build ./entry-a.ts ./entry-b.ts --outdir ./out --splitting

تشغيل هذا البناء سينتج الملفات التالية:

file system
text
.
├── entry-a.tsx
├── entry-b.tsx
├── shared.tsx
└── out
    ├── entry-a.js
    ├── entry-b.js
    └── chunk-2fce6291bf86559d.js

الملف chunk-2fce6291bf86559d.js الذي تم إنشاؤه يحتوي على الكود المشترك. لتجنب التصادمات، يتضمن اسم الملف تلقائيًا تجزئة محتوى افتراضيًا. يمكن تخصيص هذا باستخدام naming.

plugins

قائمة المكونات الإضافية لاستخدامها أثناء الحزمة.

ts
await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
  plugins: [
    /* ... */
  ],
});

Bun تنفذ نظام مكونات إضافية عالمي لكل من وقت التشغيل والحزمة في Bun. راجع وثائق المكونات الإضافية للوثائق الكاملة.

env

يتحكم في كيفية التعامل مع متغيرات البيئة أثناء الحزمة. داخليًا، يستخدم هذا define لحقن متغيرات البيئة في الحزمة، لكن يجعل من الأسهل تحديد متغيرات البيئة لحقنها.

env: "inline"

يحقق متغيرات البيئة في الإخراج المحزم عن طريق تحويل مراجع process.env.FOO إلى سلاسل حرفية تحتوي على قيم متغيرات البيئة الفعلية.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  env: "inline",
})

CLI

bash
bun build ./index.tsx --outdir ./out --env inline

للمدخلات أدناه:

input.js
js
// input.js
console.log(process.env.FOO);
console.log(process.env.BAZ);

الحزمة التي تم إنشاؤها ستحتوي على الكود التالي:

output.js
js
// output.js
console.log("bar");
console.log("123");

env: "PUBLIC_*" (بادئة)

يحقق متغيرات البيئة المطابقة للبادئة المعطاة (الجزء قبل حرف *)، ويستبدل process.env.FOO بقيمة متغير البيئة الفعلية. هذا مفيد لتحقق انتقائي لمتغيرات البيئة لأشياء مثل URLs العامة أو رموز جانب العميل، دون القلق بشأن حقن بيانات اعتماد خاصة في حزم الإخراج.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  
  // تحقق جميع متغيرات البيئة التي تبدأ بـ "ACME_PUBLIC_"
  env: "ACME_PUBLIC_*",
})

CLI

bash
bun build ./index.tsx --outdir ./out --env ACME_PUBLIC_*

على سبيل المثال، مع متغيرات البيئة التالية:

bash
FOO=bar BAZ=123 ACME_PUBLIC_URL=https://acme.com

وكود المصدر:

tsx
console.log(process.env.FOO);
console.log(process.env.ACME_PUBLIC_URL);
console.log(process.env.BAZ);

الحزمة التي تم إنشاؤها ستحتوي على الكود التالي:

output.js
js
console.log(process.env.FOO);
console.log("https://acme.com");
console.log(process.env.BAZ);

env: "disable"

تعطيل حقن متغيرات البيئة بالكامل.

sourcemap

يحدد نوع خريطة المصدر المراد إنشاؤها.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  sourcemap: 'linked', // افتراضي 'none'
})

CLI

bash
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

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  minify: true, // افتراضي false
})

CLI

bash
bun build ./index.tsx --outdir ./out --minify

لتمكين تصغيرات معينة بشكل دقيق:

JavaScript

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

CLI

bash
bun build ./index.tsx --outdir ./out --minify-whitespace --minify-identifiers --minify-syntax

external

قائمة من مسارات الاستيراد لاعتبارها خارجية. افتراضي [].

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ["lodash", "react"], // افتراضي: []
})

CLI

bash
bun build ./index.tsx --outdir ./out --external lodash --external react

الاستيراد الخارجي هو الذي لن يتم تضمينه في الحزمة النهائية. بدلاً من ذلك، سيتم ترك بيان الاستيراد كما هو، ليتم حله في وقت التشغيل.

على سبيل المثال، ضع في اعتبارك ملف نقطة الدخول التالي:

tsx
import _ from "lodash";
import { z } from "zod";

const value = z.string().parse("Hello world!");
console.log(_.upperCase(value));

عادةً، حزمة index.tsx ستنشئ حزمة تحتوي على كود المصدر الكامل لحزمة "zod". إذا أردنا بدلاً من ذلك ترك بيان الاستيراد كما هو، يمكننا تعليمه كخارجي:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ['zod'],
})

CLI

bash
bun build ./index.tsx --outdir ./out --external zod

الحزمة التي تم إنشاؤها ستبدو شيئًا مثل هذا:

out/index.js
js
import { z } from "zod";

// ...
// محتويات حزمة "lodash"
// بما في ذلك دالة `_.upperCase`

var value = z.string().parse("Hello world!");
console.log(_.upperCase(value));

لتعليم جميع الواردات كخارجية، استخدم البدل *:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ['*'],
})

CLI

bash
bun build ./index.tsx --outdir ./out --external '*'

packages

التحكم في ما إذا كانت تبعيات الحزمة مُضمنة في الحزمة أم لا. القيم الممكنة: bundle (افتراضي)، external. تعامل Bun مع أي استيراد مساره لا يبدأ بـ . أو .. أو / كحزمة.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.ts'],
  packages: 'external',
})

CLI

bash
bun build ./index.ts --packages external

naming

يخصص أسماء الملفات التي تم إنشاؤها. افتراضي ./[dir]/[name].[ext].

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: "[dir]/[name].[ext]", // افتراضي
})

CLI

bash
bun build ./index.tsx --outdir ./out --entry-naming "[dir]/[name].[ext]"

افتراضيًا، تستند أسماء الحزم التي تم إنشاؤها إلى اسم نقطة الدخول المرتبطة.

file system
text
.
├── index.tsx
└── out
    └── index.js

مع نقاط دخول متعددة، سيعكس تسلسل الملفات الذي تم إنشاؤه هيكل الدليل لنقاط الدخول.

file system
text
.
├── index.tsx
└── nested
    └── index.tsx
└── out
    ├── index.js
    └── nested
        └── index.js

يمكن تخصيص أسماء ومواقع الملفات التي تم إنشاؤها باستخدام حقل naming. يقبل هذا الحقل سلسلة قالب تُستخدم لإنشاء أسماء الملفات لجميع الحزم المقابلة لنقاط الدخول. حيث يتم استبدال الرموز التالية بقيمها المقابلة:

  • [name] - اسم ملف نقطة الدخول، بدون الامتداد.
  • [ext] - امتداد الحزمة التي تم إنشاؤها.
  • [hash] - تجزئة لمحتويات الحزمة.
  • [dir] - المسار النسبي من جذر المشروع إلى الدليل الأصلي للملف المصدر.

على سبيل المثال:

Token[name][ext][hash][dir]
./index.tsxindexjsa1b2c3d4"" (سلسلة فارغة)
./nested/entry.tsentryjsc3d4e5f6"nested"

يمكننا دمج هذه الرموز لإنشاء سلسلة قالب. على سبيل المثال، لتضمين التجزئة في أسماء الحزم التي تم إنشاؤها:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: 'files/[dir]/[name]-[hash].[ext]',
})

CLI

bash
bun build ./index.tsx --outdir ./out --entry-naming 'files/[dir]/[name]-[hash].[ext]'

هذا البناء سينتج هيكل الملفات التالي:

file system
text
.
├── index.tsx
└── out
    └── files
        └── index-a1b2c3d4.js

عند تقديم سلسلة لحقل naming، تُستخدم فقط للحزم التي تقابل نقاط الدخول. لا تتأثر أسماء chunks والأصول المنسوخة. باستخدام واجهة برمجة تطبيقات JavaScript، يمكن تحديد سلاسل قالب منفصلة لكل نوع من الملفات التي تم إنشاؤها.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: {
    // قيم افتراضية
    entry: '[dir]/[name].[ext]',
    chunk: '[name]-[hash].[ext]',
    asset: '[name]-[hash].[ext]',
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out \
  --entry-naming '[dir]/[name].[ext]' \
  --chunk-naming '[name]-[hash].[ext]' \
  --asset-naming '[name]-[hash].[ext]'

root

دليل جذر المشروع.

JavaScript

ts
await Bun.build({
  entrypoints: ['./pages/a.tsx', './pages/b.tsx'],
  outdir: './out',
  root: '.',
})

CLI

bash
bun build ./pages/a.tsx ./pages/b.tsx --outdir ./out --root .

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

file system
text
.
└── pages
  └── index.tsx
  └── settings.tsx

يمكننا بناء كلتا نقطتي الدخول في دليل pages:

JavaScript

js
await Bun.build({
  entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
  outdir: './out',
})

CLI

bash
bun build ./pages/index.tsx ./pages/settings.tsx --outdir ./out

هذا سينتج هيكل ملفات مثل هذا:

file system
text
.
└── pages
  └── index.tsx
  └── settings.tsx
└── out
  └── index.js
  └── settings.js

بما أن دليل pages هو أول سلف مشترك لملفات نقطة الدخول، يُعتبر جذر المشروع. هذا يعني أن الحزم التي تم إنشاؤها تعيش في المستوى الأعلى من دليل out؛ لا يوجد دليل out/pages.

يمكن تجاوز هذا السلوك عن طريق تحديد خيار root:

JavaScript

js
await Bun.build({
  entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
  outdir: './out',
  root: '.',
})

CLI

bash
bun build ./pages/index.tsx ./pages/settings.tsx --outdir ./out --root .

عن طريق تحديد . كـ root، سيبدو هيكل الملفات الذي تم إنشاؤه هكذا:

.
└── pages
  └── index.tsx
  └── settings.tsx
└── out
  └── pages
    └── index.js
    └── settings.js

publicPath

بادئة تُضاف إلى أي مسارات استيراد في الكود المحزم.

في كثير من الحالات، لن تحتوي الحزم التي تم إنشاؤها على أي بيانات استيراد. بعد كل شيء، هدف الحزمة هو دمج كل الكود في ملف واحد. ومع ذلك هناك عدد من الحالات التي ستحتوي فيها الحزم التي تم إنشاؤها على بيانات استيراد.

  • واردات الأصول - عند استيراد نوع ملف غير معترف به مثل *.svg، تفوض الحزمة إلى محمل الملفات، الذي ينسخ الملف إلى outdir كما هو. يتم تحويل الاستيراد إلى متغير
  • الوحدات الخارجية - يمكن تعليم الملفات والوحدات كخارجية، وفي هذه الحالة لن يتم تضمينها في الحزمة. بدلاً من ذلك، سيتم ترك بيان الاستيراد في الحزمة النهائية.
  • التقسيم. عند تمكين splitting، قد تنشئ الحزمة ملفات "chunk" منفصلة تمثل الكود المشترك بين نقاط دخول متعددة.

في أي من هذه الحالات، قد تحتوي الحزم النهائية على مسارات إلى ملفات أخرى. افتراضيًا هذه الواردات نسبية. هنا مثال على استيراد أصل بسيط:

ts
import logo from "./logo.svg";
console.log(logo);
ts
var logo = "./logo-a7305bdef.svg";
console.log(logo);

تعيين publicPath سيقوم ببادئة جميع مسارات الملفات بالقيمة المحددة.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  publicPath: 'https://cdn.example.com/', // افتراضي غير معرّف
})

CLI

bash
bun build ./index.tsx --outdir ./out --public-path 'https://cdn.example.com/'

ملف الإخراج سيبدو الآن شيئًا مثل هذا.

out/index.js
js
var logo = "https://cdn.example.com/logo-a7305bdef.svg";

define

خريطة من المعرفات العامة لاستبدالها في وقت البناء. مفاتيح هذا الكائن هي أسماء معرفات، والقيم هي سلاسل JSON سيتم تضمينها.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  define: {
    STRING: JSON.stringify("value"),
    "nested.boolean": "true",
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out --define STRING='"value"' --define nested.boolean=true

loader

خريطة من امتدادات الملفات إلى أسماء المحملات المدمجة. يمكن استخدام هذا لتخصيص كيفية تحميل ملفات معينة بسرعة.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  loader: {
    ".png": "dataurl",
    ".txt": "file",
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out --loader .png:dataurl --loader .txt:file

راية تُضاف إلى الحزمة النهائية، يمكن أن تكون توجيهًا مثل use client لـ react أو كتلة تعليق مثل ترخيص للكود.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  banner: 'use client;'
})

CLI

bash
bun build ./index.tsx --outdir ./out --banner 'use client";'

تذييل يُضاف إلى الحزمة النهائية، يمكن أن يكون شيئًا مثل كتلة تعليق لترخيص أو مجرد بيضة عيد مضحكة.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  footer: '// built with love in SF'
})

CLI

bash
bun build ./index.tsx --outdir ./out --footer '// built with love in SF'

drop

إزالة استدعاءات الدوال من الحزمة. على سبيل المثال، --drop=console ستزيل جميع استدعاءات console.log. سيتم أيضًا إزالة وسيطات الاستدعاءات، بغض النظر عما إذا كانت تلك الوسائط قد يكون لها آثار جانبية. إسقاط debugger سيزيل جميع بيانات debugger.

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  drop: ["console", "debugger", "anyIdentifier.or.propertyAccess"],
})

CLI

bash
bun build ./index.tsx --outdir ./out --drop console --drop debugger

المخرجات

دالة Bun.build ترجع Promise<BuildOutput>، معرّف كالتالي:

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

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

ts
const build = await Bun.build({
  /* */
});

const artifact = build.outputs[0];

// يتم تعيين رأس Content-Type تلقائيًا
return new Response(artifact);

وقت تشغيل Bun ينفذ طباعة خاصة جميلة لكائن BuildArtifact لتسهيل التصحيح.

ts
// build.ts
const build = await Bun.build({
  /* */
});

const artifact = build.outputs[0];
console.log(artifact);
bash
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

ts
await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
  bytecode: true,
})

CLI

bash
bun build ./index.tsx --outdir ./out --bytecode

الملفات التنفيذية

Bun تدعم "تجميع" نقطة دخول JavaScript/TypeScript إلى ملف تنفيذي مستقل. هذا الملف التنفيذي يحتوي على نسخة من ثنائي Bun.

bash
bun build ./cli.tsx --outfile mycli --compile
./mycli

راجع الحزمة > الملفات التنفيذية للوثائق الكاملة.

السجلات والأخطاء

عند الفشل، ترجع Bun.build promise مرفوض مع AggregateError. يمكن تسجيل هذا إلى console للطباعة الجميلة لقائمة الأخطاء، أو قراءته برمجيًا مع كتلة try/catch.

ts
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)، تحتوي على معلومات مفصلة لكل خطأ.

ts
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، التي تحتوي على تحذيرات الحزمة ورسائل المعلومات.

ts
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);
  }
}

المرجع

ts
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;
}

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