নেক্সট (বা যেকোনো SSR ফ্রেমওয়ার্ক) এর সাথে ওয়েব কম্পোনেন্ট ব্যবহার করা

আমার মধ্যে পূর্ববর্তী পোস্ট আমরা শোলেসের দিকে তাকালাম, যেটি একটি কম্পোনেন্ট লাইব্রেরি যেখানে UX উপাদানগুলির একটি সম্পূর্ণ স্যুট যা সুন্দর, অ্যাক্সেসযোগ্য এবং - সম্ভবত অপ্রত্যাশিতভাবে - দিয়ে তৈরি ওয়েব কম্পোনেন্টস. এর মানে এগুলি যেকোন জাভাস্ক্রিপ্ট ফ্রেমওয়ার্কের সাথে ব্যবহার করা যেতে পারে। যদিও রিঅ্যাক্টের ওয়েব কম্পোনেন্ট ইন্টারঅপারেবিলিটি বর্তমানে আদর্শের চেয়ে কম, সমাধান আছে.

কিন্তু ওয়েব কম্পোনেন্টগুলির একটি গুরুতর ত্রুটি হল সার্ভার-সাইড রেন্ডারিং (SSR) এর জন্য তাদের সমর্থনের অভাব। ডিক্লারেটিভ শ্যাডো ডিওএম (ডিএসডি) নামে কিছু কাজ চলছে, তবে এটির জন্য বর্তমান সমর্থন খুবই কম, এবং এটি আসলে ডিএসডি-র জন্য বিশেষ মার্কআপ নির্গত করতে আপনার ওয়েব সার্ভার থেকে কেনা-ইন করতে হবে। এর জন্য বর্তমানে কাজ চলছে পরবর্তী.js যে আমি দেখার জন্য উন্মুখ. কিন্তু এই পোস্টের জন্য, আমরা দেখব কিভাবে যেকোনো SSR ফ্রেমওয়ার্ক থেকে Web Components পরিচালনা করা যায়, যেমন Next.js, আজ.

আমরা ম্যানুয়াল কাজ একটি অ তুচ্ছ পরিমাণ করা শেষ করব, এবং সামান্য প্রক্রিয়ায় আমাদের পৃষ্ঠার স্টার্টআপ কর্মক্ষমতা ক্ষতিকারক. তারপরে আমরা দেখব কিভাবে এই পারফরম্যান্স খরচ কমানো যায়। কিন্তু কোন ভুল করবেন না: এই সমাধানটি ট্রেডঅফ ছাড়া নয়, তাই অন্যথায় আশা করবেন না। সর্বদা পরিমাপ এবং প্রোফাইল.

সমস্যাটি

আমরা ডুব দেওয়ার আগে, আসুন একটু সময় নিয়ে আসলে সমস্যাটি ব্যাখ্যা করি। কেন ওয়েব উপাদান সার্ভার-সাইড রেন্ডারিংয়ের সাথে ভাল কাজ করে না?

Next.js-এর মতো অ্যাপ্লিকেশন ফ্রেমওয়ার্ক রিঅ্যাক্ট কোড নেয় এবং একটি API এর মাধ্যমে এটিকে মূলত "স্ট্রিংফাই" করতে চালায়, যার অর্থ এটি আপনার উপাদানগুলিকে প্লেইন HTML-এ পরিণত করে। তাই রিঅ্যাক্ট কম্পোনেন্ট ট্রি ওয়েব অ্যাপ হোস্ট করা সার্ভারে রেন্ডার করবে এবং সেই HTMLটি ওয়েব অ্যাপের বাকি HTML ডকুমেন্টের সাথে আপনার ব্যবহারকারীর ব্রাউজারে পাঠানো হবে। এই এইচটিএমএল এর সাথে কিছু আছে যে ট্যাগগুলি প্রতিক্রিয়া লোড করে, আপনার সমস্ত প্রতিক্রিয়া উপাদানগুলির কোড সহ। যখন একটি ব্রাউজার এগুলো প্রক্রিয়া করে ট্যাগ, প্রতিক্রিয়া কম্পোনেন্ট ট্রিকে পুনরায় রেন্ডার করবে এবং পাঠানো 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 ফ্রেমওয়ার্ক) সেই ট্যাগগুলি দেখতে পাবে এবং সহজভাবে তাদের পাস করবে। এই ট্যাগগুলিকে সুন্দরভাবে ফরম্যাট করা ট্যাবে পরিণত করার জন্য প্রতিক্রিয়া (বা Svelte বা সলিড) দায়ী নয়। এর জন্য কোডটি আপনার কাছে যেকোন কোডের ভিতরে আটকে দেওয়া হয় যা সেই ওয়েব উপাদানগুলিকে সংজ্ঞায়িত করে। আমাদের ক্ষেত্রে, সেই কোডটি শোলেস লাইব্রেরিতে রয়েছে, কিন্তু কোডটি যেকোনো জায়গায় হতে পারে। যা গুরুত্বপূর্ণ তা হল যখন কোড চলে.

