زیادہ تر فرنٹ اینڈ انجینئرز مائیکرو سروسز کا انتخاب نہیں کرتے ہیں۔ وہ اس کے وارث ہیں۔ ایک دن آپ ایک API سے ڈیٹا نکال رہے ہیں، اگلے دن آپ پانچ سروسز کے جوابات کو اکٹھا کر رہے ہیں، ہر ایک کا اپنا معاہدہ، اس کے اپنے ناکامی کے طریقوں، اور اس کا اپنا خیال ہے کہ "صارف” کیسا لگتا ہے۔
بیک اینڈ ٹیمیں پابند سیاق و سباق، حتمی مستقل مزاجی، اور سروس میش کے بارے میں بات کرتی ہیں۔ میں لوڈنگ کے حالات، باسی ڈیٹا، سست انوینٹری سروسز اور میرا چیک آؤٹ صفحہ کیوں کریش ہو رہا ہے کے بارے میں سوچ رہا ہوں۔
یہ مضمون مائیکرو سروسز ماحول میں کام کرنے والے فرنٹ اینڈ انجینئرز کے لیے ہے۔ آپ یہ سیکھیں گے کہ پیچیدگیاں پیدا کیے بغیر متعدد سروس APIs کا استعمال کیسے کیا جائے، اپنے UI میں جزوی ناکامیوں کو خوبصورتی سے کیسے ہینڈل کیا جائے، تمام سروسز میں تقسیم شدہ حالت کا انتظام کیسے کیا جائے، اور API معاہدوں پر بیک اینڈ ٹیموں کے ساتھ مؤثر طریقے سے کیسے کام کیا جائے۔ کیونکہ آدھی جنگ مواصلات کی ہے، کوڈ نہیں۔.
مقصد آپ کو بیک اینڈ انجینئر بنانا نہیں ہے، بلکہ آپ کو ایسے ذہنی ماڈل اور نمونے دینا ہے جو مائیکرو سروسز کی دنیا میں فرنٹ اینڈ ڈیولپمنٹ کو کم تکلیف دہ بناتے ہیں۔
شرطیں
اس مضمون سے زیادہ سے زیادہ فائدہ اٹھانے کے لیے، آپ کو یہ جاننے کی ضرورت ہے:
-
رد عمل یا اس سے ملتا جلتا جزو فریم ورک (مثال کے طور پر React اور TypeScript کا استعمال)
-
REST API اور HTTP کی بنیادی تفہیم
-
فرنٹ اینڈ ایپلی کیشنز سے ڈیٹا حاصل کرنے کا تجربہ کریں (فچ، ایکسیوس، یا ری ایکٹ سوال)۔
-
مائیکرو سروسز کیا ہیں کے بارے میں عمومی آگاہی (ایک بنانے کی ضرورت نہیں)
انڈیکس
فرنٹ اینڈ مائیکرو سروس کے مسائل
یک سنگی فن تعمیر میں، فرنٹ اینڈ ایک API کے ساتھ بات چیت کرتا ہے۔ وہ API ڈیٹا بیس کا مالک ہے، کاروباری منطق کو ہینڈل کرتا ہے، اور ڈیٹا کو بالکل اسی شکل میں واپس کرتا ہے جس کی UI کے لیے ضروری ہے۔ زندگی سادہ ہے۔
مائیکرو سروسز فن تعمیر میں، ایک API کو متعدد میں تقسیم کیا جاتا ہے۔
Monolith:
Browser → API → Database
Microservices:
Browser → API Gateway → User Service
→ Order Service
→ Inventory Service
→ Payment Service
→ Notification Service
ان خدمات میں سے ہر ایک مختلف ٹیم کی ملکیت ہے، جو آزادانہ طور پر تعینات ہے، اور مختلف ڈیٹا فارمیٹس یا قواعد استعمال کر سکتی ہے۔ ایک فرنٹ اینڈ انجینئر کے طور پر، اب آپ کو کچھ نئے چیلنجز کا سامنا ہے۔
-
متعدد معاہدے: ہر سروس کی اپنی API کی شکل ہوتی ہے۔ انوینٹری سروس میں "پروڈکٹ” کے کیٹلاگ سروس میں "پروڈکٹ” سے مختلف فیلڈز ہوتے ہیں۔
-
جزوی ناکامی: آرڈرنگ سروس 50ms کے اندر جواب دے سکتی ہے جبکہ ریفرل سروس کا وقت ختم ہو جاتا ہے۔ UI کو دونوں کو ہینڈل کرنا چاہیے۔
-
ڈیٹا کی مطابقت: آرڈرنگ سروس اب بھی پرانا پتہ دکھاتی ہے کیونکہ صارف نے ایڈریس کو اپ ڈیٹ کیا ہے لیکن اسے ابھی تک ہم آہنگ نہیں کیا گیا ہے۔
-
تاخیر میں اضافہ: ایک صفحہ بنانے کے لیے ایک کے بجائے تین یا چار API کالز کی ضرورت پڑ سکتی ہے۔
یہ پس منظر کا مسئلہ نہیں ہے جو فرنٹ اینڈ کو متاثر کرتا ہے۔ یہ بنیادی طور پر ایک فرنٹ اینڈ مسئلہ ہے جس کے لیے فرنٹ اینڈ حل کی ضرورت ہے۔
پیٹرن 1: بیک اینڈ فار فرنٹ اینڈ (BFF)
مائیکرو سروسز کی دنیا میں، فرنٹ اینڈ ٹیموں کے لیے سب سے زیادہ بااثر پیٹرن فرنٹ اینڈ کے لیے بیک اینڈ ہے۔ BFF براؤزر اور مائیکرو سروسز کے درمیان ایک پتلی API پرت ہے۔ یہ فرنٹ اینڈ ٹیم کی ملکیت ہے اور فرنٹ اینڈ کی مخصوص ضروریات کو پورا کرنے کے لیے موجود ہے۔
Without BFF:
Browser → User Service (call 1)
Browser → Order Service (call 2)
Browser → Inventory Service (call 3)
3 round trips, 3 contracts to manage
With BFF:
Browser → BFF → User Service
→ Order Service
→ Inventory Service
1 round trip, 1 contract to manage
BFF کالوں کو اکٹھا کرتا ہے، جوابات کو جزو کے لیے درکار فارم میں تبدیل کرتا ہے، اور کراس سروس کے مسائل کو ہینڈل کرتا ہے جیسے کہ تصدیقی ٹوکن پاس کرنا۔
// BFF endpoint: GET /api/order-summary/:orderId
// Aggregates data from three services into one frontend-friendly response
import express from "express";
const router = express.Router();
router.get("/api/order-summary/:orderId", async (req, res) => {
const { orderId } = req.params;
const token = req.headers.authorization;
try {
const [order, customer, shipment] = await Promise.allSettled([
fetch(`\({ORDER_SERVICE}/orders/\){orderId}`, {
headers: { Authorization: token },
}).then((r) => r.json()),
fetch(`\({USER_SERVICE}/users/\){req.userId}`, { // userId set by auth middleware
headers: { Authorization: token },
}).then((r) => r.json()),
fetch(`\({SHIPPING_SERVICE}/shipments?orderId=\){orderId}`, {
headers: { Authorization: token },
}).then((r) => r.json()),
]);
res.json({
order: order.status === "fulfilled" ? order.value : null,
customer: customer.status === "fulfilled" ? customer.value : null,
shipment: shipment.status === "fulfilled" ? shipment.value : null,
errors: [order, customer, shipment]
.filter((r) => r.status === "rejected")
.map((r) => r.reason.message),
});
} catch (error) {
res.status(500).json({ error: "Failed to assemble order summary" });
}
});
کے استعمال پر توجہ دیں۔ Promise.allSettled اس کے بجائے Promise.all. یہ مائیکرو سروسز ماحول میں بہت اہم ہے۔ Promise.all تیزی سے ناکام: اگر ایک سروس بند ہوجاتی ہے، تو پوری درخواست ناکام ہوجاتی ہے۔ Promise.allSettled آپ جزوی ڈیٹا واپس کر سکتے ہیں جو براہ راست درج ذیل پیٹرن کی طرف جاتا ہے:
اپنا BFF کب استعمال کریں۔
BFF سرمایہ کاری کے قابل ہے اگر:
-
فرنٹ اینڈ فی صفحہ تین یا زیادہ سروسز سے ڈیٹا اکٹھا کرتا ہے۔
-
مختلف کلائنٹس (ویب، موبائل، ایڈمن) کو ایک ہی سروس سے ڈیٹا کی مختلف شکلوں کی ضرورت ہوتی ہے۔
-
آپ چاہتے ہیں کہ آپ کی فرنٹ اینڈ ٹیم یہ کنٹرول کرے کہ آپ کی بیک اینڈ ٹیم کا انتظار کرنے کے بجائے ردعمل کیسا لگتا ہے۔
آپ کو BFF کی ضرورت نہیں ہے اگر:
-
پہلے سے ہی API گیٹ ویز موجود ہیں جو جمع کو ہینڈل کرتے ہیں (جیسے Apollo Federation for GraphQL)۔
-
صرف ایک یا دو خدمات استعمال کریں۔
-
بیک اینڈ ٹیم پہلے سے ہی فرنٹ اینڈ کے لیے بہترین اینڈ پوائنٹس فراہم کر رہی ہے۔
پیٹرن 2: UI میں جزوی خرابی کو سنبھالنا
یک سنگی میں، درخواستیں کامیاب ہوجاتی ہیں یا ناکام ہوجاتی ہیں۔ مائیکرو سروسز کی دنیا میں، جزوی کامیابی حاصل کی جا سکتی ہے۔ آرڈر کا ڈیٹا ٹھیک لوڈ ہوتا ہے، لیکن سفارشی سروس بند ہے۔ پروڈکٹ کی تفصیلات چیک کی جا سکتی ہیں، لیکن جائزہ لینے کی سروس سست ہے۔
UI کو اسے احسن طریقے سے ہینڈل کرنا چاہیے۔ بنیادی اصول: غیر اہم سروس کی غلطیوں کو صارف کے اہم بہاؤ میں خلل نہ آنے دیں۔
// Types for partial data loading
interface ServiceResult {
data: T | null;
status: "loaded" | "error" | "loading";
error?: string;
}
interface OrderPageData {
order: ServiceResult;
recommendations: ServiceResult;
reviews: ServiceResult;
}
دستیاب ڈیٹا کی بنیاد پر آزادانہ طور پر رینڈر کرنے کے لیے اجزاء بنائیں۔
function OrderPage({ orderId }: { orderId: string }) {
const { order, recommendations, reviews } = useOrderPageData(orderId);
// Critical: order must load or the page makes no sense
if (order.status === "loading") return ;
if (order.status === "error") return ;
return (
{/* Critical section: always rendered */}
{/* Non-critical: degrades gracefully */}
{recommendations.status === "loaded" ? (
) : recommendations.status === "error" ? (
) : (
)}
{/* Non-critical: degrades gracefully */}
{reviews.status === "loaded" ? (
) : reviews.status === "error" ? (
) : (
)}
);
}
اہم اور غیر حساس ڈیٹا کی درجہ بندی
صفحہ پر موجود تمام ڈیٹا اتنا ہی اہم نہیں ہے۔ متعدد خدمات سے حاصل ہونے والے صفحات بنانے سے پہلے، ہر ڈیٹا سورس کی درجہ بندی کریں۔
| ڈیٹا کا ذریعہ | تنقیدی | ناکامی کی حکمت عملی |
|---|---|---|
| آرڈر کی تفصیلات | ہاں | غلطی کا صفحہ دکھائیں، مکمل منظر کو مسدود کریں۔ |
| کسٹمر کی معلومات | ہاں | غلطی کا صفحہ دکھائیں۔ |
| سفارش | نہیں | حصوں کو چھپائیں، خالی حالت دکھائیں۔ |
| جائزہ لیں | نہیں | ‘جائزہ دستیاب نہیں’ پیغام دکھایا گیا ہے۔ |
| حال ہی میں دیکھا گیا۔ | نہیں | خاموشی سے چھپ جاؤ |
یہ درجہ بندی پروڈکٹ ٹیم کی طرف سے کیا جانے والا شعوری فیصلہ ہونا چاہیے، نہ کہ کوئی ایسی چیز جو آپ کو دریافت ہوتی ہے جب کوئی سروس پیداوار سے باہر ہو جاتی ہے۔
پیٹرن 3: تقسیم شدہ ریاستی انتظام
یک سنگی دنیا میں، سرور معلومات کا واحد ذریعہ ہے۔ مائیکرو سروسز کی دنیا میں، سچائی تقسیم کی جاتی ہے۔ صارف کی خدمت صارف کا موجودہ پتہ جانتی ہے۔ آرڈرنگ سروس کے پاس آپ کے آرڈر کے وقت آپ کے پتے کا سنیپ شاٹ ہوتا ہے۔ ہو سکتا ہے وہ میچ نہ کریں۔
پرانے ڈیٹا اور کیشے کی حدود
اگر آپ کا فرنٹ اینڈ متعدد سروسز سے ڈیٹا کیش کرتا ہے، تو آپ کو کیشے کی حدود کے بارے میں سوچنے کی ضرورت ہے۔ مختلف خدمات کی عمروں سے مختلف نرخوں پر ڈیٹا۔
// Configure cache times based on how frequently the underlying data changes
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 30_000, // Default: 30 seconds
},
},
});
// Product catalog: changes infrequently
function useProduct(productId: string) {
return useQuery({
queryKey: ["product", productId],
queryFn: () => fetchProduct(productId),
staleTime: 5 * 60_000, // 5 minutes: catalog updates are rare
});
}
// Inventory levels: changes constantly
function useStockLevel(productId: string) {
return useQuery({
queryKey: ["stock", productId],
queryFn: () => fetchStockLevel(productId),
staleTime: 10_000, // 10 seconds: stock changes with every purchase
refetchInterval: 30_000, // Poll every 30 seconds on active pages
});
}
// User's own order: should reflect latest state
function useOrder(orderId: string) {
return useQuery({
queryKey: ["order", orderId],
queryFn: () => fetchOrder(orderId),
staleTime: 0, // Always refetch: user expects to see their latest action
});
}
غلطی یہ ہے کہ تمام کیشڈ ڈیٹا کو یکساں برتا جائے۔ کیٹلاگ سروس میں پروڈکٹ کی معلومات کو کئی منٹ تک محفوظ کیا جا سکتا ہے۔ انوینٹری خدمات میں انوینٹری کی سطح کو زیادہ کثرت سے تازہ کرنے کی ضرورت ہے۔ آپ کا اپنا آرڈر ڈیٹا ہمیشہ اپ ٹو ڈیٹ ہونا چاہیے کیونکہ آپ نے ابھی کام کیا ہے اور نتائج کی توقع ہے۔
کراس سروس کی غلط کاری
تقسیم شدہ ریاست کا سب سے مشکل حصہ یہ جاننا ہے کہ کب باطل کرنا ہے۔ جب کوئی صارف آرڈر دیتا ہے، تو اسے چاہیے کہ:
-
باطل آرڈر کی فہرست (آرڈر سروس)
-
انوینٹری کی سطحوں کو باطل کریں (انوینٹری سروس)
-
صارف کے وفاداری پوائنٹس (صارف کی خدمات) کو باطل کریں۔
// After a successful order placement, invalidate across service boundaries
async function placeOrder(cart: Cart): Promise {
const order = await api.post("/api/orders", { items: cart.items });
// Invalidate data from multiple services that this action affected
queryClient.invalidateQueries({ queryKey: ["orders"] });
queryClient.invalidateQueries({ queryKey: ["stock"] });
queryClient.invalidateQueries({ queryKey: ["loyalty-points"] });
// Optimistically update the cart (owned by the frontend)
queryClient.setQueryData(["cart"], { items: [] });
return order;
}
یہ دستی اور غلطی کا شکار ہے۔ یہ یاد رکھنا ضروری ہے کہ جب بھی کوئی نئی سروس اسپیل ایونٹ میں دلچسپی رکھتی ہے، تو اسے اس میں ایک غلط کاری شامل کرنے کی ضرورت ہوتی ہے۔
زیادہ مضبوط متبادل کے لیے، آپ سرور سے بھیجے گئے ایونٹس یا ویب ساکٹ کنکشن کا استعمال کر سکتے ہیں تاکہ فرنٹ اینڈ پر بیک اینڈ پش انیلیڈیشن سگنلز ہوں، یا آپ کلائنٹ سائیڈ اسٹیٹ لیئر کے اندر شائع/سبسکرائب پیٹرن کو اپنا سکتے ہیں جہاں کیشے کیز ڈومین ایونٹس کو سبسکرائب کرتی ہیں۔
یہ نقطہ نظر اس مضمون کے دائرہ کار سے باہر ہے، لیکن اگر آپ کی باطل کرنے والی جدول 12 اندراجات سے زیادہ ہے تو یہ تلاش کرنے کے قابل ہو سکتی ہے۔
اس دوران، جدولوں میں ان انٹر-سروس انحصار کو دستاویز کرنا آپ کی مدد کرتا ہے:
| صارف کی کارروائی | خدمات متاثر | غلط کرنے کے لیے کیشے کی کلید |
|---|---|---|
| آرڈر دیں۔ | آرڈرز، انوینٹری، صارفین | orders، stock، loyalty-points، cart |
| ایڈریس اپ ڈیٹ | صارف، شپنگ | user-profile، shipping-estimates |
| ایک جائزہ لکھیں۔ | جائزے، مصنوعات | reviews، product (گریڈ کی تبدیلی) |
پیٹرن 4: ایک سے زیادہ API معاہدوں پر قابو پانا
مائیکرو سروسز کی دنیا میں، ہر سروس اپنے API معاہدے کی وضاحت کرتی ہے۔ صارف کی خدمت واپس آ گئی ہے۔ firstName اور lastName. آرڈر سروس واپس آ گئی ہے۔ customerName ایک تار کے طور پر۔ نوٹیفکیشن سروس کی توقع ہے: fullName. ایک ہی تصور، تین مختلف فیلڈ کے نام۔
اڈاپٹر پرت
ایک اڈاپٹر پرت بنائیں جو ہر سروس کے جواب کو ایک مستقل ڈومین ماڈل میں ترجمہ کرے جسے آپ کے اجزاء استعمال کرتے ہیں۔
// Domain models: what the frontend actually works with
interface User {
id: string;
fullName: string;
email: string;
address: Address;
}
// Adapter for the User Service
function adaptUserServiceResponse(raw: UserServiceResponse): User {
return {
id: raw.userId,
fullName: `\({raw.firstName} \){raw.lastName}`,
email: raw.emailAddress,
address: {
line1: raw.address.street,
city: raw.address.city,
postcode: raw.address.zipCode,
country: raw.address.countryCode,
},
};
}
// Adapter for the Order Service (which embeds a different user shape)
function adaptOrderCustomer(raw: OrderServiceCustomer): User {
return {
id: raw.customerId,
fullName: raw.customerName,
email: raw.email,
address: {
line1: raw.shippingAddress.addressLine1,
city: raw.shippingAddress.city,
postcode: raw.shippingAddress.postalCode,
country: raw.shippingAddress.country,
},
};
}
آپ کا جزو ہے User زمرہ وہ کبھی بھی خام خدمت کا جواب نہیں دیکھتے ہیں۔ جب کوئی سروس اپنا API تبدیل کرتی ہے تو، صارف نام کو ظاہر کرنے والے تمام اجزاء کے بجائے ایک اڈاپٹر اپ ڈیٹ ہوتا ہے۔
اڈاپٹر پرت کہاں رکھنا ہے۔
اگر آپ کے پاس BFF ہے تو اڈاپٹر موجود ہے۔ براؤزر خام سروس کا جواب نہیں دیکھ سکتا۔ اگر آپ سروس کو براہ راست فرنٹ اینڈ سے کال کرتے ہیں، تو ڈیٹا فیچ لیئر میں HTTP کال اور کیش کے درمیان ایک اڈاپٹر رکھیں۔
// The adapter runs before data enters the cache
function useUser(userId: string) {
return useQuery({
queryKey: ["user", userId],
queryFn: async () => {
const raw = await fetch(`/api/users/${userId}`).then((r) => r.json());
return adaptUserServiceResponse(raw);
},
});
}
پیٹرن 5: صفحہ اسمبلی کے لیے بجٹ سے زیادہ وقت
اگر آپ کا صفحہ متعدد خدمات پر انحصار کرتا ہے، تو آپ کو ٹائم آؤٹ حکمت عملی کی ضرورت ہوگی۔ اس کے بغیر، صفحہ لوڈ ہونے کا وقت سست ترین سروس سے طے ہوتا ہے، اور مائیکرو سروسز کی دنیا میں ہمیشہ سست خدمات ہوں گی۔
ٹائم آؤٹ بجٹ صفحہ کے لیے درکار تمام ڈیٹا اکٹھا کرنے کے لیے زیادہ سے زیادہ وقت مختص کرتا ہے۔ اگر غیر اہم خدمات آپ کے بجٹ کے اندر جواب نہیں دیتی ہیں، تو انہیں ان کے بغیر پیش کریں۔
درحقیقت، یہ افادیت مشترکہ خدمات کی پرت پر رہتی ہے، جیسے lib/api.ts) یہاں ایک نفاذ ہے جو ہر صفحے کی اسمبلی منطق میں ان لائن نہیں ہے:
// lib/api.ts: shared timeout utility
async function fetchWithTimeout(
url: string,
options: RequestInit,
timeoutMs: number
): Promise {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
...options,
signal: controller.signal,
});
return response.json();
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") {
console.warn(`Request to \({url} timed out after \){timeoutMs}ms`);
}
return null;
} finally {
clearTimeout(timeout);
}
}
// Page assembly with tiered timeouts
async function assembleProductPage(productId: string): Promise {
// Critical data: longer timeout, page fails without it
const product = await fetchWithTimeout(
`/api/products/${productId}`,
{},
3000 // 3 second budget for critical data
);
if (!product) {
throw new Error("Product not found");
}
// Non-critical data: shorter timeout, page renders without it
const [reviews, recommendations, relatedProducts] = await Promise.all([
fetchWithTimeout(
`/api/reviews?productId=${productId}`,
{},
1500 // 1.5 second budget
),
fetchWithTimeout(
`/api/recommendations?productId=${productId}`,
{},
1000 // 1 second budget: nice to have
),
fetchWithTimeout(
`/api/products/${productId}/related`,
{},
1000
),
]);
return {
product,
reviews: reviews ?? [],
recommendations: recommendations ?? [],
relatedProducts: relatedProducts ?? [],
};
}
ہمارے مختلف بجٹ چیک کریں۔ اہم ڈیٹا (خود پروڈکٹ) کو 3 سیکنڈ ملتے ہیں۔ غیر اہم ڈیٹا (جائزے، سفارشات) کو 1-1.5 سیکنڈ ملتا ہے۔ اگر سفارشات سست ہیں، تو ہم سفارشات کے بغیر پروڈکٹس دکھائیں گے۔ صارفین ان خدمات کا انتظار نہیں کرتے جو انہوں نے نہیں دیکھی ہیں۔
پیٹرن 6: فی سروس خرابی کی حدود
ردعمل کی غلطی کی حدیں خاص طور پر مائیکرو سروس فرنٹ اینڈز میں طاقتور ہوتی ہیں۔ صفحہ کی سطح پر ایک غلطی کی حد کے بجائے، ان حصوں کے ارد گرد حدود لگائیں جو مختلف بیک اینڈ سروسز کا نقشہ بناتے ہیں۔
اگر آپ نے پہلے کبھی غلطی کی حدود کا استعمال نہیں کیا ہے تو، یہاں ایک کم سے کم عمل درآمد ہے: خامی کی حدود لازمی طور پر طبقاتی اجزاء ہونی چاہئیں، اور React ابھی تک ان کو فنکشن اجزاء کے طور پر سپورٹ نہیں کرتا ہے (مزید تفصیلات کے لیے React دستاویزات دیکھیں)۔
class ErrorBoundary extends React.Component<
{ fallback: React.ReactNode; children: React.ReactNode },
{ hasError: boolean } > {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.error("ErrorBoundary caught:", error, info);
}
render() {
if (this.state.hasError) return this.props.fallback;
return this.props.children;
}
}
یہ انفرادی خدمت کے حصوں کی حدود کو محدود کرتا ہے۔
function ProductPage({ productId }: { productId: string }) {
return (
{/* If the product service fails, show a full-page error */}
}>
}>
{/* If the review service fails, just hide reviews */}
}>
}>
{/* If recommendations fail, hide silently */}
}>
);
}
ہر باؤنڈری اپنے ڈیٹا سورس سے آزادانہ طور پر غلطیوں کو پکڑتی ہے۔ جائزہ سروس بند ہونے پر پروڈکٹ کی تفصیلات متاثر نہیں ہوں گی۔ ریفرل سروس کا ٹائم آؤٹ بالکل بھی کوئی غلطی نہیں دکھاتا ہے۔ سیکشن صرف رینڈر نہیں کرتا ہے۔
یہ نقشہ براہ راست تنقیدی/غیر تنقیدی درجہ بندی پر ہے۔ اہم خدمات ظاہر کردہ غلطی UI کے ذریعے غلطی کی حدود حاصل کرتی ہیں۔ غیر اہم خدمات خود بخود انحطاط پذیر ہو جاتی ہیں یا ایک باؤنڈری حاصل کرتی ہیں جو کم سے کم خالی حالت کو ظاہر کرتی ہے۔
معاہدوں پر بیک اینڈ ٹیم کے ساتھ تعاون کریں۔
مندرجہ بالا تکنیک پیٹرن علامات کو حل کرتا ہے. مائیکرو سروسز ماحول میں زیادہ تر فرنٹ اینڈ مسائل کی بنیادی وجہ API معاہدوں کے بارے میں فرنٹ اینڈ اور بیک اینڈ ٹیموں کے درمیان ناقص مواصلت ہے۔
معاہدے کی بات چیت جلد کریں۔
1. فرنٹ اینڈ اصل میں کون سے فیلڈز استعمال کرتا ہے؟
بیک اینڈ سروسز اکثر ڈیٹا کے پورے ماڈل کو بے نقاب کرتی ہیں۔ فرنٹ اینڈ تین فیلڈز کا استعمال کرتا ہے: اگر آپ کی بیک اینڈ ٹیم جانتی ہے کہ آپ کن فیلڈز پر انحصار کرتے ہیں، تو وہ ان فیلڈز کو زیادہ احتیاط سے برقرار رکھ سکتے ہیں اور ان فیلڈز کو استعمال کرنے سے گریز کر سکتے ہیں جنہیں اب کوئی استعمال نہیں کر رہا ہے۔
2. اس اختتامی نقطہ کے لیے متوقع تاخیر کا بجٹ کیا ہے؟
اگر آپ کے پروڈکٹ پیج کا مجموعی بجٹ 2 سیکنڈ ہے اور آپ کی نمایاں سروس کا اوسط سروس ٹائم 1.8 سیکنڈ ہے، تو آپ کو کوئی بھی فرنٹ اینڈ کوڈ لکھنے سے پہلے ایک مسئلہ درپیش ہے۔ اسے جلد سطح پر بنائیں۔
3. اگر یہ سروس کم ہو جائے تو کیا ہوگا؟
ہر بیک اینڈ ٹیم سے درج ذیل سوالات پوچھیں: "اگر میری سروس ایک گھنٹے میں 500 غلطیوں کے ساتھ جواب دیتی ہے تو مجھے فرنٹ اینڈ پر کیا ڈسپلے کرنا چاہیے؟” یہ سوال اکثر یہ ظاہر کرتا ہے کہ اس کے بارے میں کبھی کسی نے سوچا ہی نہیں، اسی لیے آپ کو پوچھنا چاہیے۔
4. آپ بڑی تبدیلیوں کو کیسے بتاتے ہیں؟
میں عمل سے متفق ہوں۔ کسی بھی چیز کا انتخاب کریں – پل کی درخواستوں میں اوپن اے پی آئی کی تفصیلات میں فرق، API تبدیلیوں کے لیے سلیک چینلز، ورژن والے اختتامی پوائنٹس – اور انہیں ایک ساتھ رکھیں۔
مشترکہ نمونے کے بطور API معاہدے
پش مشین پڑھنے کے قابل معاہدے۔ OpenAPI تفصیلات، GraphQL اسکیما، یا پروٹوکول بفر ڈیفینیشن فرنٹ اینڈ اور بیک اینڈ ٹیموں کے درمیان معلومات کے مشترکہ ذریعہ کے طور پر کام کرتی ہے۔ یہ آپ کو اجازت دیتا ہے:
-
خودکار قسم کی نسل: اوزار جیسے
openapi-typescriptOpenAPI تفصیلات سے TypeScript کی قسمیں بنائیں۔ اگر بیک اینڈ کسی فیلڈ کو تبدیل کرتا ہے، تو غیر پیداواری تعمیر فوری طور پر ناکام ہو جائے گی۔ -
معاہدے کی جانچ: اوزار جیسے
Pactفرنٹ اینڈ کے نقطہ نظر سے، آپ متوقع درخواست/جواب کے جوڑوں کی وضاحت کر سکتے ہیں۔ بیک اینڈ ان ٹیسٹوں کو CI پائپ لائن میں چلاتا ہے۔ اگر کوئی تبدیلی فرنٹ اینڈ کی توقعات کو توڑ دیتی ہے تو پائپ لائن ناکام ہوجاتی ہے۔ -
فرضی سرور: چشموں سے تیار کردہ موکس آپ کو پسدید کے تیار ہونے سے پہلے فرنٹ اینڈ بنانے کی اجازت دیتا ہے۔ جب اصل سروس شروع کی جاتی ہے، کوڈ پہلے ہی کام کر رہا ہوتا ہے۔
// Generated types from OpenAPI spec, always in sync with the backend
import type { components } from "./generated/inventory-api";
type Product = components["schemas"]["Product"];
type StockLevel = components["schemas"]["StockLevel"];
// If the backend renames "available" to "inStock",
// this code fails at compile time, not in production
function formatStockMessage(stock: StockLevel): string {
if (stock.available > 10) return "In Stock";
if (stock.available > 0) return `Only ${stock.available} left`;
return "Out of Stock";
}
متعدد خدمات کے لیے جانچ
کنٹریکٹ ٹیسٹنگ بیک اینڈ پر بریکنگ تبدیلیاں پکڑتی ہے، لیکن آپ کو فرنٹ اینڈ کے رویے کی بھی جانچ کرنی چاہیے جب سروس غیر متوقع طریقوں سے جواب دیتی ہے۔ موک سروس ورکر (MSW) آپ کو اپنے ٹیسٹ کے ماحول میں سروس کے مخصوص موک ہینڈلرز کو اسپن کرنے کی اجازت دیتا ہے۔
import { setupServer } from "msw/node";
import { http, HttpResponse } from "msw";
// Mock each service independently
const server = setupServer(
http.get("/api/products/:id", () =>
HttpResponse.json({ productId: "abc-123", name: "Widget", price: 49.99 })
),
http.get("/api/reviews", () =>
HttpResponse.json([{ rating: 5, body: "Great product" }])
)
);
// Test: what happens when the review service is down?
test("renders product page when reviews service fails", async () => {
server.use(
http.get("/api/reviews", () => HttpResponse.error())
);
render( );
expect(await screen.findByText("Widget")).toBeInTheDocument();
expect(await screen.findByText("Reviews unavailable")).toBeInTheDocument();
});
یہ ہمیں اپنے ٹیسٹ سویٹ میں پیٹرن 2 کے جزوی ناکامی کے منظر نامے کی نقل کرنے کی اجازت دیتا ہے۔ خام سروس رسپانس سہولیات کے خلاف یونٹ ٹیسٹ کے ساتھ اڈاپٹر پرت (پیٹرن 4) کی جانچ کریں، اور انضمام ٹیسٹوں کے لیے MSW استعمال کریں تاکہ یہ یقینی بنایا جا سکے کہ جب انفرادی خدمات سست، نیچے، یا غیر متوقع شکلیں واپس آتی ہیں تو پورا صفحہ درست طریقے سے جمع ہوتا ہے۔
کب پیچھے دھکیلنا ہے۔
ہر مائیکرو سروس کے مسئلے کا فرنٹ اینڈ حل نہیں ہوتا ہے۔ کبھی کبھی صحیح جواب فن تعمیر کو پیچھے چھوڑنا ہے۔
اگر فرنٹ اینڈ ایک صفحے کے لیے 5 سے زیادہ API کال کرتا ہے تو پش بیک۔ یہ اس بات کی علامت ہے کہ سروس بہت زیادہ دانے دار ہے یا اس میں مجموعی پرت غائب ہے۔ حل BFF یا جامع API ہے۔ Promise.all براؤزر سے کال کی گئی۔
جب دو سروسز ایک ہی ہستی کے لیے متضاد ڈیٹا واپس کرتی ہیں، تو وہ پیچھے ہٹ جاتی ہیں۔ اگر آپ کی صارف سروس کہتی ہے کہ صارف نام "جین” ہے اور آپ کی آرڈر سروس کہتی ہے "جینٹ”، تو یہ ڈیٹا کی مستقل مزاجی کا مسئلہ ہے جسے فرنٹ اینڈ حل نہیں کر سکتا۔ ترمیمات ماخذ پر کی جانی چاہئیں، یا تو خدمات کے درمیان واقعہ پر مبنی ہم آہنگی کے ذریعے، یا اس فیلڈ کے لیے ایک سروس کو مستند ذریعہ کے طور پر ترتیب دے کر۔
جب آپ کی بیک اینڈ ٹیم بغیر کسی وارننگ کے اہم تبدیلیاں کرتی ہے تو پیچھے ہٹیں۔ اگر کوئی سروس کسی پروڈکشن ایپ کو توڑ دیتی ہے کیونکہ یہ ایک معمولی ورژن کے ٹکرانے پر فیلڈ کا نام تبدیل کرتی ہے، تو یہ عمل کی ناکامی ہے۔ ایڈووکیٹ ورژن والے APIs، فرسودگی کی اطلاعات، اور معاہدہ کی جانچ۔
آپ صرف ایک API صارف نہیں ہیں۔ اس API کو کس طرح ڈیزائن کیا گیا ہے اس میں آپ اسٹیک ہولڈر ہیں۔ جتنی جلدی آپ API ڈیزائن گفتگو میں مشغول ہوں گے، پیداوار میں آپ کو اتنے ہی کم مسائل سے نمٹنا پڑے گا۔
نتیجہ
اس مضمون میں پیٹرن ایک منظم نقطہ آغاز فراہم کرتے ہیں، لیکن بنیادی اصول تمام نمونوں میں یکساں ہیں۔
جھلکیاں:
-
مجموعی پرت کا مالک ہے۔ BFF فرنٹ اینڈ ٹیموں کو جوابات کی شکل کو کنٹرول کرنے اور براؤزر کی بجائے سرور کی سطح پر جزوی غلطیوں کو سنبھالنے کی اجازت دیتا ہے۔
-
تمام ڈیٹا ذرائع کو اہم یا غیر اہم کے طور پر درجہ بندی کریں۔ یہ واحد فیصلہ ہر صفحہ پر ہر حصے کے لیے غلطی سے نمٹنے، ٹائم آؤٹ بجٹ، اور لوڈ کرنے کی حکمت عملی کا تعین کرتا ہے۔
-
حدود کو معمول بنائیں: خام سروس کے جوابات اور اجزاء کے درمیان ایک اڈاپٹر پرت آپ کو اپ اسٹریم API تبدیلیوں سے بچاتی ہے اور ایک مستقل ڈومین ماڈل فراہم کرتی ہے۔
-
معاہدوں میں سرمایہ کاری کریں: مشین سے پڑھنے کے قابل API معاہدے، تیار کردہ اقسام، اور معاہدے کے ٹیسٹ تعمیراتی وقت پر بریکنگ تبدیلیاں پکڑتے ہیں، نہ کہ پیداوار۔
-
ضرورت پڑنے پر پیچھے دھکیلیں: ہر مائیکرو سروس کے مسئلے کا فرنٹ اینڈ حل نہیں ہوتا ہے۔ اگر آپ کا فن تعمیر UI پرت پر غیر معقول بوجھ ڈالتا ہے، تو جلد بولیں۔
مائیکرو سروسز بیک اینڈ آرکیٹیکچرل فیصلہ ہیں، لیکن اس کے نتائج فرنٹ اینڈ پر سب سے زیادہ شدت سے محسوس کیے جاتے ہیں۔ اس مضمون میں نمونوں کا استعمال پیچیدگی کو ختم نہیں کرتا ہے، لیکن یہ اسے منظم کرنے کا ایک منظم طریقہ فراہم کرتا ہے۔