Anophel-آنوفل آشنایی با esbuild باندلر در جاوااسکریپت

آشنایی با esbuild باندلر در جاوااسکریپت

انتشار:
1
0

در دنیای توسعه وب، یکی از مسائل اساسی که با آن مواجه می‌شویم، سرعت و بهینگی در فرآیند بیلد و تولید فایل‌های استاتیک است. این مشکل به خصوص در پروژه‌های بزرگ و پیچیده، به چالش کشیده می‌شود. در این مقاله، با یکی از ابزارهای جدید و کارآمد در این زمینه، یعنی esbuild باندلر در جاوااسکریپت، آشنا خواهیم شد. ما به بررسی نحوه استفاده از این ابزار قدرتمند و کارایی آن پرداخته و به شما نشان خواهیم داد که چگونه می‌توانید فرآیند بیلد پروژه‌های وب خود را بهبود بخشید.

esbuild  چیست؟

esbuild یک باندلر فوق‌سریع و با کارایی بالا برای جاوااسکریپت است. این ابزار توسط Evan Wallace توسعه داده شده و باعث تجربه بهتری در توسعه و بهینه‌سازی وبسایت‌ها و برنامه‌های وب می‌شود. با استفاده از این باندلر، می‌توانید به سرعت فایل‌های جاوااسکریپت خود را باندل کرده و بهینه کنید.این باندلر می تواند کدهای JavaScript، TypeScript، JSX و CSS را بهینه کند.

esbuild چگونه کار می کند؟

فریمورک هایی مانند Vite از esbuild استفاده کرده اند، اما شما می توانید از esbuild به عنوان یک ابزار مستقل در پروژه های خود استفاده کنید.

esbuild کد جاوا اسکریپت را به روشی مشابه باندلرهایی مانند Rollup در یک فایل واحد قرار می دهد. این تابع اصلی esbuild است و ماژول‌ها را حل می‌کند، مشکلات سینتکسی را گزارش می‌کند، «tree-shakes» را برای حذف توابع استفاده‌نشده، پاک می‌کند، عبارات ورود و اشکال‌زدایی را پاک می‌کند، کد را کوچک می‌کند و نقشه‌های منبع را ارائه می‌دهد.

esbuild کدهای CSS را در یک فایل واحد دسته بندی می کند. این یک جایگزین کامل برای پیش پردازنده‌هایی مانند Sass یا PostCSS نیست، اما esbuild می‌تواند جزئی، مسائل سینتکس، تودرتو، رمزگذاری asset های درون خطی، نقشه‌های منبع، پیشوند خودکار و کوچک‌سازی را مدیریت کند. این ممکن است تمام چیزی باشد که شما نیاز دارید.

esbuild همچنین یک سرور توسعه محلی را با بسته‌بندی خودکار و بارگذاری مجدد داغ ارائه می‌کند، بنابراین نیازی به به‌روزرسانی نیست. همه ویژگی های ارائه شده توسط Browsersync را ندارد، اما برای اکثر موارد به اندازه کافی خوب است.

در ادامه مقاله به شما در درک مفاهیم esbuild کمک می کند تا بتوانید فرصت های پیکربندی بیشتر پروژه های خود را بررسی کنید.

چرا باندل؟

بسته بندی کد در یک فایل واحد مزایای مختلفی را ارائه می دهد. در اینجا به برخی از آنها اشاره می کنیم:

  • می‌توانید فایل‌های منبع کوچک‌تر و مستقل ایجاد کنید که نگهداری آن‌ها آسان‌تر است.
  • می‌توانید کدها را در طول فرآیند بسته‌بندی review، زیباسازی، و سینتکس آن را بررسی کنید.
  • باندلر می‌تواند توابع استفاده‌نشده را حذف کند که به tree-shakes معروف است.
  • می‌توانید نسخه‌های جایگزین همان کد را بسته‌بندی کنید و اهدافی را برای مرورگرهای قدیمی‌تر، Node.js، Deno و غیره ایجاد کنید.
  • تک فایل ها سریعتر از چندین فایل بارگیری می شوند و مرورگر به پشتیبانی ماژول ES نیاز ندارد.
  • بسته‌بندی در سطح تولید می‌تواند عملکرد را با کوچک کردن کد و حذف عبارات ورود و اشکال‌زدایی بهبود بخشد.

 

چرا از esbuild استفاده کنیم؟

