ارائه کامپوننت های Svelte به عنوان اجزای وب در Angular: راهنمای گام به گام

Svelte در حال رشد است و همانطور که در نظرسنجی قبلی State of JS نشان داده شده است، در سال های گذشته به سرعت مورد توجه قرار گرفته است:
با آموزش جامع آن، ممکن است وسوسه شوید که آن را یک قدم فراتر بردارید و از Svelte در برنامه واقعی استفاده کنید.
با این حال، انتقال یک برنامه کامل به سبک Big Bang ممکن است راه آسانی برای فرو رفتن در آن نباشد. یک راه حل ممکن است ایجاد مؤلفه Svelte جداگانه و مصرف آنها به عنوان مؤلفه های وب باشد.
وقتی برای اولین بار این آموزش را خواندم، روی این جمله متوقف شدم:
می توانید کل برنامه خود را با Svelte بسازید، یا می توانید آن را به صورت تدریجی به یک پایگاه کد موجود اضافه کنید. شما همچنین می توانید قطعات را به عنوان بسته های مستقل ارسال کنید که در هر جایی کار می کنند، بدون سربار وابستگی به یک چارچوب معمولی.
بهعنوان یک توسعهدهنده آشنا با Angular، میخواستم روند ایجاد کامپوننتهای Svelte، کامپایل کردن آنها در جاوا اسکریپت خام و ترکیب آنها به عنوان عناصر بومی در یک برنامه Angular موجود را ببینم تا این فرآیند را طی کند.
در این مقاله، نحوه ادغام اجزای Svelte را در یک برنامه Angular موجود به عنوان کامپوننت های وب بررسی خواهیم کرد.
✋ توجه – Svelte 4 به تازگی منتشر شده است، اما این راهنما از Svelte 3 استفاده می کند: بسته های مورد استفاده در اینجا همچنان از Svelte 3 استفاده می کنند، بنابراین مهاجرت اکنون کمی زودرس خواهد بود.
اگر مایلید در مورد Svelte 4 اطلاعات بیشتری کسب کنید، من فقط در مورد آن وبلاگ نوشتم:
فهرست مطالب
کامپوننت های وب چیست؟
قبل از اینکه ابتدا به قابلیت همکاری Svelte و Angular بپردازیم، ابتدا ببینیم چسبی که آنها را به هم وصل می کند چیست: اجزای وب.
همانطور که توسط وب اسناد MDN بیان شده است:
Web Components مجموعهای از فنآوریهای مختلف است که به شما امکان میدهد عناصر سفارشی قابل استفاده مجدد را ایجاد کنید – با عملکرد آنها دور از بقیه کد شما – و از آنها در برنامههای وب خود استفاده کنید.
هسته اصلی این فناوری، ایده صادرات یک قطعه HTML با منطق آن، و امکان استفاده از آن در جای دیگری بدون ترس از هرگونه تداخل با کد موجود است.
اجزای وب در هسته خود سه فناوری دارند:
- 🧪 عناصر سفارشی که توانایی ایجاد عناصر HTML خودمان با رفتار، سبک و/یا الگوهای خاص خود است
- 🌑 سایه DOM که به عنوان یک DOM محلی برای کامپوننت عمل می کند و به آن امکان می دهد تمام عناصر خود را به صورت مجزا با DOM جهانی تعریف کند.
- 🧩 قالب های HTML که راهی برای تعریف و استفاده مجدد از تکه های HTML با قرار دادن آنها در DOM فراهم می کند
در زمینه ما، به این معنی است که ما می خواهیم یک کامپوننت Svelte (با قالب، سبک و منطق آن) را صادر کنیم و آن را در برنامه Angular خود رها کنیم.
عالی! اکنون کمی واضح تر می بینیم که این به کجا می رود. پس بیایید به سراغ کد برویم!
پروژه Svelte ما
قبل از صادرات هر جزء Svelte، ابتدا باید کتابخانه کامپوننت را ایجاد کنیم.
برای انجام این کار، با استفاده از SvelteKit یک پروژه کتابخانه جدید را داربست خواهیم داشت.
راه اندازی یک پروژه جدید
از آنجایی که Svelte “فقط” یک کامپایلر است، ما یک پروژه جاوا اسکریپت خام ایجاد خواهیم کرد.
در یک جدید svelte-web-components
پوشه، ایجاد یک package.json
فایل حاوی پیکربندی زیر:
{
"name": "svelte-web-components",
"version": "1.0.0",
"scripts": { },
"devDependencies": {
"svelte": "^3.59.1"
},
"type": "module"
}
ما برای رفتن آماده ایم!
ایجاد یک کامپوننت سفارشی Svelte
برای مثال، شمارندهای را صادر میکنیم که با توجه به مقدار اولیه، میتوان آن را افزایش، کاهش یا تنظیم مجدد کرد.
کد کامپوننت را به صورت جدید تعریف کنید components/Counter.svelte
فایل:
<!-- components/Counter.svelte -->
<script>
export let initialValue = 0;
let count = initialValue;
$: isInitialValue = count === initialValue;
const increment = () => (count += 1);
const decrement = () => (count -= 1);
const reset = () => (count = initialValue);
</script>
<div>
<span>{count}</span>
<button type="button" on:click={decrement}>-</button>
<button type="button" on:click={increment}>+</button>
<button type="button" on:click={reset} disabled={isInitialValue}>Reset</button>
</div>
اگر می خواهید آن را امتحان کنید، Svelte یک REPL آنلاین دارد
شما باید چیزی مشابه ببینید:
از آنجایی که ما در حال ساخت یک کتابخانه هستیم، فراموش نکنیم که آن را در API عمومی خود نمایش دهیم:
// components/index.js
export { default as Counter } from './Counter.svelte';
به منظور استفاده از قابلیت های Svelte، ما از یک فروشگاه برای مدیریت ارزش پیشخوان خود استفاده خواهیم کرد.
این در اینجا مطلقاً ضروری نیست، اما به ما این امکان را میدهد که ببینیم آیا میتوانیم از چنین ویژگیهایی در زمانی که جزء ما صادر میشود استفاده کنیم یا خیر.
نسخه به روز شده فقط کمی متفاوت است:
<!-- components/Counter.svelte -->
<script>
import { writable } from 'svelte/store';
export let initialValue = 0;
let count = writable(initialValue);
$: isInitialValue = $count === initialValue;
const increment = () => count.update((n) => (n += 1));
const decrement = () => count.update((n) => (n -= 1));
const reset = () => count.set(initialValue);
</script>
<div>
<span>{$count}</span>
<button type="button" on:click={decrement}>-</button>
<button type="button" on:click={increment}>+</button>
<button type="button" on:click={reset} disabled={isInitialValue}>Reset</button>
</div>
از آنجایی که از کامپوننت خود در جای دیگری استفاده خواهیم کرد، بیایید کمی آن را نیز سبک کنیم تا استفاده از آن لذت بخش تر باشد.
✨ CSS اضافی
<!-- components/Counter.svelte --> <style> div { display: flex; align-items: center; gap: 5px; border: 1px solid #999; width: fit-content; padding: 5px; border-radius: 5px; } div span { font-size: 18px; font-weight: bold; margin: 0 10px; } div button { padding: 5px 10px; border: 1px solid #ccc; background-color: #f0f0f0; color: #333; font-size: 16px; transition: background-color 0.3s ease; border-radius: 5px; } div button:hover { background-color: #e0e0e0; } div button:active { background-color: #ccc; } div button:disabled { opacity: 40%; } </style>
مؤلفه ما هنوز با استفاده از فروشگاه خود به خوبی کار می کند:
در واقع، آنقدر خوب کار می کند که ممکن است بخواهم از آن خارج از این کتابخانه استفاده کنم، بیایید این اتفاق بیفتد!
تبدیل کامپوننت Svelte به یک کامپوننت وب
همانطور که قبلا دیدیم، راهی برای اجرای کامپوننت ما در خارج از این محیط، تبدیل آن به یک کامپوننت وب است.
بیایید چک لیست را مرور کنیم و ببینیم که قبلاً چه چیزی را بررسی کرده ایم:
- ❌
🧪 عناصر سفارشی - ✅ 🌑 Shadow DOM
- ✅ 🧩 قالب های HTML
ما تقریبا اینجا هستیم!
برای استفاده از عنصر HTML سفارشی خود، باید یکی را برای کامپوننت خود تعریف کنیم.
برای این کار می توانیم از ویژه استفاده کنیم <svelte:options>
عنصری برای تعیین اینکه از کدام برچسب استفاده شود:
<!-- components/Counter.svelte -->
<svelte:options tag="svelte-counter" />
<!-- Counter component code here -->
ما اکنون خود را داریم Counter
مؤلفه ای که هر سه الزامات یک مؤلفه وب را برآورده می کند.
کامپایل کامپوننت Svelte به جاوا اسکریپت خالص
در حالی که جزء ما آماده صادرات است، اکنون میتوانیم این کار را با کامپایل کردن آن در جاوا اسکریپت خالص انجام دهیم.
برای این کار، از esbuild به باندل یا کامپوننت استفاده می کنیم. ما باید دو وابستگی دیگر را بگیریم: esbuild
و esbuild-svelte
:
npm i -D esbuild esbuild-svelte
سپس می توانیم یک اسکریپت اضافه کنیم که نقطه ورودی کتابخانه ما را بخواند و نتیجه JS را خروجی کند:
// esbuild-bundle.js
import esbuild from "esbuild";
import sveltePlugin from "esbuild-svelte";
esbuild
.build({
entryPoints: ["./components"],
bundle: true,
outfile: "dist/web-components.js",
plugins: [
sveltePlugin(),
],
logLevel: "info",
})
.catch(() => process.exit(1));
با این حال، ما باید به eslint بگوییم که ما در حال ساخت اجزای وب هستیم، نه اینکه برنامه خود را صرفاً بسته بندی کنیم:
esbuild
.build({
entryPoints: ["./components"],
bundle: true,
outfile: "dist/web-components.js",
plugins: [
sveltePlugin({
+ compilerOptions: {
+ customElement: true,
+ },
}),
],
logLevel: "info",
})
.catch(() => process.exit(1));
در نهایت، برای اینکه اجرای آن کمی آسانتر شود، میتوانیم یک ورودی به آن اضافه کنیم scripts
از ما package.json
:
{
"name": "svelte-web-components",
"version": "1.0.0",
"scripts": {
+ "build": "node esbuild-bundle.js"
},
"devDependencies": {
"esbuild": "^0.18.2",
"esbuild-svelte": "^0.7.3",
"svelte": "^3.59.1"
},
"type": "module"
}
اکنون می توانیم اجرا کنیم npm run build
و خروجی را ببینید:
ما باید خروجی کتابخانه خود را در زیر داشته باشیم dist/web-components.js
حاوی کامپوننت وب ما 📦
ادغام Svelte Web Components در Angular
با آماده بودن بسته ما، فقط مصرف آن باقی می ماند.
راه اندازی یک Angular Application
برای بوت استرپ اپلیکیشن Angular دستور زیر را اجرا کنید:
ng new angular-wrapper --standalone --defaults
و تولید شده را جایگزین کنید app.component.ts
با کد زیر:
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
standalone: true,
template: `
<h1>Svelte in Angular!</h1>
`,
})
export class AppComponent {}
اکنون که برنامه Angular ما آماده است و کامپوننت وب Svelte ما نیز آماده است، بیایید این را سیم کشی کنیم!
مصرف کامپوننت های وب Svelte در Angular
برای اینکه Angular از بسته JS خارجی خود آگاه شود، باید آن را به عنوان وابستگی پروژه خود اضافه کنیم.
برای آن، از قبل تولید شده را بگیرید web-components.js
فایل و آن را در یک پوشه جدید در ریشه پروژه Angular خود، در زیر رها کنید src/scripts
:
و ارجاع به آن در angular.json
فایل در scripts
آرایه واقع در angular.json > projects > angular-wrapper > architect > build > options > scripts
:
"styles": [
"src/styles.css"
],
"scripts": [
+ "src/scripts/web-components.js"
]
Angular با همراه کردن کامپوننت وب خود در کنار برنامه خود، اکنون می توانیم از شمارنده خود استفاده کنیم!
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
standalone: true,
template: `
<h1>Svelte in Angular!</h1>
+ <svelte-counter />
`,
})
export class AppComponent {}
… یا می توانیم؟
در تلاشی برای جلوگیری از انجام اشتباهات، Angular عناصر HTML مورد استفاده ما را اسکن می کند و می بیند که آیا آنها یک عنصر HTML بومی هستند یا یک جزء Angular قابل حل.
با این حال، در مورد ما، این هیچ کدام نیست.
امیدواریم که Angular راه حلی برای موارد استفاده ما ارائه دهد:
اگر «svelte-counter» یک مؤلفه وب است، «CUSTOM_ELEMENTS_SCHEMA» را به «Component.schemas@» این مؤلفه اضافه کنید تا این پیام سرکوب شود.
+ import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
@Component({
selector: "app-root",
standalone: true,
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<h1>Svelte in Angular!</h1>
<svelte-counter />
`,
})
export class AppComponent {}
اکنون می توانید Svelte Web Component را در حال اجرا در برنامه Angular ما مشاهده کنید!
غذای آماده
در این مقاله دیدیم که Web Components چیست، چگونه یک کامپوننت Svelte را به یک Web Component تبدیل کنیم و چگونه آن را از یک برنامه Angular مصرف کنیم.
این فرآیند به لطف بستههای جامعه و ماهیت خود Svelte بسیار ساده است: کامپایلر بودن، ایجاد تکههایی از JS که میتوانند در هر جایی اجرا شوند، در ماهیت خودش است.
اگر می خواهید کد به دست آمده را بررسی کنید، می توانید به مخزن GitHub مرتبط بروید
امیدوارم در آنجا چیز مفیدی یاد بگیرید!

عکس از Didssph در Unsplash