اگلے (یا کسی بھی SSR فریم ورک) کے ساتھ ویب اجزاء کا استعمال

میرے میں پچھلے پیغام ہم نے شولیس کو دیکھا، جو کہ ایک جزو لائبریری ہے جس میں UX اجزاء کا ایک مکمل مجموعہ ہے جو خوبصورت، قابل رسائی، اور — شاید غیر متوقع طور پر — کے ساتھ بنایا گیا ہے۔ ویب اجزاء. اس کا مطلب ہے کہ وہ کسی بھی جاوا اسکرپٹ کے فریم ورک کے ساتھ استعمال کیے جا سکتے ہیں۔ جبکہ React کی ویب کمپوننٹ انٹرآپریبلٹی فی الحال مثالی سے کم ہے، وہاں حل ہیں.

لیکن ویب اجزاء کی ایک سنگین کمی سرور سائیڈ رینڈرنگ (SSR) کے لیے ان کی حمایت کی موجودہ کمی ہے۔ ڈیکلریٹو شیڈو DOM (DSD) نامی کوئی چیز کام میں ہے، لیکن اس کے لیے موجودہ سپورٹ بہت کم ہے، اور یہ درحقیقت DSD کے لیے خصوصی مارک اپ کو خارج کرنے کے لیے آپ کے ویب سرور سے خریداری کی ضرورت ہے۔ اس کے لیے فی الحال کام ہو رہا ہے۔ Next.js جسے میں دیکھنے کا منتظر ہوں۔ لیکن اس پوسٹ کے لیے، ہم دیکھیں گے کہ کسی بھی SSR فریم ورک، جیسے Next.js سے ویب اجزاء کو کیسے منظم کیا جائے، آج.

ہم دستی کام کی ایک غیر معمولی رقم کو ختم کر دیں گے، اور تھوڑا سا اس عمل میں ہمارے صفحہ کی شروعاتی کارکردگی کو نقصان پہنچانا۔ پھر ہم دیکھیں گے کہ کارکردگی کے ان اخراجات کو کیسے کم کیا جائے۔ لیکن کوئی غلطی نہ کریں: یہ حل تجارت کے بغیر نہیں ہے، لہذا دوسری صورت میں توقع نہ کریں۔ ہمیشہ پیمائش اور پروفائل.

مسئلہ

اس سے پہلے کہ ہم اس میں غوطہ لگائیں، آئیے ایک لمحہ نکالیں اور درحقیقت مسئلہ کی وضاحت کریں۔ سرور سائڈ رینڈرنگ کے ساتھ ویب اجزاء کیوں کام نہیں کرتے؟

Next.js جیسے ایپلیکیشن فریم ورک React کوڈ لیتے ہیں اور اسے API کے ذریعے بنیادی طور پر "stringify" کرنے کے لیے چلاتے ہیں، یعنی یہ آپ کے اجزاء کو سادہ HTML میں بدل دیتا ہے۔ لہذا React جزو کا درخت ویب ایپ کی میزبانی کرنے والے سرور پر پیش کرے گا، اور وہ HTML باقی ویب ایپ کے HTML دستاویز کے ساتھ آپ کے صارف کے براؤزر پر بھیج دیا جائے گا۔ اس کے ساتھ کچھ HTML بھی ہیں۔ وہ ٹیگز جو React کو لوڈ کرتے ہیں، آپ کے تمام React اجزاء کے کوڈ کے ساتھ۔ جب کوئی براؤزر ان پر کارروائی کرتا ہے۔ tags، React جزو کے درخت کو دوبارہ رینڈر کرے گا، اور چیزوں کو SSR'd HTML کے ساتھ ملایا جائے گا جو نیچے بھیجا گیا تھا۔ اس مقام پر، تمام اثرات چلنا شروع ہو جائیں گے، ایونٹ کے ہینڈلرز وائر اپ ہو جائیں گے، اور ریاست درحقیقت... ریاست پر مشتمل ہو گی۔ اس وقت ویب ایپ بن جاتی ہے۔ انٹرایکٹو. کلائنٹ پر آپ کے جزو کے درخت کو دوبارہ پروسیس کرنے، اور ہر چیز کو تار لگانے کے عمل کو کہا جاتا ہے۔ نمی.