برخلاف باندلرهای جاوا اسکریپت، esbuild یک فایل اجرایی Go کامپایل شده است که پردازش موازی سنگین را پیاده سازی می کند. این سریع و تا صد برابر سریعتر از Rollup، Parcel یا Webpack است. این می تواند هفته ها در زمان توسعه در طول عمر یک پروژه صرفه جویی کند.

علاوه بر این، esbuild همچنین ارائه می دهد:

  • بسته‌بندی داخلی و کامپایل برای جاوا اسکریپت، TypeScript، JSX و CSS
  • APIهای پیکربندی خط فرمان، جاوا اسکریپت و Go
  • پشتیبانی از ماژول های ES و CommonJS
  • یک سرور توسعه محلی با حالت تماشا و بارگذاری مجدد زنده
  • پلاگین هایی برای افزودن قابلیت های بیشتر
  • مستندات جامع و یک ابزار آزمایش آنلاین

 

چرا از esbuild اجتناب کنید؟

در زمان نگارش، esbuild به نسخه 0.19 رسیده است. قابل اعتماد است اما هنوز یک محصول بتا است.

esbuild اغلب به روز می شود و گزینه ها ممکن است بین نسخه ها تغییر کنند. مستندات توصیه می‌کنند که از یک نسخه خاص استفاده کنید. می‌توانید آن را به‌روزرسانی کنید، اما ممکن است لازم باشد فایل‌های پیکربندی خود را منتقل کنید و در اسناد جدید جستجو کنید تا تغییرات شکسته‌کننده را کشف کنید.

همچنین توجه داشته باشید که esbuild بررسی نوع TypeScript را انجام نمی دهد، بنابراین همچنان باید tsc -noEmit را اجرا کنید.

نحوه نصب esbuild 

در صورت لزوم، یک پروژه 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 API برای بسته‌بندی یک اسکریپت ورودی (myapp.js) و همه ماژول‌های وارد شده آن در یک فایل واحد به نام bundle.js استفاده کنید. esbuild یک فایل را با استفاده از فرمت پیش‌فرض، با هدف مرورگر و بلافاصله فراخوانی تابع (IIFE) خروجی می‌دهد:

./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js

اگر از Node.js استفاده نمی کنید، می توانید esbuild را به روش های دیگری نصب کنید.

ایجاد یک پروژه با esbuild 

ابتدا vite را نصب کنید:

npm install -g create-vite

سپس برای شروع، یک پوشه جدید بسازید و به آن وارد شوید. به عنوان مثال:

create-vite my-vite-esbuild-project

cd my-esbuild-project

فایل vite.config.js باز کنید در پوشه پروژه و تنظیمات esbuild را به آن اضافه کنید:

import { defineConfig } from 'vite'
import { viteEsbuildPlugin } from 'vite-esbuild-plugin'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [viteEsbuildPlugin()],
})

برای اجرای پروژه:

npm run dev

فایل های CSS و جاوا اسکریپت را در فهرست ساخت بررسی کنید تا نسخه های کوچک شده را بدون نقشه منبع ببینید.

در زیر ما کد های پروژه Clock ساده داریم :

//main.js

import * as dom from './lib/dom.js';
import { formatHMS } from './lib/time.js';

// get clock element
const clock = dom.getAll('.clock');

if (clock.length) {

  console.log('initializing clock');

  setInterval(() => {

    clock.forEach(c => c.textContent = formatHMS());

  }, 1000);

}

و

// DOM libary

// fetch first node from selector
export function get(selector, doc = document) {
  return doc.querySelector(selector);
}

// fetch all nodes from selector
export function getAll(selector, doc = document) {
  return Array.from(doc.querySelectorAll(selector));
}

و

// time library

// return 2-digit value
function timePad(n) {
  return String(n).padStart(2, '0');
}

// return time in HH:MM format
export function formatHM(d = new Date()) {
  return timePad(d.getHours()) + ':' + timePad(d.getMinutes());
}

// return time in HH:MM:SS format
export function formatHMS(d = new Date()) {
  return formatHM(d) + ':' + timePad(d.getSeconds());
}

در فایل index.html :


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>esbuild testing</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<script type="module" src="/js/main.js"></script>
<link rel="stylesheet" href="/css/main.css" />
</head>
<body>

  <header>
    <h1>Realtime clock</h1>
  </header>

  <main>
    <time class="clock"></time>
  </main>

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

    }

  })

});
</script>
</body>
</html>

