esbuild عبارة عن أداة تجميع سريعة يمكنها تحسين تعليمات JavaScript وTypeScript وJSX وCSS. ستساعدك هذه المقالة على سرعة استخدام esbuild وستوضح لك كيفية إنشاء نظام البناء الخاص بك دون تبعيات أخرى.
كيف يعمل esbuild؟
أطر مثل برغي لقد اعتمدت esbuild، ولكن يمكنك استخدام esbuild كأداة مستقلة في مشاريعك الخاصة.
-
esbuild حزم كود جافا سكريبت في ملف واحد بطريقة مشابهة للمجمعات مثل التراكمي. هذه هي الوظيفة الأساسية لـ esbuild، وهي تعمل على حل الوحدات النمطية، والإبلاغ عن مشكلات بناء الجملة، و"اهتزاز الشجرة" لإزالة الوظائف غير المستخدمة، ومسح بيانات التسجيل ومصحح الأخطاء، وتقليل التعليمات البرمجية، وتوفير خرائط المصدر.
-
إنشاء حزم كود CSS في ملف واحد. إنه ليس بديلاً كاملاً للمعالجات المسبقة مثل ساس or بوستCSS، ولكن يمكن لـ esbuild التعامل مع الأجزاء الجزئية، ومشكلات بناء الجملة، والتداخل، وترميز الأصول المضمنة، وخرائط المصدر، والبادئة التلقائية، والتصغير. قد يكون هذا كل ما تحتاجه.
-
يوفر esbuild أيضًا خادم تطوير محلي مع التجميع التلقائي وإعادة التحميل السريع، لذلك ليست هناك حاجة للتحديث. لا يحتوي على جميع الميزات التي تقدمها مزامنة المتصفح، ولكنه جيد بما فيه الكفاية لمعظم الحالات.
سيساعدك الكود أدناه على فهم مفاهيم esbuild حتى تتمكن من استكشاف المزيد من فرص التكوين لمشاريعك.
لماذا الحزمة؟
يوفر تجميع التعليمات البرمجية في ملف واحد فوائد متنوعة. وهنا بعض منها:
- يمكنك تطوير ملفات مصدر أصغر حجمًا ومكتفية ذاتيًا يسهل صيانتها
- يمكنك فحص التعليمات البرمجية وتجميلها والتحقق من تركيبها أثناء عملية التجميع
- يمكن للمجمع إزالة الوظائف غير المستخدمة - المعروفة باسم هز الشجرة
- يمكنك تجميع إصدارات بديلة من نفس الكود وإنشاء أهداف للمتصفحات الأقدم مثل Node.js وDeno وما إلى ذلك.
- يتم تحميل الملفات الفردية بشكل أسرع من الملفات المتعددة ولا يتطلب المتصفح دعم وحدة ES
- يمكن للتجميع على مستوى الإنتاج تحسين الأداء عن طريق تصغير التعليمات البرمجية وإزالة بيانات التسجيل وتصحيح الأخطاء
لماذا استخدام esbuild؟
على عكس حزم JavaScript، فإن esbuild عبارة عن برنامج Go قابل للتنفيذ والذي ينفذ معالجة متوازية ثقيلة. إنه سريع وأسرع بما يصل إلى مائة مرة من Rollup أو Parcel أو Webpack. يمكن أن يوفر أسابيع من وقت التطوير طوال عمر المشروع.
بالإضافة إلى ذلك، يقدم esbuild أيضًا:
- تجميع وتجميع مدمج لـ JavaScript وTypeScript وJSX وCSS
- واجهات برمجة تطبيقات تكوين سطر الأوامر وجافا سكريبت وGo
- دعم وحدات ES وCommonJS
- خادم تطوير محلي مع وضع المراقبة وإعادة التحميل المباشر
- الإضافات لإضافة المزيد من الوظائف
- توثيق شامل و أداة التجريب عبر الإنترنت
لماذا تجنب esbuild؟
في وقت كتابة هذا التقرير، وصل esbuild إلى الإصدار 0.18. إنه منتج موثوق به ولكنه لا يزال منتجًا تجريبيًا.
يتم تحديث esbuild بشكل متكرر وقد تتغير الخيارات بين الإصدارات. ال توثيق توصي بالالتزام بإصدار محدد. يمكنك تحديثه، ولكن قد تحتاج إلى ترحيل ملفات التكوين الخاصة بك والتعمق في الوثائق الجديدة لاكتشاف التغييرات العاجلة.
لاحظ أيضًا أن esbuild لا يقوم بالتحقق من نوع TypeScript، لذا ستظل بحاجة إلى التشغيل tsc -noEmit
.
بداية فائقة السرعة
إذا لزم الأمر، قم بإنشاء مشروع Node.js جديد باستخدام npm init
، ثم قم بتثبيت esbuild محليًا باعتباره تابعًا للتطوير:
npm install esbuild --save-dev --save-exact
يتطلب التثبيت حوالي 9 ميغابايت. تحقق من أنه يعمل عن طريق تشغيل هذا الأمر لرؤية الإصدار المثبت:
./node_modules/.bin/esbuild --version
أو قم بتشغيل هذا الأمر لعرض تعليمات CLI:
./node_modules/.bin/esbuild --help
استخدم واجهة برمجة تطبيقات CLI لتجميع برنامج نصي للإدخال (myapp.js
) وجميع الوحدات المستوردة في ملف واحد اسمه bundle.js
. سيقوم esbuild بإخراج ملف باستخدام تنسيق التعبير الوظيفي الافتراضي (IIFE) الذي يستهدف المستعرض والذي يتم استدعاؤه على الفور:
./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js
اطلع على تثبيت esbuild بطرق أخرى إذا كنت لا تستخدم Node.js.
مشروع مثال
قم بتنزيل ملفات الأمثلة و تكوين esbuild من جيثب. إنه مشروع Node.js، لذا قم بتثبيت تبعية esbuild الفردية باستخدام:
npm install
بناء الملفات المصدر في src
ل build
الدليل وابدأ خادم التطوير باستخدام:
npm start
انتقل الآن إلى localhost:8000
في متصفحك لعرض صفحة ويب تعرض ساعة الوقت الفعلي. عند تحديث أي ملف CSS في src/css/
or src/css/partials
، سيقوم esbuild بإعادة تجميع التعليمات البرمجية وإعادة تحميل الأنماط مباشرة.
صحافة السيطرة|كمد + السيطرة|كمد لإيقاف الخادم.
قم بإنشاء إصدار إنتاج للنشر باستخدام:
npm run build
افحص ملفات CSS وJavaScript في ملف build
الدليل لرؤية الإصدارات المصغرة بدون خرائط المصدر.
نظرة عامة على المشروع
تم إنشاء صفحة الساعة في الوقت الفعلي في ملف build
الدليل باستخدام الملفات المصدر من src
.
• package.json
يحدد الملف خمسة npm
نصوص. الأول يحذف build
دليل:
"clean": "rm -rf ./build",
قبل حدوث أي تجميع، أ init
يعمل البرنامج النصي clean
، يخلق جديد build
الدليل والنسخ:
- ملف HTML ثابت من
src/html/index.html
إلىbuild/index.html
- صور ثابتة من
src/images/
إلىbuild/images/
"init": "npm run clean && mkdir ./build && cp ./src/html/* ./build/ && cp -r ./src/images ./build",
An esbuild.config.js
يتحكم الملف في عملية تجميع esbuild باستخدام JavaScript API. يعد هذا أسهل في الإدارة من تمرير الخيارات إلى واجهة برمجة تطبيقات CLI، والتي يمكن أن تصبح غير عملية. ان npm
bundle
يعمل البرنامج النصي init
تليها node ./esbuild.config.js
:
"bundle": "npm run init && node ./esbuild.config.js",
الاخيرتين npm
تشغيل البرامج النصية bundle
مع إما أ production
or development
تم تمرير المعلمة إلى ./esbuild.config.js
للتحكم في البناء:
"build": "npm run bundle -- production",
"start": "npm run bundle -- development"
متى ./esbuild.config.js
يتم تشغيله، فهو يحدد ما إذا كان ينبغي إنشاءه بشكل مصغر production
الملفات (الافتراضي) أو development
الملفات ذات التحديثات التلقائية وخرائط المصدر وخادم إعادة التحميل المباشر. في كلتا الحالتين، قم ببناء الحزم:
- ملف الدخول CSS
src/css/main.css
إلىbuild/css/main.css
- ملف جافا سكريبت الإدخال
scr/js/main.js
إلىbuild/js/main.js
تكوين esbuild
package.json
لديها "type"
of "module"
لذلك كل .js
يمكن للملفات استخدام وحدات ES. ال esbuild.config.js
واردات البرنامج النصي esbuild
ومجموعات productionMode
إلى true
عند التجميع للإنتاج أو false
عند التجميع من أجل التطوير:
import { argv } from 'node:process';
import * as esbuild from 'esbuild'; const productionMode = ('development' !== (argv[2] || process.env.NODE_ENV)), target = 'chrome100,firefox100,safari15'.split(','); console.log(`${ productionMode ? 'production' : 'development' } build`);
هدف الحزمة
نلاحظ أن متغير الهدف يحدد مجموعة من المتصفحات وأرقام الإصدارات لاستخدامها في التكوين. يؤثر هذا على المخرجات المجمعة ويغير البنية لدعم منصات معينة. على سبيل المثال، يمكن لـ esbuild:
- توسيع تداخل CSS الأصلي في محددات كاملة (سيبقى التداخل إذا
"Chrome115"
كان الهدف الوحيد) - أضف خصائص CSS مسبوقة بالبائع عند الضرورة
- polyfill ال
??
عامل الاندماج الباطل - إزالة
#
من مجالات الطبقة الخاصة
بالإضافة إلى المتصفحات، يمكنك أيضًا استهدافها node
و es
إصدارات مثل es2020
و esnext
(أحدث ميزات JS وCSS).
حزمة جافا سكريبت
أبسط واجهة برمجة تطبيقات لإنشاء حزمة:
await esbuild.build({ entryPoints: ['myapp.js'], bundle: true outfile: 'bundle.js'
});
يؤدي هذا إلى تكرار أمر CLI المستخدم أعلاه:
./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js
يستخدم مشروع المثال خيارات أكثر تقدمًا مثل مشاهدة الملفات. وهذا يتطلب بناء طويل الأمد سياق الكلام الذي يحدد التكوين:
const buildJS = await esbuild.context({ entryPoints: [ './src/js/main.js' ], format: 'esm', bundle: true, target, drop: productionMode ? ['debugger', 'console'] : [], logLevel: productionMode ? 'error' : 'info', minify: productionMode, sourcemap: !productionMode && 'linked', outdir: './build/js' });
عروض البناء العشرات من خيارات التكوين. فيما يلي ملخص لتلك المستخدمة هنا:
-
entryPoints
يحدد مجموعة من نقاط إدخال الملفات للتجميع. يحتوي المشروع المثال على برنامج نصي واحد في./src/js/main.js
. -
format
يضبط تنسيق الإخراج. يستخدم المثالesm
، ولكن يمكنك تعيينها بشكل اختياريiife
للمتصفحات القديمة أوcommonjs
لـ Node.js. -
bundle
تعيين إلىtrue
تضمين الوحدات المستوردة في ملف الإخراج. -
target
هي مجموعة من المتصفحات المستهدفة المحددة أعلاه. -
drop
مجموعة منconsole
و / أوdebugger
تصريحات لإزالة. في هذه الحالة، تقوم إصدارات الإنتاج بإزالة كليهما وتحتفظ إصدارات التطوير بهما. -
logLevel
يحدد إسهاب التسجيل. يوضح المثال أعلاه الأخطاء أثناء إنشاءات الإنتاج والمزيد من رسائل المعلومات المطولة أثناء إنشاءات التطوير. -
minify
يقلل حجم الكود عن طريق إزالة التعليقات والمسافات البيضاء وإعادة تسمية المتغيرات والوظائف حيثما أمكن ذلك. يتم تصغير مشروع المثال أثناء إنشاءات الإنتاج ولكن يجمل الكود أثناء بناء التطوير. -
sourcemap
تعيين إلىlinked
(في وضع التطوير فقط) ينشئ خريطة مصدر مرتبطة في ملف.map
الملف بحيث يتوفر الملف المصدر الأصلي والخط في أدوات مطور المتصفح. يمكنك أيضًا ضبطinline
لتضمين الخريطة المصدر داخل الملف المجمع،both
لإنشاء كليهما، أوexternal
لتوليد.map
الملف بدون رابط من JavaScript المجمعة. -
outdir
يحدد دليل إخراج الملفات المجمعة.
استدعاء كائن السياق rebuild()
طريقة لتشغيل البناء مرة واحدة - عادةً لبناء الإنتاج:
await buildJS.rebuild();
buildJS.dispose();
استدعاء كائن السياق watch()
طريقة لمواصلة التشغيل وإعادة الإنشاء تلقائيًا عند تغيير الملفات التي تمت مشاهدتها:
await buildJS.watch();
يضمن كائن السياق معالجة الإصدارات اللاحقة بشكل متزايد وإعادة استخدام العمل من الإصدارات السابقة لتحسين الأداء.
جافا سكريبت ملفات الإدخال والإخراج
الدخول src/js/main.js
واردات الملف dom.js
و time.js
وحدات من lib
المجلد الفرعي. يجد كافة العناصر مع فئة من clock
ويضبط محتوى النص الخاص بهم على الوقت الحالي كل ثانية:
import * as dom from './lib/dom.js';
import { formatHMS } from './lib/time.js'; const clock = dom.getAll('.clock'); if (clock.length) { console.log('initializing clock'); setInterval(() => { clock.forEach(c => c.textContent = formatHMS()); }, 1000); }
dom.js
تصدير وظيفتين. main.js
يستورد كلاهما ولكن يستخدم فقط getAll()
:
export function get(selector, doc = document) { return doc.querySelector(selector);
} export function getAll(selector, doc = document) { return Array.from(doc.querySelectorAll(selector));
}
time.js
تصدير وظيفتين. main.js
واردات formatHMS()
، ولكن هذا يستخدم الوظائف الأخرى في الوحدة:
function timePad(n) { return String(n).padStart(2, '0');
} export function formatHM(d = new Date()) { return timePad(d.getHours()) + ':' + timePad(d.getMinutes());
} export function formatHMS(d = new Date()) { return formatHM(d) + ':' + timePad(d.getSeconds());
}
تتم إزالة حزمة التطوير الناتجة (اهتزاز الشجرة) get()
تبدأ من dom.js
ولكن يشمل كل time.js
المهام. يتم أيضًا إنشاء خريطة المصدر:
function getAll(selector, doc = document) { return Array.from(doc.querySelectorAll(selector));
} function timePad(n) { return String(n).padStart(2, "0");
} function formatHM(d = new Date()) { return timePad(d.getHours()) + ":" + timePad(d.getMinutes());
} function formatHMS(d = new Date()) { return formatHM(d) + ":" + timePad(d.getSeconds());
} var clock = getAll(".clock");
if (clock.length) { console.log("initializing clock"); setInterval(() => { clock.forEach((c) => c.textContent = formatHMS()); }, 1e3);
}
(لاحظ أن esbuild يمكن إعادة كتابة let
و const
إلى var
من أجل الصحة والسرعة.)
تعمل حزمة الإنتاج الناتجة على تصغير الكود إلى 322 حرفًا:
function o(t,c=document){return Array.from(c.querySelectorAll(t))}function e(t){return String(t).padStart(2,"0")}function l(t=new Date){return e(t.getHours())+":"+e(t.getMinutes())}function r(t=new Date){return l(t)+":"+e(t.getSeconds())}var n=o(".clock");n.length&&setInterval(()=>{n.forEach(t=>t.textContent=r())},1e3);
تجميعة CSS
تستخدم تجميعة CSS في مشروع المثال كائن سياق مشابهًا لـ JavaScript أعلاه:
const buildCSS = await esbuild.context({ entryPoints: [ './src/css/main.css' ], bundle: true, target, external: ['/images/*'], loader: { '.png': 'file', '.jpg': 'file', '.svg': 'dataurl' }, logLevel: productionMode ? 'error' : 'info', minify: productionMode, sourcemap: !productionMode && 'linked', outdir: './build/css' });
يحدد ملف external
الخيار كمجموعة من الملفات والمسارات إلى منع من البناء. في المشروع المثال، الملفات الموجودة في src/images/
يتم نسخ الدليل إلى build
الدليل حتى يتمكن HTML أو CSS أو JavaScript من الرجوع إليها مباشرةً. إذا لم يتم تعيين هذا، فسيقوم esbuild بنسخ الملفات إلى الإخراج build/css/
الدليل عند استخدامها في background-image
أو خصائص مماثلة.
• loader
يغير الخيار كيفية تعامل esbuild مع ملف مستورد لم تتم الإشارة إليه كملف external
أصل. في هذا المثال:
- تصبح صور SVG مضمنة كمعرفات URI للبيانات
- يتم نسخ صور PNG وJPG إلى الملف
build/css/
الدليل والمشار إليه كملفات
ملفات الإدخال والإخراج CSS
الدخول src/css/main.css
واردات الملف variables.css
و elements.css
من partials
المجلد الفرعي:
@import './partials/variables.css';
@import './partials/elements.css';
variables.css
يحدد الخصائص المخصصة الافتراضية:
:root { --font-body: sans-serif; --color-fore: #fff; --color-back: #112;
}
elements.css
يحدد جميع الأنماط. ملحوظة:
- ال
body
لديه صورة خلفية محملة من الخارجimages
دليل - ال
h1
متداخلة في الداخلheader
- ال
h1
يحتوي على خلفية SVG والتي سيتم تضمينها - المتصفحات المستهدفة لا تتطلب أي بادئات البائع
*, *::before, ::after { box-sizing: border-box; font-weight: normal; padding: 0; margin: 0;
} body { font-family: var(--font-body); color: var(--color-fore); background: var(--color-back) url(/images/web.png) repeat; margin: 1em;
} header { & h1 { font-size: 2em; padding-left: 1.5em; margin: 0.5em 0; background: url(../../icons/clock.svg) no-repeat; } } .clock { display: block; font-size: 5em; text-align: center; font-variant-numeric: tabular-nums;
}
تقوم حزمة التطوير الناتجة بتوسيع بناء الجملة المتداخل، وتضمين SVG، وإنشاء خريطة مصدر:
:root { --font-body: sans-serif; --color-fore: #fff; --color-back: #112;
} *,
*::before,
::after { box-sizing: border-box; font-weight: normal; padding: 0; margin: 0;
}
body { font-family: var(--font-body); color: var(--color-fore); background: var(--color-back) url(/images/web.png) repeat; margin: 1em;
}
header h1 { font-size: 2em; padding-left: 1.5em; margin: 0.5em 0; background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>*{fill:none;stroke:%23fff;stroke-width:1.5;stroke-miterlimit:10}</style></defs><circle cx="12" cy="12" r="10.5"></circle><circle cx="12" cy="12" r="0.95"></circle><polyline points="12 4.36 12 12 16.77 16.77"></polyline></svg>') no-repeat;
}
.clock { display: block; font-size: 5em; text-align: center; font-variant-numeric: tabular-nums;
}
تعمل حزمة الإنتاج الناتجة على تصغير الكود إلى 764 حرفًا (تم حذف SVG هنا):
:root{--font-body: sans-serif;--color-fore: #fff;--color-back: #112}*,*:before,:after{box-sizing:border-box;font-weight:400;padding:0;margin:0}body{font-family:var(--font-body);color:var(--color-fore);background:var(--color-back) url(/images/web.png) repeat;margin:1em}header h1{font-size:2em;padding-left:1.5em;margin:.5em 0;background:url('data:image/svg+xml,<svg...></svg>') no-repeat}.clock{display:block;font-size:5em;text-align:center;font-variant-numeric:tabular-nums}
المشاهدة وإعادة البناء والخدمة
ما تبقى من esbuild.config.js
يتم إنشاء حزم البرامج النصية مرة واحدة للإنتاج قبل الإنهاء:
if (productionMode) { await buildCSS.rebuild(); buildCSS.dispose(); await buildJS.rebuild(); buildJS.dispose(); }
أثناء إنشاءات التطوير، يستمر البرنامج النصي في العمل، ويراقب تغييرات الملف، ويتم تجميعه تلقائيًا مرة أخرى. ال buildCSS
يُطلق السياق خادم ويب للتطوير باستخدام build/
كدليل جذر:
else { await buildCSS.watch(); await buildJS.watch(); await buildCSS.serve({ servedir: './build' }); }
ابدأ بناء التطوير باستخدام:
npm start
ثم انتقل إلى localhost:8000
لعرض الصفحة.
على عكس Browsersync، ستحتاج إلى إضافة التعليمات البرمجية الخاصة بك إلى صفحات التطوير لإعادة التحميل المباشر. عند حدوث تغييرات، يرسل esbuild معلومات حول التحديث عبر ملف حدث إرسال الخادم. الخيار الأبسط هو إعادة تحميل الصفحة بالكامل عند حدوث أي تغيير:
new EventSource('/esbuild').addEventListener('change', () => location.reload());
يستخدم مشروع المثال كائن سياق CSS لإنشاء الخادم. وذلك لأنني أفضل تحديث تغييرات JavaScript يدويًا — ولأنني لم أتمكن من إيجاد طريقة لـ esbuild لإرسال حدث لتحديثات CSS وJS! تتضمن صفحة HTML البرنامج النصي التالي لاستبدال ملفات CSS المحدثة دون تحديث الصفحة بالكامل (إعادة التحميل السريع):
<script type="module">
// esbuild server-sent event - live reload CSS
new EventSource('/esbuild').addEventListener('change', e => { const { added, removed, updated } = JSON.parse(e.data); // reload when CSS files are added or removed if (added.length || removed.length) { location.reload(); return; } // replace updated CSS files Array.from(document.getElementsByTagName('link')).forEach(link => { const url = new URL(link.href), path = url.pathname; if (updated.includes(path) && url.host === location.host) { const css = link.cloneNode(); css.onload = () => link.remove(); css.href = `${ path }?${ +new Date() }`; link.after(css); } }) });
لاحظ أن esbuild لا يدعم حاليًا إعادة التحميل السريع لـ JavaScript — لا يعني ذلك أنني أثق به على أي حال!
نبذة عامة
مع القليل من التكوين، يمكن أن يكون esbuild كافيًا للتعامل مع جميع متطلبات تطوير مشروعك وبناء الإنتاج.
هناك مجموعة شاملة من الإضافات إذا كنت تحتاج إلى وظائف أكثر تقدما. انتبه إلى أن هذه غالبًا ما تشتمل على Sass أو PostCSS أو أدوات إنشاء مماثلة، لذا فهي تستخدم esbuild بشكل فعال كمدير مهام. انت تستطيع دائما إنشاء الإضافات الخاصة بك إذا كنت بحاجة إلى مزيد من الخيارات المخصصة وخفيفة الوزن.
لقد تم استخدام esbuild لمدة عام. السرعة مذهلة مقارنة ببرامج الحزم المماثلة، وتظهر الميزات الجديدة بشكل متكرر. الجانب السلبي الوحيد هو كسر التغييرات التي تتطلب الصيانة.
لا تدعي esbuild أنها أداة بناء موحدة وشاملة، ولكنها ربما تكون أقرب إلى هذا الهدف من روما.
- محتوى مدعوم من تحسين محركات البحث وتوزيع العلاقات العامة. تضخيم اليوم.
- PlatoData.Network Vertical Generative Ai. تمكين نفسك. الوصول هنا.
- أفلاطونايستريم. ذكاء Web3. تضخيم المعرفة. الوصول هنا.
- أفلاطون السيارات / المركبات الكهربائية ، كربون، كلينتك ، الطاقة، بيئة، شمسي، إدارة المخلفات. الوصول هنا.
- BlockOffsets. تحديث ملكية الأوفست البيئية. الوصول هنا.
- المصدر https://www.sitepoint.com/esbuild-introduction/?utm_source=rss