সাধারনত, এই ওয়েব কম্পোনেন্ট রেজিস্টার করা কোড জাভাস্ক্রিপ্টের মাধ্যমে আপনার অ্যাপ্লিকেশানের সাধারণ কোডে টেনে আনা হবে import. তার মানে এই কোডটি আপনার জাভাস্ক্রিপ্ট বান্ডেলে চলে যাবে এবং হাইড্রেশনের সময় এক্সিকিউট হবে যার মানে হল যে, আপনার ব্যবহারকারীর মধ্যে SSR'd HTML এবং হাইড্রেশন হচ্ছে, এই ট্যাবগুলি (অথবা সেই বিষয়ে কোনো ওয়েব কম্পোনেন্ট) সঠিক কন্টেন্ট রেন্ডার করবে না। . তারপর, যখন হাইড্রেশন হয়, তখন সঠিক বিষয়বস্তু প্রদর্শিত হবে, সম্ভবত এই ওয়েব কম্পোনেন্টগুলির আশেপাশের বিষয়বস্তু ঘুরে দাঁড়াতে পারে এবং সঠিকভাবে ফর্ম্যাট করা বিষয়বস্তুর সাথে মানানসই হয়৷ এটি একটি হিসাবে পরিচিত স্টাইল না করা বিষয়বস্তুর ফ্ল্যাশ, বা FOUC. তাত্ত্বিকভাবে, আপনি সেগুলির মধ্যে মার্কআপ আটকে রাখতে পারেন সমাপ্ত আউটপুট মেলে ট্যাগ, কিন্তু এই সব কিন্তু বাস্তবে অসম্ভব, বিশেষ করে Shoelace মত একটি তৃতীয় পক্ষের উপাদান লাইব্রেরির জন্য.

আমাদের ওয়েব কম্পোনেন্ট রেজিস্ট্রেশন কোড সরানো হচ্ছে

তাই সমস্যা হল যে ওয়েব কম্পোনেন্ট তৈরি করার কোডটি তাদের যা করতে হবে তা আসলে হাইড্রেশন না হওয়া পর্যন্ত চলবে না। এই পোস্টের জন্য, আমরা শীঘ্রই সেই কোডটি চালানোর দিকে নজর দেব; অবিলম্বে, আসলে। আমরা কাস্টম আমাদের ওয়েব কম্পোনেন্ট কোড বান্ডলিং এবং ম্যানুয়ালি সরাসরি আমাদের নথিতে একটি স্ক্রিপ্ট যোগ করার দিকে নজর দেব। তাই এটি অবিলম্বে চলে, এবং এটি না হওয়া পর্যন্ত নথির বাকি অংশটিকে ব্লক করে। এটি সাধারণত একটি ভয়ঙ্কর জিনিস। সার্ভার-সাইড রেন্ডারিং এর পুরো পয়েন্ট হল না আমাদের জাভাস্ক্রিপ্ট প্রক্রিয়া না হওয়া পর্যন্ত আমাদের পৃষ্ঠা প্রক্রিয়াকরণ থেকে ব্লক করুন। কিন্তু একবার হয়ে গেলে, এর অর্থ হল, যেহেতু ডকুমেন্টটি প্রাথমিকভাবে সার্ভার থেকে আমাদের HTML রেন্ডার করছে, ওয়েব উপাদানগুলি নিবন্ধিত হবে এবং উভয়ই অবিলম্বে এবং সিঙ্ক্রোনাসভাবে সঠিক বিষয়বস্তু নির্গত করবে৷