حال در فایل package.json می توانید پنج اسکریپت npm را تعریف کنید. اولی دایرکتوری build را حذف می کند:

"clean": "rm -rf ./build",

قبل از اینکه هر building اتفاق بیفتد، یک اسکریپت 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",

یک فایل esbuild.config.js فرآیند بسته‌بندی esbuild را با استفاده از JavaScript API کنترل می‌کند. مدیریت این کار راحت تر از انتقال گزینه ها به CLI API است که ممکن است سخت شود. یک اسکریپت باندل npm در init و سپس node ./esbuild.config.js اجرا می شود:

"bundle": "npm run init && node ./esbuild.config.js",

دو اسکریپت آخر npm باندل اجرا می‌شوند که یک پارامتر تولید یا توسعه به esbuild.config.js/. برای کنترل build ارسال شده است:

"build": "npm run bundle -- production",
"start": "npm run bundle -- development"

وقتی esbuild.config.js/.  اجرا می‌شود، تعیین می‌کند که آیا باید فایل‌های تولیدی کوچک (پیش‌فرض) ایجاد کند یا فایل‌های توسعه را با به‌روزرسانی‌های خودکار، نقشه‌های منبع، و یک سرور بارگذاری مجدد زنده ایجاد کند. در هر دو مورد، esbuild bundles:

ورودی فایل CSS درsrc/css/main.css به build/css/main.css
ورودی فایل جاوا اسکریپت scr/js/main.js به build/js/main.js

پیکربندی esbuild