تو، اس کا ویب اجزاء سے کیا تعلق ہے؟ ٹھیک ہے، جب آپ کچھ پیش کرتے ہیں، تو وہی جوتا بولیں۔ جزو جس کا ہم نے دورہ کیا۔ آخری بار:


   General 
   Custom 
   Advanced 
   Disabled 

  This is the general tab panel.
  This is the custom tab panel.
  This is the advanced tab panel.
  This is a disabled tab panel.

… رد عمل کا اظہار کریں (یا ایمانداری سے کوئی بھی JavaScript فریم ورک) ان ٹیگز کو دیکھیں گے اور انہیں آسانی سے پاس کریں گے۔ React (یا Svelte، یا Solid) ان ٹیگز کو اچھی طرح سے فارمیٹ شدہ ٹیبز میں تبدیل کرنے کے لیے ذمہ دار نہیں ہیں۔ اس کے لیے کوڈ آپ کے پاس جو بھی کوڈ ہے اس کے اندر ٹک جاتا ہے جو ان ویب اجزاء کی وضاحت کرتا ہے۔ ہمارے معاملے میں، وہ کوڈ Shoelace لائبریری میں ہے، لیکن کوڈ کہیں بھی ہو سکتا ہے۔ اہم بات یہ ہے۔ جب کوڈ چلتا ہے۔.

عام طور پر، ان ویب اجزاء کو رجسٹر کرنے والے کوڈ کو جاوا اسکرپٹ کے ذریعے آپ کی ایپلیکیشن کے عام کوڈ میں کھینچ لیا جائے گا۔ import. اس کا مطلب یہ ہے کہ یہ کوڈ آپ کے جاوا اسکرپٹ بنڈل میں ختم ہو جائے گا اور ہائیڈریشن کے دوران عمل میں آ جائے گا جس کا مطلب ہے کہ، آپ کے صارف کے درمیان SSR'd HTML اور ہائیڈریشن ہو رہا ہے، یہ ٹیبز (یا اس معاملے کے لیے کوئی بھی ویب اجزاء) صحیح مواد کو پیش نہیں کریں گے۔ . پھر، جب ہائیڈریشن ہوتا ہے، تو مناسب مواد ظاہر ہوتا ہے، جس کی وجہ سے ممکنہ طور پر ان ویب اجزاء کے ارد گرد کا مواد گھوم جاتا ہے اور مناسب طریقے سے فارمیٹ شدہ مواد کو فٹ کر دیتا ہے۔ یہ ایک کے طور پر جانا جاتا ہے غیر اسٹائل شدہ مواد کا فلیش، یا FOUC۔ نظریہ میں، آپ ان سب کے درمیان مارک اپ لگا سکتے ہیں۔ تیار شدہ آؤٹ پٹ سے ملنے کے لیے ٹیگز، لیکن عملی طور پر یہ سب کچھ ناممکن ہے، خاص طور پر تیسری پارٹی کے جزو کی لائبریری جیسے Shoelace کے لیے۔

ہمارے ویب اجزاء کے رجسٹریشن کوڈ کو منتقل کرنا