আমাদের ক্ষেত্রে, আমরা করছি মাত্র একটি ব্লকিং স্ক্রিপ্টে আমাদের ওয়েব কম্পোনেন্ট রেজিস্ট্রেশন কোড চালাতে চাই। এই কোডটি বিশাল নয়, এবং আমরা পরবর্তী ভিজিটগুলিতে সাহায্য করার জন্য কিছু ক্যাশে শিরোনাম যোগ করে পারফরম্যান্স হিটকে উল্লেখযোগ্যভাবে কমাতে দেখব। এটি একটি নিখুঁত সমাধান নয়। স্ক্রিপ্ট ফাইলটি লোড হওয়ার সময় প্রথমবার একজন ব্যবহারকারী আপনার পৃষ্ঠা ব্রাউজ করার সময় সর্বদা ব্লক করবে। পরবর্তী ভিজিট সুন্দরভাবে ক্যাশে হবে, কিন্তু এই ট্রেডঅফ হতে পারে না আপনার জন্য সম্ভব হবে — ই-কমার্স, কেউ? যাইহোক, প্রোফাইল, পরিমাপ করুন এবং আপনার অ্যাপের জন্য সঠিক সিদ্ধান্ত নিন। এছাড়াও, ভবিষ্যতে এটি সম্পূর্ণরূপে সম্ভব Next.js সম্পূর্ণরূপে DSD এবং ওয়েব উপাদানগুলিকে সমর্থন করবে৷

শুরু হচ্ছে

আমরা যে কোডটি দেখব তা সবই রয়েছে এই GitHub রেপো এবং Vercel এর সাথে এখানে মোতায়েন করা হয়েছে. ওয়েব অ্যাপটি টেক্সটের সাথে কিছু জুতোর উপাদান রেন্ডার করে যা হাইড্রেশনের পরে রঙ এবং বিষয়বস্তু পরিবর্তন করে। আপনি টেক্সট পরিবর্তন দেখতে সক্ষম হওয়া উচিত “হাইড্রেটেড”, জুতার উপাদান ইতিমধ্যে সঠিকভাবে রেন্ডার করা হয়েছে।

কাস্টম বান্ডলিং ওয়েব কম্পোনেন্ট কোড

আমাদের প্রথম ধাপ হল একটি একক জাভাস্ক্রিপ্ট মডিউল তৈরি করা যা আমাদের সমস্ত ওয়েব কম্পোনেন্ট সংজ্ঞা আমদানি করে। আমি যে জুতোর উপাদানগুলি ব্যবহার করছি তার জন্য, আমার কোডটি এইরকম দেখাচ্ছে:

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 কে বলব:

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

এখন, আমাদের সাইটের পরবর্তী ব্রাউজগুলিতে, আমরা দেখতে পাচ্ছি শোলেস বান্ডিলটি সুন্দরভাবে ক্যাশ করছে!

DevTools সোর্স প্যানেল খুলছে এবং লোড করা জুতোর বান্ডিল দেখাচ্ছে৷
নেক্সট (বা যেকোনো SSR ফ্রেমওয়ার্ক) এর সাথে ওয়েব কম্পোনেন্ট ব্যবহার করা

যদি আমাদের জুতার বান্ডিল কখনও পরিবর্তিত হয়, ফাইলের নাম পরিবর্তন হবে (এর মাধ্যমে :hash উপরের সোর্স প্রপার্টি থেকে অংশ), ব্রাউজার দেখতে পাবে যে এটিতে সেই ফাইলটি ক্যাশ করা নেই এবং এটি নেটওয়ার্ক থেকে তাজা করার অনুরোধ করবে।

মোড়ক উম্মচন

এটা অনেকটা ম্যানুয়ালি কাজ বলে মনে হতে পারে; এবং এটা ছিল. এটা দুর্ভাগ্যজনক যে ওয়েব কম্পোনেন্ট সার্ভার-সাইড রেন্ডারিংয়ের জন্য আরও ভাল আউট-অফ-দ্য-বক্স সমর্থন অফার করে না।

তবে তারা যে সুবিধাগুলি প্রদান করে তা আমাদের ভুলে যাওয়া উচিত নয়: একটি নির্দিষ্ট কাঠামোর সাথে আবদ্ধ নয় এমন মানসম্পন্ন UX উপাদানগুলি ব্যবহার করতে সক্ষম হওয়া ভাল। একদম নতুন ফ্রেমওয়ার্কের সাথে পরীক্ষা করতে পারাটা ভালো লাগছে, যেমন কঠিন, কোন ধরণের ট্যাব, মডেল, স্বয়ংসম্পূর্ণ, বা যে কোনও উপাদান খুঁজে (বা একসাথে হ্যাক) করার প্রয়োজন ছাড়াই।

সময় স্ট্যাম্প:

থেকে আরো সিএসএস কৌশল