package.json یک "type" "ماژول" دارد، بنابراین همه فایل‌های 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`);

تارگت باندل

توجه داشته باشید که متغیر target آرایه ای از مرورگرها و شماره نسخه ها را برای استفاده در پیکربندی تعریف می کند. این بر خروجی باندل تأثیر می گذارد و سینتکس را برای پشتیبانی از پلتفرم های خاص تغییر می دهد. به عنوان مثال، esbuild می تواند:

تودرتوی CSS را به انتخابگرهای کامل گسترش دهید (اگر تنها تارگت "Chrome115" باشد، تودرتو باقی می ماند)
در صورت لزوم، ویژگی های با پیشوند فروشنده CSS را اضافه کنید
پلی فیل کردن ?? عملگر nullish coalescing
# را از فیلدهای کلاس خصوصی حذف کنید


علاوه بر مرورگرها، می‌توانید نسخه‌های node و es مانند es2020 و esnext (آخرین ویژگی‌های JS و CSS) را نیز هدف قرار دهید.

باندل کردن در جاوا اسکریپت

ساده ترین API برای ایجاد یک باندل:

await esbuild.build({
  entryPoints: ['myapp.js'],
  bundle: true
  outfile: 'bundle.js'
});

این دستور CLI استفاده شده در بالا را تکرار می کند:

./node_modules/.bin/esbuild myapp.js --bundle --outfile=bundle.js

پروژه نمونه از گزینه های پیشرفته تری مانند watch فایل استفاده می کند. این به یک زمینه ساخت طولانی مدت نیاز دارد که پیکربندی را تنظیم می کند:

// 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'

});

esbuild ده ها گزینه پیکربندی را ارائه می دهد. در اینجا خلاصه ای از موارد استفاده شده در اینجا آمده است:

enterPoints آرایه ای از نقاط ورودی فایل را برای بسته بندی تعریف می کند. پروژه نمونه دارای یک اسکریپت در src/js/main.js/. است.

 

format خروجی را تنظیم می کند. مثال از esm استفاده می‌کند، اما می‌توانید به صورت اختیاری iife را برای مرورگرهای قدیمی‌تر یا commonjs را برای Node.js تنظیم کنید.

بسته نرم افزاری روی خطوط واقعی ماژول های وارد شده به فایل خروجی تنظیم می شود.

 

target آرایه ای از مرورگرهای هدف است که در بالا تعریف شده است.

 

drop آرایه ای از دستورات console و/یا debugger برای حذف است. در این حالت، ساخت‌های تولیدی هر دو را حذف می‌کنند و ساخت‌های توسعه آن‌ها را حفظ می‌کنند.

 

logLevel طولانی نویسی ورود به سیستم را تعریف می کند. مثال بالا خطاها را در طول ساخت‌های تولید و پیام‌های اطلاعاتی پرمخاطب‌تر را در طول ساخت‌های توسعه نشان می‌دهد.

 

minify با حذف نظرات و فضای خالی و تغییر نام متغیرها و توابع در صورت امکان، اندازه کد را کاهش می دهد. پروژه مثال در طول ساخت های تولیدی کوچک می شود اما در طول ساخت های توسعه کد را زیباتر می کند.

 

sourcemap که روی linked تنظیم شده است (فقط در حالت توسعه) یک نقشه منبع linkded را در یک فایل map. ایجاد می کند، بنابراین فایل منبع اصلی و خط در ابزارهای توسعه دهنده مرورگر موجود است. همچنین می‌توانید به صورت خطی تنظیم کنید تا نقشه منبع در داخل فایل باندل قرار گیرد، هر دو برای ایجاد هر دو، یا خارجی برای ایجاد یک فایل map. بدون link از جاوا اسکریپت باندل.

 

outdir دایرکتوری خروجی فایل باندل را تعریف می کند.

متد ()rebuild شیء context را فراخوانی کنید تا بیلد را یک بار اجرا کنید - معمولاً برای یک ساخت production :

await buildJS.rebuild();
buildJS.dispose(); // free up resources

برای ادامه اجرا و بازسازی خودکار زمانی که فایل‌های تماشا شده تغییر می‌کنند، متد ()watch را فراخوانی کنید:

await buildJS.watch();

شیء context تضمین می‌کند که ساخت‌های بعدی به صورت تدریجی پردازش می‌شوند و از کار ساخت‌های قبلی برای بهبود عملکرد استفاده مجدد می‌کنند.

فایل های ورودی و خروجی جاوا اسکریپت

فایل ورودی src/js/main.js ماژول های dom.js و time.js را از پوشه lib وارد می کند. همه عناصر را با یک کلاس ساعت پیدا می کند و محتوای متن آنها را در هر ثانیه روی زمان فعلی تنظیم می کند:

import * as dom from './lib/dom.js';
import { formatHMS } from './lib/time.js';

// get clock element
const clock = dom.getAll('.clock');

if (clock.length) {

  console.log('initializing clock');

  setInterval(() => {

    clock.forEach(c => c.textContent = formatHMS());

  }, 1000);

}

dom.js دو تابع export می کند. main.js هر دو را وارد می کند اما فقط از ()getAll:

// DOM libary

// fetch first node from selector
export function get(selector, doc = document) {
  return doc.querySelector(selector);
}

// fetch all nodes from selector
export function getAll(selector, doc = document) {
  return Array.from(doc.querySelectorAll(selector));
}

time.js دو تابع را export می کند. ()main.js formatHMS را وارد می کند، اما از توابع دیگر در ماژول استفاده می کند:

// time library

// return 2-digit value
function timePad(n) {
  return String(n).padStart(2, '0');
}

// return time in HH:MM format
export function formatHM(d = new Date()) {
  return timePad(d.getHours()) + ':' + timePad(d.getMinutes());
}

// return time in HH:MM:SS format
export function formatHMS(d = new Date()) {
  return formatHM(d) + ':' + timePad(d.getSeconds());
}

بسته توسعه به دست آمده ()get را از dom.js حذف می‌کند اما شامل تمام توابع time.js می‌شود. یک نقشه منبع نیز تولید می شود:

// src/js/lib/dom.js
function getAll(selector, doc = document) {
  return Array.from(doc.querySelectorAll(selector));
}

// src/js/lib/time.js
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());
}

// src/js/main.js
var clock = getAll(".clock");
if (clock.length) {
  console.log("initializing clock");
  setInterval(() => {
    clock.forEach((c) => c.textContent = formatHMS());
  }, 1e3);
}
//# sourceMappingURL=main.js.map

بسته تولیدی به دست آمده کد را به 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 Bundling

بسته‌بندی CSS در پروژه نمونه از یک شی context مشابه با جاوا اسکریپت بالا استفاده می‌کند:

// bundle CSS
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'

});

این یک گزینه خارجی را به عنوان آرایه ای از فایل ها و مسیرها برای حذف از ساخت تعریف می کند. در پروژه مثال بالا، فایل‌های موجود در دایرکتوری src/images/ در فهرست ساخت کپی می‌شوند تا HTML، CSS یا جاوا اسکریپت بتوانند مستقیماً به آنها ارجاع دهند. اگر این تنظیم نشده بود، esbuild هنگام استفاده از آنها در پس‌زمینه تصویر یا ویژگی‌های مشابه، فایل‌ها را در فهرست خروجی build/css/ کپی می‌کرد.

گزینه loader نحوه مدیریت esbuild یک فایل وارداتی را که به عنوان دارایی خارجی ارجاع نمی شود، تغییر می دهد. در این مثال:

تصاویر SVG به‌عنوان URI داده‌ها درج می‌شوند
تصاویر PNG و JPG در دایرکتوری build/css/ کپی می شوند و به عنوان فایل ارجاع می شوند


فایل های ورودی و خروجی CSS

برای مثال ورودی src/css/main.css فایل variables.css و element.css را در پوشه partials  وارد می کند:

/* import */
@import './partials/variables.css';
@import './partials/elements.css';

variables.css ویژگی های سفارشی پیش فرض را تعریف می کند:

/* primary variables */
:root {
  --font-body: sans-serif;
  --color-fore: #fff;
  --color-back: #112;
}

element.css همه استایل ها را تعریف می کند. توجه داشته باشید:

بدنه دارای یک تصویر پس زمینه است که از فهرست تصاویر خارجی بارگیری شده است
h1 در داخل هدر تو در تو قرار دارد
h1 دارای یک SVG پس زمینه است که به صورت خطی خواهد بود
مرورگرهای هدف نیازی به پیشوند فروشنده ندارند

/* element styling */
*, *::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;
}

/* nested elements with inline icon */
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 را درون خطی می‌کند و یک نقشه منبع تولید می‌کند:

/* src/css/partials/variables.css */
:root {
  --font-body: sans-serif;
  --color-fore: #fff;
  --color-back: #112;
}

/* src/css/partials/elements.css */
*,
*::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;
}

/* src/css/main.css */
/*# sourceMappingURL=main.css.map */

بسته تولید به دست آمده کد را به 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}

Watching، Rebuilding، و Serving

باقیمانده اسکریپت esbuild.config.js یکبار برای بیلدهای production قبل از خاتمه بسته می شود:

if (productionMode) {

  // single production build
  await buildCSS.rebuild();
  buildCSS.dispose();

  await buildJS.rebuild();
  buildJS.dispose();

}

در طول ساخت‌های توسعه، اسکریپت به اجرا ادامه می‌دهد، تغییرات فایل را مشاهده می‌کند و دوباره به‌طور خودکار بسته‌بندی می‌شود. زمینه buildCSS یک وب سرور توسعه با /build به عنوان دایرکتوری ریشه راه اندازی می کند:

else {

  // watch for file changes
  await buildCSS.watch();
  await buildJS.watch();

  // development server
  await buildCSS.serve({
    servedir: './build'
  });

}

ساخت توسعه را با:

npm start

برای مشاهده صفحه به localhost:8000 بروید.

برخلاف Browsersync، برای بارگذاری مجدد زنده باید کد خود را به صفحات توسعه اضافه کنید. هنگامی که تغییرات رخ می دهد، esbuild اطلاعات مربوط به به روز رسانی را از طریق یک رویداد ارسال شده توسط سرور ارسال می کند. ساده ترین گزینه این است که وقتی هر تغییری رخ می دهد صفحه را به طور کامل بارگیری کنید:

new EventSource('/esbuild').addEventListener('change', () => location.reload());

پروژه مثال از شی زمینه CSS برای ایجاد سرور استفاده می کند. دلیلش این است که ترجیح می‌دهم به‌طور دستی تغییرات جاوا اسکریپت را بازخوانی کنم - و به این دلیل که نتوانستم راهی برای 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 در حال حاضر از بارگیری مجدد جاوا اسکریپت پشتیبانی نمی کند - به هر حال من به آن اعتماد کنم!

نتیجه
با کمی پیکربندی، esbuild می تواند برای رسیدگی به تمام نیازهای ساخت و توسعه پروژه شما کافی باشد.

اگر به عملکرد پیشرفته تری نیاز دارید، مجموعه ای جامع از افزونه ها وجود دارد. توجه داشته باشید که این ابزارها اغلب شامل Sass، PostCSS یا ابزارهای ساخت مشابه هستند، بنابراین آنها به طور موثر از esbuild به عنوان یک task runner استفاده می کنند. اگر به گزینه های سفارشی و سبک وزن بیشتری نیاز دارید، همیشه می توانید افزونه های خود را ایجاد کنید.

#باندل_جاوااسکریپت#باندل#جاوااسکریپت#js#bundel
نظرات ارزشمند شما :
Loading...