تو مسئلہ یہ ہے کہ ویب اجزاء بنانے کا کوڈ وہ کام کرتا ہے جو انہیں کرنے کی ضرورت ہوتی ہے وہ اس وقت تک نہیں چلے گا جب تک کہ ہائیڈریشن نہ ہو۔ اس پوسٹ کے لیے، ہم اس کوڈ کو جلد چلانے پر غور کریں گے۔ فوری طور پر، حقیقت میں. ہم اپنی مرضی کے مطابق اپنے ویب اجزاء کے کوڈ کو بنڈل کرنے، اور دستی طور پر ایک اسکرپٹ کو براہ راست اپنے دستاویز میں شامل کرنے کو دیکھیں گے۔ لہذا یہ فوری طور پر چلتا ہے، اور باقی دستاویز کو اس وقت تک روکتا ہے جب تک کہ ایسا نہ ہو۔ یہ عام طور پر کرنا ایک خوفناک چیز ہے۔ سرور سائیڈ رینڈرنگ کا پورا نقطہ ہے۔ نوٹ ہمارے صفحے کو اس وقت تک پروسیسنگ سے روکیں جب تک کہ ہماری جاوا اسکرپٹ پر کارروائی نہ ہو جائے۔ لیکن ایک بار ہو جانے کے بعد، اس کا مطلب یہ ہے کہ، جیسا کہ دستاویز ابتدائی طور پر سرور سے ہمارے HTML کو پیش کر رہی ہے، ویب اجزاء رجسٹرڈ ہو جائیں گے اور فوری طور پر اور ہم وقتی طور پر صحیح مواد کا اخراج کریں گے۔

ہمارے معاملے میں، ہم ہیں صرف ہمارے ویب اجزاء کے رجسٹریشن کوڈ کو بلاکنگ اسکرپٹ میں چلانا چاہتے ہیں۔ یہ کوڈ بہت بڑا نہیں ہے، اور ہم بعد میں آنے والے دوروں میں مدد کے لیے کچھ کیش ہیڈرز شامل کرکے کارکردگی کو نمایاں طور پر کم کرنے کی کوشش کریں گے۔ یہ کامل حل نہیں ہے۔ پہلی بار جب کوئی صارف آپ کے صفحہ کو براؤز کرتا ہے تو وہ اسکرپٹ فائل لوڈ ہونے کے دوران ہمیشہ بلاک ہوجائے گا۔ بعد کے دورے اچھی طرح سے کیش کریں گے، لیکن یہ تجارت شاید نہیں آپ کے لیے قابل عمل ہو — ای کامرس، کوئی؟ بہر حال، پروفائل، پیمائش، اور اپنی ایپ کے لیے صحیح فیصلہ کریں۔ اس کے علاوہ، مستقبل میں یہ مکمل طور پر ممکن ہے Next.js مکمل طور پر DSD اور ویب اجزاء کو سپورٹ کرے گا۔

شروع

ہم جس کوڈ کو دیکھیں گے وہ سب اس میں ہے۔ یہ GitHub ریپو اور Vercel کے ساتھ یہاں تعینات. ویب ایپ متن کے ساتھ جوتے کے کچھ اجزاء پیش کرتی ہے جو ہائیڈریشن کے بعد رنگ اور مواد کو تبدیل کرتی ہے۔ آپ کو متن کی تبدیلی کو "ہائیڈریٹڈ" میں دیکھنے کے قابل ہونا چاہئے جس میں جوتے کے اجزاء پہلے سے ہی مناسب طریقے سے پیش کر رہے ہیں۔

حسب ضرورت بنڈلنگ ویب اجزاء کوڈ

ہمارا پہلا قدم ایک واحد JavaScript ماڈیول بنانا ہے جو ہماری ویب اجزاء کی تمام تعریفیں درآمد کرتا ہے۔ جوتے کے اجزاء کے لیے جو میں استعمال کر رہا ہوں، میرا کوڈ اس طرح لگتا ہے:

import { setDefaultAnimation } from "@shoelace-style/shoelace/dist/utilities/animation-registry";

import "@shoelace-style/shoelace/dist/components/tab/tab.js";
import "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js";
import "@shoelace-style/shoelace/dist/components/tab-group/tab-group.js";

import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";

setDefaultAnimation("dialog.show", {
  keyframes: [
    { opacity: 0, transform: "translate3d(0px, -20px, 0px)" },
    { opacity: 1, transform: "translate3d(0px, 0px, 0px)" },
  ],
  options: { duration: 250, easing: "cubic-bezier(0.785, 0.135, 0.150, 0.860)" },
});
setDefaultAnimation("dialog.hide", {
  keyframes: [
    { opacity: 1, transform: "translate3d(0px, 0px, 0px)" },
    { opacity: 0, transform: "translate3d(0px, 20px, 0px)" },
  ],
  options: { duration: 250, easing: "cubic-bezier(0.785, 0.135, 0.150, 0.860)" },
});

یہ کے لیے تعریفیں لوڈ کرتا ہے۔ اور اجزاء، اور ڈائیلاگ کے لیے کچھ ڈیفالٹ متحرک تصاویر کو اوور رائیڈ کرتا ہے۔ کافی سادہ۔ لیکن یہاں دلچسپ بات یہ ہے کہ اس کوڈ کو ہماری درخواست میں شامل کیا جائے۔ ہم نہیں کر سکتے ہیں صرف import یہ ماڈیول. اگر ہم نے ایسا کیا، تو یہ ہمارے عام جاوا اسکرپٹ بنڈلز میں بنڈل ہو جائے گا اور ہائیڈریشن کے دوران چلتا ہے۔ یہ اس FOUC کا سبب بنے گا جس سے ہم بچنے کی کوشش کر رہے ہیں۔

جبکہ Next.js کے پاس اپنی مرضی کے بنڈل چیزوں کے لیے متعدد ویب پیک ہکس ہیں، میں استعمال کروں گا۔ وائٹ اس کے بجائے سب سے پہلے، اس کے ساتھ انسٹال کریں npm i vite اور پھر ایک بنائیں vite.config.js فائل میرا اس طرح لگتا ہے:

import { defineConfig } from "vite";
import path from "path";

export default defineConfig({
  build: {
    outDir: path.join(__dirname, "./shoelace-dir"),
    lib: {
      name: "shoelace",
      entry: "./src/shoelace-bundle.js",
      formats: ["umd"],
      fileName: () => "shoelace-bundle.js",
    },
    rollupOptions: {
      output: {
        entryFileNames: `[name]-[hash].js`,
      },
    },
  },
});

یہ میں ہماری ویب اجزاء کی تعریفوں کے ساتھ ایک بنڈل فائل بنائے گا۔ shoelace-dir فولڈر آئیے اسے پر منتقل کریں۔ public فولڈر تاکہ Next.js اس کی خدمت کرے۔ اور ہمیں فائل کے عین نام کا بھی پتہ لگانا چاہیے، اس کے آخر میں ہیش کے ساتھ۔ یہاں ایک نوڈ اسکرپٹ ہے جو فائل کو منتقل کرتا ہے اور جاوا اسکرپٹ ماڈیول لکھتا ہے جو بنڈل فائل کے نام کے ساتھ ایک سادہ مستقل برآمد کرتا ہے (یہ جلد ہی کام آئے گا):

const fs = require("fs");
const path = require("path");

const shoelaceOutputPath = path.join(process.cwd(), "shoelace-dir");
const publicShoelacePath = path.join(process.cwd(), "public", "shoelace");

const files = fs.readdirSync(shoelaceOutputPath);

const shoelaceBundleFile = files.find(name => /^shoelace-bundle/.test(name));

fs.rmSync(publicShoelacePath, { force: true, recursive: true });

fs.mkdirSync(publicShoelacePath, { recursive: true });
fs.renameSync(path.join(shoelaceOutputPath, shoelaceBundleFile), path.join(publicShoelacePath, shoelaceBundleFile));
fs.rmSync(shoelaceOutputPath, { force: true, recursive: true });

fs.writeFileSync(path.join(process.cwd(), "util", "shoelace-bundle-info.js"), `export const shoelacePath = "/shoelace/${shoelaceBundleFile}";`);

یہاں ایک ساتھی npm اسکرپٹ ہے:

"bundle-shoelace": "vite build && node util/process-shoelace-bundle",

یہ کام کرنا چاہئے. میرے لئے، util/shoelace-bundle-info.js اب موجود ہے، اور اس طرح لگتا ہے:

export const shoelacePath = "/shoelace/shoelace-bundle-a6f19317.js";

اسکرپٹ لوڈ ہو رہا ہے۔

آئیے Next.js میں چلتے ہیں۔ _document.js فائل کریں اور ہماری ویب اجزاء بنڈل فائل کا نام کھینچیں:

import { shoelacePath } from "../util/shoelace-bundle-info";

پھر ہم دستی طور پر ایک رینڈر کرتے ہیں۔ میں ٹیگ کریں . یہاں میرا پورا کیا ہے _document.js فائل کی طرح لگتا ہے:

import { Html, Head, Main, NextScript } from "next/document";
import { shoelacePath } from "../util/shoelace-bundle-info";

export default function Document() {
  return (
    
      
        
      
      
        
); }

اور یہ کام کرنا چاہئے! ہماری جوتے کی رجسٹریشن ایک بلاکنگ اسکرپٹ میں لوڈ ہو جائے گی اور ہمارے صفحہ کے ابتدائی HTML پر کارروائی کرتے وقت فوری طور پر دستیاب ہو گی۔

کارکردگی کو بہتر بنانا

ہم چیزوں کو ویسے ہی چھوڑ سکتے ہیں جیسے وہ ہیں لیکن آئیے اپنے جوتے کے بنڈل کے لیے کیشنگ شامل کریں۔ ہم Next.js کو اپنی Next.js کنفگ فائل میں درج ذیل اندراج کو شامل کرکے ان Shoelace بنڈلوں کو کیش ایبل بنانے کے لیے کہیں گے:

async headers() {
  return [
    {
      source: "/shoelace/shoelace-bundle-:hash.js",
      headers: [
        {
          key: "Cache-Control",
          value: "public,max-age=31536000,immutable",
        },
      ],
    },
  ];
}

اب، ہماری سائٹ کے بعد کے براؤزز پر، ہم شولیس بنڈل کو اچھی طرح سے کیش کرتے ہوئے دیکھتے ہیں!

DevTools Sources پینل کھلتا ہے اور بھری ہوئی Shoelace بنڈل دکھا رہا ہے۔
اگلے (یا کسی بھی SSR فریم ورک) کے ساتھ ویب اجزاء کا استعمال

اگر ہمارا جوتے کا بنڈل کبھی تبدیل ہوتا ہے، تو فائل کا نام بدل جائے گا (بذریعہ :hash مندرجہ بالا سورس پراپرٹی سے حصہ)، براؤزر کو پتہ چلے گا کہ اس کے پاس وہ فائل کیش نہیں ہے، اور وہ اسے نیٹ ورک سے تازہ کرنے کی درخواست کرے گا۔

اپ ریپنگ

یہ بہت دستی کام کی طرح لگ رہا ہو سکتا ہے; اور یہ تھا. یہ بدقسمتی کی بات ہے کہ ویب اجزاء سرور سائیڈ رینڈرنگ کے لیے بہتر آؤٹ آف دی باکس سپورٹ پیش نہیں کرتے ہیں۔

لیکن ہمیں ان کے فراہم کردہ فوائد کو فراموش نہیں کرنا چاہئے: معیاری UX اجزاء استعمال کرنے کے قابل ہونا اچھا ہے جو کسی مخصوص فریم ورک سے منسلک نہیں ہیں۔ بالکل نئے فریم ورک کے ساتھ تجربہ کرنے کے قابل ہونا بہت اچھا ہے، جیسے ٹھوس، کسی قسم کے ٹیب، موڈل، خودکار تکمیل، یا کسی بھی جزو کو تلاش کرنے (یا ایک ساتھ ہیک) کرنے کی ضرورت کے بغیر۔

ٹائم اسٹیمپ:

سے زیادہ سی ایس ایس ٹیکنیکس