ব্রাউজার প্রিলোড স্ক্যানারকে উপেক্ষা করবেন না

ব্রাউজার প্রিলোড স্ক্যানার কী, এটি কীভাবে পারফর্ম্যান্স উন্নত করতে সাহায্য করে এবং আপনি কীভাবে এর থেকে দূরে থাকতে পারেন তা জানুন।

পৃষ্ঠা লোড হওয়ার গতি অপ্টিমাইজ করার একটি উপেক্ষিত দিক হল ব্রাউজারের ইন্টার্নাল সম্পর্কে কিছুটা জানা। ব্রাউজার পারফর্ম্যান্স উন্নত করার জন্য নির্দিষ্ট কিছু অপ্টিমাইজেশন করে যা ডেভেলপার হিসেবে আমরা করতে পারি না—তবে শুধুমাত্র ততক্ষণ পর্যন্ত যতক্ষণ না সেই অপ্টিমাইজেশনগুলি অনিচ্ছাকৃতভাবে বাধাগ্রস্ত হয়।

ব্রাউজার প্রিলোড স্ক্যানার হল ইন্টার্নাল ব্রাউজার অপ্টিমাইজেশন যা আপনাকে বুঝতে হবে। এই পোস্টে প্রিলোড স্ক্যানার কীভাবে কাজ করে এবং আরও গুরুত্বপূর্ণভাবে, আপনি কীভাবে এর পথে বাধা সৃষ্টি করা এড়াতে পারেন তা কভার করা হবে।

প্রিলোড স্ক্যানার কী?

প্রতিটি ব্রাউজারে একটি প্রাথমিক HTML পার্সার থাকে যা র মার্কআপকে টোকেনাইজ করে এবং এটিকে একটি অবজেক্ট মডেলে প্রসেস করে। পার্সার কোনও ব্লকিং রিসোর্স খুঁজে না পাওয়া পর্যন্ত এই প্রক্রিয়া চলতে থাকে। ব্লকিং রিসোর্স হল <link> এলিমেন্ট সহ লোড করা স্টাইলশিট অথবা async বা defer অ্যাট্রিবিউট ছাড়া <script> এলিমেন্ট সহ লোড করা স্ক্রিপ্ট।

HTML পার্সার ডায়াগ্রাম।
ছবি ১: ব্রাউজারের প্রাথমিক HTML পার্সার কীভাবে ব্লক করা যেতে পারে তার একটি ডায়াগ্রাম। এই ক্ষেত্রে, পার্সার এক্সটার্নাল CSS ফাইলের জন্য <link> এলিমেন্ট খুঁজে পায়, যা ব্রাউজারকে ডকুমেন্টের বাকি অংশ পার্স করা থেকে আটকায়—এমনকি CSS ডাউনলোড ও পার্স না করা পর্যন্ত এর কোনও অংশই রেন্ডার করতে দেয় না।

CSS ফাইলের ক্ষেত্রে, ফ্ল্যাশ অফ আনস্টাইলড কন্টেন্ট (FOUC) প্রতিরোধ করার জন্য রেন্ডারিং ব্লক করা হয়, যা হল কোনও পৃষ্ঠার স্টাইল প্রয়োগ করার আগে পৃষ্ঠার একটি আনস্টাইলড ভার্সন সংক্ষেপে দেখা যেতে পারে।

স্টাইল করা হয়নি এমন অবস্থায় (বাঁদিকে) এবং স্টাইল করা অবস্থায় (ডানদিকে) web.dev হোম পেজ।
ছবি ২: FOUC-এর একটি সিমুলেটেড উদাহরণ। বাঁদিকে স্টাইল ছাড়া web.dev-এর প্রথম পৃষ্ঠা দেখানো হয়েছে। ডানদিকে স্টাইল প্রয়োগ করা একই পৃষ্ঠা দেখানো হয়েছে। স্টাইলশিট ডাউনলোড ও প্রসেস করার সময় ব্রাউজার রেন্ডারিং ব্লক না করলে, স্টাইলহীন অবস্থা এক ঝলকে দেখা যেতে পারে।

এছাড়াও, defer বা async অ্যাট্রিবিউট ছাড়া <script> এলিমেন্ট পেলে, ব্রাউজার পৃষ্ঠার পার্সিং ও রেন্ডারিং ব্লক করে দেয়।

এর কারণ হল, প্রাইমারি HTML পার্সার কাজ করার সময় কোনও স্ক্রিপ্ট DOM-এ পরিবর্তন করবে কিনা তা ব্রাউজার নিশ্চিতভাবে জানতে পারে না। এই কারণে, ডকুমেন্টের শেষে জাভাস্ক্রিপ্ট লোড করা একটি সাধারণ প্র্যাকটিস, যাতে ব্লক করা পার্সিং এবং রেন্ডারিংয়ের প্রভাব ন্যূনতম হয়।

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

প্রাইমারি HTML পার্সার (বাঁদিকে) এবং প্রিলোড স্ক্যানার (ডানদিকে) যা সেকেন্ডারি HTML পার্সার, দুটিরই ডায়াগ্রাম।
ছবি ৩: একটি ডায়াগ্রাম যা দেখায় যে কীভাবে প্রিলোড স্ক্যানার প্রাইমারি HTML পার্সারের সাথে সমান্তরালভাবে কাজ করে যাতে অ্যাসেট স্পেকুলেটিভভাবে লোড করা যায়। এখানে, প্রাথমিক HTML পার্সার ব্লক করা হয়েছে কারণ এটি <body> এলিমেন্টে ইমেজ মার্কআপ প্রসেস করা শুরু করার আগে CSS লোড এবং প্রসেস করে, কিন্তু প্রিলোড স্ক্যানার র মার্কআপে আগে থেকে দেখে সেই ইমেজ রিসোর্স খুঁজে পেতে পারে এবং প্রাথমিক HTML পার্সার আনব্লক হওয়ার আগে এটি লোড করা শুরু করতে পারে।

প্রিলোড স্ক্যানারের ভূমিকা হল অনুমান করা, অর্থাৎ এটি প্রাইমারি HTML পার্সার আবিষ্কার করার আগেই সুযোগ বুঝে রিসোর্স খুঁজে পেতে র মার্কআপ পরীক্ষা করে।

প্রিলোড স্ক্যানার কখন কাজ করছে তা কীভাবে বুঝবেন

ব্লক করা রেন্ডারিং ও পার্সিংয়ের কারণে প্রিলোড স্ক্যানার থাকে। পারফর্ম্যান্স সংক্রান্ত এই দুটি সমস্যা না থাকলে, প্রিলোড স্ক্যানার খুব একটা কাজে লাগত না। কোনও ওয়েব পেজ প্রিলোড স্ক্যানার থেকে সুবিধা পায় কিনা তা বোঝার মূল উপায় হল এই ব্লকিংয়ের ঘটনা। এটি করার জন্য, প্রিলোড স্ক্যানার কোথায় কাজ করছে তা খুঁজে বের করার অনুরোধের জন্য আপনি একটি কৃত্রিম বিলম্বের ব্যবস্থা করতে পারেন।

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

WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট স্টাইলশিটে ২ সেকেন্ডের কৃত্রিম বিলম্ব দেখায়।
ছবি ৪: সিমুলেট করা 3G কানেকশনে মোবাইল ডিভাইসে Chrome-এ চলা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। স্টাইলশিট লোড হওয়া শুরু হওয়ার আগে প্রক্সির মাধ্যমে কৃত্রিমভাবে দুই সেকেন্ড দেরি করা হলেও, মার্কআপ পেলোডে পরে থাকা ছবি প্রিলোড স্ক্যানার খুঁজে পায়।

আপনি ওয়াটারফলে দেখতে পাচ্ছেন যে প্রিলোড স্ক্যানার <img> এলিমেন্ট খুঁজে পায় এমনকি রেন্ডারিং ও ডকুমেন্ট পার্সিং ব্লক করা থাকলেও। এই অপ্টিমাইজেশন ছাড়া, ব্রাউজার ব্লকিং পিরিয়ডের সময় সুযোগ বুঝে জিনিসপত্র ফেচ করতে পারে না এবং আরও রিসোর্স অনুরোধ সমবর্তী হওয়ার পরিবর্তে পরপর হবে।

খেলনার উদাহরণটি বাদ দিয়ে, আসুন কিছু বাস্তব-জগতের প্যাটার্ন দেখে নেওয়া যাক যেখানে প্রিলোড স্ক্যানারকে পরাজিত করা যেতে পারে—এবং সেগুলি ঠিক করার জন্য কী করা যেতে পারে।

asyncটি স্ক্রিপ্ট ইনজেক্ট করা হয়েছে

ধরা যাক, আপনার <head>-এ HTML আছে যার মধ্যে এই ধরনের কিছু ইনলাইন জাভাস্ক্রিপ্ট আছে:

<script>
  const scriptEl = document.createElement('script');
  scriptEl.src = '/yall.min.js';

  document.head.appendChild(scriptEl);
</script>

ইনজেক্ট করা স্ক্রিপ্ট ডিফল্ট হিসেবে async হয়, তাই এই স্ক্রিপ্ট ইনজেক্ট করা হলে, এটি এমনভাবে কাজ করবে যেন async অ্যাট্রিবিউট এতে প্রয়োগ করা হয়েছে। এর অর্থ হল, এটি যত তাড়াতাড়ি সম্ভব রান করবে এবং রেন্ডারিং ব্লক করবে না। দারুণ, তাই না? তবুও, আপনি যদি মনে করেন যে এই ইনলাইন <script>, <link> এলিমেন্টের পরে আসে যা একটি এক্সটার্নাল CSS ফাইল লোড করে, তাহলে আপনি সাবঅপ্টিমাল ফলাফল পাবেন:

এই WebPageTest চার্ট দেখায় যে স্ক্রিপ্ট ইনজেক্ট করা হলে প্রিলোড স্ক্যান কাজ করে না।
ছবি ৫: সিমুলেট করা 3G কানেকশনে মোবাইল ডিভাইসে Chrome-এ রান করা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠায় একটি স্টাইলশিট এবং একটি ইনজেক্ট করা async স্ক্রিপ্ট আছে। রেন্ডার ব্লকিং ফেজ চলাকালীন প্রিলোড স্ক্যানার স্ক্রিপ্ট খুঁজে পায় না, কারণ এটি ক্লায়েন্টে ইনজেক্ট করা হয়।

এখানে কী ঘটেছে তা বিশ্লেষণ করা যাক:

  1. ০ সেকেন্ডে, প্রধান ডকুমেন্টের অনুরোধ করা হয়েছে।
  2. ১.৪ সেকেন্ডে, নেভিগেশন অনুরোধের প্রথম বাইট আসে।
  3. ২.০ সেকেন্ডে, CSS এবং ছবির জন্য অনুরোধ করা হয়েছে।
  4. যেহেতু পার্সার স্টাইলশিট লোড করা ব্লক করে এবং ইনলাইন জাভাস্ক্রিপ্ট যা async স্ক্রিপ্ট ইনজেক্ট করে তা ২.৬ সেকেন্ডে সেই স্টাইলশিটের পরে আসে, তাই স্ক্রিপ্ট যে কার্যকারিতা প্রদান করে তা যত তাড়াতাড়ি সম্ভব উপলভ্য হয় না।

এটি সাবঅপ্টিমাল কারণ স্টাইলশিট ডাউনলোড করা শেষ হওয়ার পরেই স্ক্রিপ্টের জন্য অনুরোধ করা হয়। এর ফলে স্ক্রিপ্ট যত তাড়াতাড়ি সম্ভব রান করার ক্ষেত্রে দেরি হয়। অন্যদিকে, <img> এলিমেন্টটি সার্ভার-প্রদত্ত মার্কআপে খুঁজে পাওয়া যায় বলে, এটি প্রিলোড স্ক্যানার খুঁজে পায়।

তাহলে, DOM-এ স্ক্রিপ্ট ইনজেক্ট করার পরিবর্তে async অ্যাট্রিবিউট সহ সাধারণ <script> ট্যাগ ব্যবহার করলে কী হবে?

<script src="/yall.min.js" async></script>

এই হল ফলাফল:

একটি WebPageTest নেটওয়ার্ক ওয়াটারফল, যা দেখায় যে HTML স্ক্রিপ্ট এলিমেন্ট ব্যবহার করে লোড করা একটি অ্যাসিঙ্ক স্ক্রিপ্ট এখনও ব্রাউজার প্রিলোড স্ক্যানার দ্বারা খুঁজে পাওয়া যায়, যদিও স্টাইলশিট ডাউনলোড এবং প্রসেস করার সময় ব্রাউজারের প্রাথমিক HTML পার্সার ব্লক করা থাকে।
ছবি ৬: সিমুলেট করা 3G কানেকশনের মাধ্যমে মোবাইল ডিভাইসে Chrome-এ রান করা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠায় একটি স্টাইলশিট এবং একটি async <script> এলিমেন্ট আছে। প্রিলোড স্ক্যানার রেন্ডার ব্লকিং ফেজে স্ক্রিপ্ট খুঁজে পায় এবং CSS-এর সাথে একই সময়ে এটি লোড করে।

rel=preload ব্যবহার করে এইসব সমস্যার সমাধান করা যেতে পারে বলে সাজেস্ট করার প্রলোভন থাকতে পারে। এটি অবশ্যই কাজ করবে, তবে এর কিছু পার্শ্বপ্রতিক্রিয়া থাকতে পারে। DOM-এ <script> এলিমেন্ট ইনজেক্ট না করে যে সমস্যা এড়ানো যায়, তা সমাধান করার জন্য rel=preload ব্যবহার করার প্রয়োজন কী?

একটি WebPageTest ওয়াটারফল দেখাচ্ছে যে কীভাবে rel=preload রিসোর্স হিন্ট ব্যবহার করে অ্যাসিঙ্ক ইনজেক্টেড স্ক্রিপ্ট খুঁজে পাওয়া যায়—যদিও এর ফলে কিছু অনভিপ্রেত পার্শ্বপ্রতিক্রিয়া হতে পারে।
ছবি ৭: সিমুলেট করা 3G কানেকশনে মোবাইল ডিভাইসে Chrome-এ রান করা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠায় একটি স্টাইলশিট ও ইনজেক্ট করা async স্ক্রিপ্ট আছে, তবে async স্ক্রিপ্ট প্রিলোড করা আছে যাতে এটি আরও দ্রুত খুঁজে পাওয়া যায়।

প্রিলোড করা এখানে সমস্যার "সমাধান" করে, তবে এটি একটি নতুন সমস্যা তৈরি করে: প্রথম দুটি ডেমোতে async স্ক্রিপ্ট—<head>-এ লোড করা সত্ত্বেও—"কম" প্রায়োরিটিতে লোড করা হয়, যেখানে স্টাইলশিট "সর্বোচ্চ" প্রায়োরিটিতে লোড করা হয়। শেষ ডেমোতে যেখানে async স্ক্রিপ্ট প্রিলোড করা হয়েছে, সেখানে স্টাইলশিট এখনও "সর্বোচ্চ" অগ্রাধিকার দিয়ে লোড করা হয়েছে, তবে স্ক্রিপ্টের অগ্রাধিকার "বেশি"তে উন্নীত করা হয়েছে।

কোনও রিসোর্সের অগ্রাধিকার বাড়ানো হলে, ব্রাউজার সেটির জন্য আরও বেশি ব্যান্ডউইথ বরাদ্দ করে। এর অর্থ হল—স্টাইলশিটের সর্বোচ্চ অগ্রাধিকার থাকলেও—স্ক্রিপ্টের অগ্রাধিকার বাড়ানোর ফলে ব্যান্ডউইথ নিয়ে সমস্যা হতে পারে। ইন্টারনেট কানেকশন স্লো হলে বা রিসোর্স অনেক বড় হলে এটি হতে পারে।

এর উত্তর খুব সহজ: স্টার্টআপের সময় স্ক্রিপ্টের প্রয়োজন হলে, DOM-এ এটি ইনজেক্ট করে প্রিলোড স্ক্যানারকে পরাস্ত করবেন না। প্রয়োজন অনুযায়ী <script> এলিমেন্ট প্লেসমেন্ট এবং defer ও async-এর মতো অ্যাট্রিবিউট নিয়ে পরীক্ষা করে দেখুন।

জাভাস্ক্রিপ্টের মাধ্যমে ধীরে ধীরে লোড করা

ধীরে ধীরে লোড করা হল ডেটা সাশ্রয় করার একটি দুর্দান্ত পদ্ধতি, যা প্রায়শই ছবির ক্ষেত্রে প্রয়োগ করা হয়। তবে, কিছু ক্ষেত্রে "ভাঁজের উপরে" থাকা ছবিতে ধীরে ধীরে লোড হওয়ার পদ্ধতি ভুলভাবে প্রয়োগ করা হয়।

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

<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

JavaScript-এর মাধ্যমে পরিচালিত লেজি লোডারে data- প্রিফিক্স ব্যবহার করা একটি সাধারণ প্যাটার্ন। ছবিটি ভিউপোর্টে স্ক্রল করা হলে, লেজি লোডার data- প্রিফিক্সটি সরিয়ে দেয়, যার অর্থ হল পূর্ববর্তী উদাহরণে, data-src হয়ে যায় src। এই আপডেট ব্রাউজারকে রিসোর্স ফেচ করার জন্য প্রম্পট করে।

স্টার্টআপের সময় ভিউপোর্টে থাকা ছবিতে প্রয়োগ না করা পর্যন্ত এই প্যাটার্নটি সমস্যাজনক নয়। প্রিলোড স্ক্যানার data-src অ্যাট্রিবিউটকে src (বা srcset) অ্যাট্রিবিউটের মতো করে পড়ে না, তাই ছবির রেফারেন্স আগে থেকে খুঁজে পাওয়া যায় না। আরও খারাপ হল, লেজি লোডার জাভাস্ক্রিপ্ট ডাউনলোড, কম্পাইল ও এক্সিকিউট হওয়ার পরে ইমেজ লোড হতে দেরি হয়।

WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট থেকে দেখা যায় যে স্টার্টআপের সময় ভিউপোর্টে থাকা ধীরে ধীরে লোড হওয়া ছবি কেন দেরি করে লোড হয়। ব্রাউজার প্রিলোড স্ক্যানার ছবির রিসোর্স খুঁজে পায় না এবং ধীরে ধীরে লোড হওয়ার জন্য প্রয়োজনীয় জাভাস্ক্রিপ্ট লোড হওয়ার পরেই এটি লোড হয়। ছবিটি অনেক পরে খুঁজে পাওয়া গেছে।
ছবি ৮: সিমুলেট করা 3G কানেকশনের মাধ্যমে মোবাইল ডিভাইসে Chrome-এ রান করা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। স্টার্টআপের সময় ভিউপোর্টে দেখা গেলেও, ছবির রিসোর্স অপ্রয়োজনীয়ভাবে ধীরে ধীরে লোড করা হয়েছে। এটি প্রিলোড স্ক্যানারকে পরাজিত করে এবং অপ্রয়োজনীয় বিলম্ব ঘটায়।

ছবির সাইজের উপর নির্ভর করে—যা ভিউপোর্টের সাইজের উপর নির্ভর করতে পারে—এটি Largest Contentful Paint (LCP)-এর জন্য একটি ক্যান্ডিডেট এলিমেন্ট হতে পারে। প্রিলোড স্ক্যানার যখন সময়ের আগে ইমেজ রিসোর্স স্পেকুলেটিভভাবে ফেচ করতে পারে না—সম্ভবত সেই সময় যখন পৃষ্ঠার স্টাইলশিট রেন্ডারিং ব্লক করে—LCP-র উপর প্রভাব পড়ে।

সমাধান হল, ছবির মার্কআপ পরিবর্তন করা:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

স্টার্টআপের সময় ভিউপোর্টে থাকা ছবির জন্য এটি হল সবচেয়ে ভালো প্যাটার্ন, কারণ প্রিলোড স্ক্যানার আরও দ্রুত ছবির রিসোর্স খুঁজে নিয়ে আসবে।

WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট যা স্টার্টআপের সময় ভিউপোর্টে কোনও ছবির লোডিং পরিস্থিতি বর্ণনা করে। ছবিটি ধীরে ধীরে লোড করা হয় না, যার অর্থ হল এটি লোড করার জন্য স্ক্রিপ্টের উপর নির্ভর করে না, অর্থাৎ প্রিলোড স্ক্যানার এটি আরও দ্রুত খুঁজে পেতে পারে।
ছবি ৯: সিমুলেট করা 3G কানেকশনের মাধ্যমে মোবাইল ডিভাইসে Chrome-এ রান করা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। CSS এবং JavaScript লোড হওয়া শুরু হওয়ার আগেই প্রিলোড স্ক্যানার ইমেজ রিসোর্স খুঁজে নেয়, যার ফলে ব্রাউজার এটি লোড করার জন্য আগে থেকেই প্রস্তুত থাকে।

এই সরলীকৃত উদাহরণের ফলাফল হল, স্লো কানেকশনে LCP-তে ১০০-মিলিসেকেন্ডের উন্নতি। এটি হয়ত বিশাল কিছু শোনাচ্ছে না, তবে আপনি যদি কোনও ম্যাচ চলাকালীন লেভেল ৩ বর্ম খুঁজে পান, তাহলে এই অতিরিক্ত স্থায়িত্ব একটি ম্যাচের শেষ মুহূর্তে বড় সুবিধা করে দেয়। এর অর্থ হল, LCP ক্যান্ডিডেটকে অন্যান্য অনেক রিসোর্সের সাথে ব্যান্ডউইথের জন্য প্রতিযোগিতা করতে হতে পারে, তাই এই ধরনের অপ্টিমাইজেশন ক্রমশ গুরুত্বপূর্ণ হয়ে উঠছে।

CSS ব্যাকগ্রাউন্ড ছবি

মনে রাখবেন যে ব্রাউজার প্রিলোড স্ক্যানার মার্কআপ স্ক্যান করে। এটি অন্যান্য রিসোর্সের ধরন স্ক্যান করে না, যেমন CSS, যার মধ্যে background-image প্রপার্টি দ্বারা রেফারেন্স করা ছবির জন্য ফেচ করা অন্তর্ভুক্ত থাকতে পারে।

HTML-এর মতো, ব্রাউজার CSS-কে নিজস্ব অবজেক্ট মডেলে প্রসেস করে, যা CSSOM নামে পরিচিত। CSSOM তৈরি করার সময় এক্সটার্নাল রিসোর্স খুঁজে পাওয়া গেলে, খুঁজে পাওয়ার সময় সেই রিসোর্সের জন্য অনুরোধ করা হয়, প্রিলোড স্ক্যানারের মাধ্যমে নয়।

ধরা যাক, আপনার পৃষ্ঠার LCP ক্যান্ডিডেট হল CSS background-image প্রপার্টি সহ একটি এলিমেন্ট। রিসোর্স লোড হওয়ার সময় নিম্নলিখিত ঘটনাগুলি ঘটে:

WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট, যেখানে background-image প্রপার্টি ব্যবহার করে CSS থেকে লোড করা LCP ক্যান্ডিডেট সহ একটি পৃষ্ঠা দেখানো হয়েছে। LCP ক্যান্ডিডেট ছবি এমন একটি রিসোর্স টাইপে রয়েছে যা ব্রাউজার প্রিলোড স্ক্যানার পরীক্ষা করতে পারে না, তাই CSS ডাউনলোড ও প্রসেস না হওয়া পর্যন্ত রিসোর্স লোড হতে দেরি হয়, যার ফলে LCP ক্যান্ডিডেটের পেইন্ট টাইমও দেরি হয়।
ছবি ১০: সিমুলেট করা 3G কানেকশনে মোবাইল ডিভাইসে Chrome-এ চলা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠার LCP ক্যান্ডিডেট হল CSS background-image প্রপার্টি (সারি ৩) সহ একটি এলিমেন্ট। CSS পার্সার খুঁজে না পাওয়া পর্যন্ত এটি যে ছবির অনুরোধ করে সেটি ফেচ করা শুরু হয় না।

এই ক্ষেত্রে, প্রিলোড স্ক্যানারটি খুব বেশি পরাজিত হয় না কারণ এটি জড়িত নয়। এমনকি, পৃষ্ঠায় LCP ক্যান্ডিডেট background-image CSS প্রপার্টি থেকে হলে, আপনি সেই ছবি প্রিলোড করতে চাইবেন:

<!-- Make sure this is in the <head> below any
     stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">

এই rel=preload ইঙ্গিতটি ছোট, তবে এটি ব্রাউজারকে অন্যথায় যে সময়ের মধ্যে ছবিটি আবিষ্কার করতে পারে তার চেয়ে দ্রুত ছবিটি আবিষ্কার করতে সহায়তা করে:

WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট CSS ব্যাকগ্রাউন্ড ইমেজ (যা LCP ক্যান্ডিডেট) দেখাচ্ছে যা rel=preload হিন্ট ব্যবহার করার কারণে অনেক দ্রুত লোড হচ্ছে। LCP সময় প্রায় ২৫০ মিলিসেকেন্ড উন্নত হয়।
ছবি ১১: সিমুলেট করা 3G কানেকশনের মাধ্যমে মোবাইল ডিভাইসে Chrome-এ রান করা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠার LCP ক্যান্ডিডেট হল CSS background-image প্রপার্টি (সারি ৩) সহ একটি এলিমেন্ট। rel=preload ইঙ্গিতটি ব্রাউজারকে ইঙ্গিত ছাড়া সময়ের চেয়ে প্রায় ২৫০ মিলিসেকেন্ড আগে ছবি খুঁজে পেতে সাহায্য করে।

rel=preload হিন্টের মাধ্যমে, LCP ক্যান্ডিডেট আরও দ্রুত খুঁজে পাওয়া যায়, যার ফলে LCP-এর সময় কমে যায়। এই ইঙ্গিতটি এই সমস্যার সমাধান করতে সাহায্য করলেও, আপনার ইমেজ LCP ক্যান্ডিডেট CSS থেকে লোড করতে হবে কিনা তা মূল্যায়ন করা আরও ভালো বিকল্প হতে পারে। <img> ট্যাগের মাধ্যমে, আপনি ভিউপোর্টের জন্য উপযুক্ত ছবি লোড করার উপর আরও নিয়ন্ত্রণ পাবেন এবং প্রিলোড স্ক্যানারকে এটি খুঁজে পেতে অনুমতি দেবেন।

অনেক বেশি রিসোর্স ইনলাইন করা হচ্ছে

ইনলাইনিং হল এমন একটি পদ্ধতি যা HTML-এর মধ্যে রিসোর্স যোগ করে। আপনি <style> এলিমেন্টে স্টাইলশিট, <script> এলিমেন্টে স্ক্রিপ্ট এবং base64 এনকোডিং ব্যবহার করে কার্যত অন্য যেকোনও রিসোর্স ইনলাইন করতে পারবেন।

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

  • আপনি যদি HTML ক্যাশে না করেন—এবং HTML রেসপন্স ডাইনামিক হলে আপনি তা করতে পারবেন না—ইনলাইন করা রিসোর্স কখনই ক্যাশে করা হয় না। এটি পারফর্ম্যান্সকে প্রভাবিত করে কারণ ইনলাইন করা রিসোর্স আবার ব্যবহার করা যায় না।
  • আপনি HTML ক্যাশে করতে পারলেও, ইনলাইন করা রিসোর্স ডকুমেন্টগুলির মধ্যে শেয়ার করা হয় না। এটি এক্সটার্নাল ফাইলের তুলনায় ক্যাশিংয়ের কার্যকারিতা কমায় যা ক্যাশ করা যায় এবং সম্পূর্ণ অরিজিন জুড়ে আবার ব্যবহার করা যায়।
  • আপনি যদি খুব বেশি ইনলাইন করেন, তাহলে আপনি ডকুমেন্টে পরে রিসোর্স আবিষ্কার করা থেকে প্রিলোড স্ক্যানারকে বিলম্বিত করেন, কারণ সেই অতিরিক্ত, ইনলাইন করা, কন্টেন্ট ডাউনলোড করতে বেশি সময় লাগে।

উদাহরণ হিসেবে এই পৃষ্ঠা দেখুন। কিছু পরিস্থিতিতে LCP ক্যান্ডিডেট হল পৃষ্ঠার সবচেয়ে উপরে থাকা ছবি এবং CSS হল আলাদা ফাইলে থাকা <link> এলিমেন্ট দ্বারা লোড করা কন্টেন্ট। এছাড়াও, পৃষ্ঠাটি চারটি ওয়েব ফন্ট ব্যবহার করে যেগুলি CSS রিসোর্স থেকে আলাদা ফাইল হিসেবে অনুরোধ করা হয়।

চারটি ফন্ট রেফারেন্স করা আছে এমন এক্সটার্নাল CSS ফাইল সহ পৃষ্ঠার WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। LCP ক্যান্ডিডেট ইমেজ যথাসময়ে প্রিলোড স্ক্যানার দ্বারা খুঁজে পাওয়া গেছে।
ছবি ১২: সিমুলেট করা 3G কানেকশনে মোবাইল ডিভাইসে Chrome-এ চলা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠার LCP ক্যান্ডিডেট হল <img> এলিমেন্ট থেকে লোড করা একটি ছবি, তবে প্রিলোড স্ক্যানার এটি খুঁজে পায় কারণ পৃষ্ঠার জন্য প্রয়োজনীয় CSS এবং ফন্ট আলাদা রিসোর্সে লোড হয়, যা প্রিলোড স্ক্যানারকে তার কাজ করতে দেরি করায় না।

এখন, CSS এবং সব ফন্ট base64 রিসোর্স হিসেবে ইনলাইন করা থাকলে কী হবে?

চারটি ফন্ট রেফারেন্স করা আছে এমন এক্সটার্নাল CSS ফাইল সহ পৃষ্ঠার WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। LCP ইমেজ খুঁজে পেতে প্রিলোড স্ক্যানার উল্লেখযোগ্যভাবে দেরি করেছে।
ছবি ১৩: সিমুলেট করা 3G কানেকশনে মোবাইল ডিভাইসে Chrome-এ চলা একটি ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। পৃষ্ঠার LCP ক্যান্ডিডেট হল <img> এলিমেন্ট থেকে লোড করা একটি ছবি, কিন্তু CSS-এর ইনলাইনিং এবং ``-এ এর চারটি ফন্ট রিসোর্স, প্রিলোড স্ক্যানারকে ছবিটি আবিষ্কার করতে দেরি করে যতক্ষণ না সেই রিসোর্সগুলি সম্পূর্ণভাবে ডাউনলোড হয়।

এই উদাহরণে ইনলাইনিংয়ের প্রভাব LCP-এর উপর নেতিবাচক ফলাফল দেয়—এবং সাধারণভাবে পারফর্ম্যান্সের উপর। পৃষ্ঠার যে ভার্সনে কোনও কিছু ইনলাইন করা হয় না, সেটি প্রায় ৩.৫ সেকেন্ডে LCP ছবি পেইন্ট করে। যে পৃষ্ঠায় সবকিছু ইনলাইন করা থাকে, সেখানে ৭ সেকেন্ডের বেশি সময় না হওয়া পর্যন্ত LCP ইমেজ পেইন্ট করা হয় না।

এখানে শুধু প্রিলোড স্ক্যানার ছাড়াও আরও অনেক কিছু আছে। ইনলাইনিং ফন্ট খুব একটা ভালো স্ট্র্যাটেজি নয় কারণ বাইনারি রিসোর্সের জন্য base64 একটি অদক্ষ ফর্ম্যাট। আরেকটি বিষয় হল, CSSOM-এর মাধ্যমে প্রয়োজনীয় বলে নির্ধারিত না হলে এক্সটার্নাল ফন্ট রিসোর্স ডাউনলোড করা হয় না। এইসব ফন্ট base64 হিসেবে ইনলাইন করা থাকলে, বর্তমান পৃষ্ঠার জন্য সেগুলি প্রয়োজন হোক বা না হোক, ডাউনলোড করা হয়।

এখানে কি প্রিলোড করলে সুবিধা হবে? নিশ্চয়ই। আপনি LCP ইমেজ প্রিলোড করতে পারেন এবং LCP সময় কমাতে পারেন, তবে ইনলাইন রিসোর্স সহ আপনার সম্ভাব্য আনক্যাশেবল HTML-এর সাইজ বাড়ালে পারফর্ম্যান্সের উপর অন্যান্য নেতিবাচক প্রভাব পড়ে। First Contentful Paint (FCP)-এর উপরেও এই প্যাটার্নের প্রভাব পড়ে। পৃষ্ঠার যে ভার্সনে কিছুই ইনলাইন করা নেই, সেখানে FCP হল প্রায় ২.৭ সেকেন্ড। যে ভার্সনে সবকিছু ইনলাইন করা আছে, সেখানে FCP হল প্রায় ৫.৮ সেকেন্ড।

HTML-এ ইনলাইন করার সময় খুব সতর্ক থাকুন, বিশেষ করে base64-এনকোড করা রিসোর্সের ক্ষেত্রে। সাধারণত, খুব ছোট রিসোর্স ছাড়া এটি সাজেস্ট করা হয় না। যতটা সম্ভব কম ইনলাইন করুন, কারণ খুব বেশি ইনলাইন করা মানে আগুন নিয়ে খেলা।

ক্লায়েন্ট-সাইড জাভাস্ক্রিপ্টের মাধ্যমে মার্কআপ রেন্ডার করা

এই বিষয়ে কোনও সন্দেহ নেই: জাভাস্ক্রিপ্ট অবশ্যই পৃষ্ঠা লোড হওয়ার গতির উপর প্রভাব ফেলে। ইন্টার‍্যাক্টিভিটি প্রদান করার জন্য ডেভেলপাররা শুধু এর উপর নির্ভর করেন না, কন্টেন্ট ডেলিভার করার জন্যও এর উপর নির্ভর করার প্রবণতা দেখা গেছে। এর ফলে কিছু ক্ষেত্রে ডেভেলপাররা আরও ভালো অভিজ্ঞতা পান; তবে ডেভেলপারদের জন্য সুবিধাগুলি সবসময় ব্যবহারকারীদের জন্য সুবিধায় রূপান্তরিত হয় না।

একটি প্যাটার্ন যা প্রিলোড স্ক্যানারকে হারাতে পারে তা হল ক্লায়েন্ট-সাইড জাভাস্ক্রিপ্ট সহ মার্কআপ রেন্ডার করা:

WebPageTest নেটওয়ার্ক ওয়াটারফল, যেখানে জাভাস্ক্রিপ্টে ক্লায়েন্টে সম্পূর্ণভাবে রেন্ডার করা ছবি ও টেক্সট সহ একটি বেসিক পৃষ্ঠা দেখানো হয়েছে। যেহেতু জাভাস্ক্রিপ্টের মধ্যে মার্কআপ থাকে, তাই প্রিলোড স্ক্যানার কোনও রিসোর্স শনাক্ত করতে পারে না। জাভাস্ক্রিপ্ট ফ্রেমওয়ার্কের জন্য প্রয়োজনীয় অতিরিক্ত নেটওয়ার্ক ও প্রসেসিংয়ের সময়ের কারণে সব রিসোর্স অতিরিক্ত দেরি করে।
ছবি ১৪: সিমুলেটেড 3G কানেকশনের মাধ্যমে মোবাইল ডিভাইসে Chrome-এ রান করা ক্লায়েন্ট-রেন্ডার করা ওয়েব পেজের WebPageTest নেটওয়ার্ক ওয়াটারফল চার্ট। কন্টেন্টটি জাভাস্ক্রিপ্টে রয়েছে এবং রেন্ডার করার জন্য একটি ফ্রেমওয়ার্কের উপর নির্ভর করে, তাই ক্লায়েন্ট-রেন্ডার করা মার্কআপে ইমেজ রিসোর্স প্রিলোড স্ক্যানার থেকে লুকানো থাকে। সার্ভার-রেন্ডার করা সমতুল্য অভিজ্ঞতা ছবি ৯-এ দেখানো হয়েছে।

ব্রাউজারে জাভাস্ক্রিপ্টের মাধ্যমে মার্কআপ পেলোড সম্পূর্ণভাবে অন্তর্ভুক্ত ও রেন্ডার করা হলে, সেই মার্কআপের যেকোনও রিসোর্স প্রিলোড স্ক্যানারের কাছে কার্যকরভাবে অদৃশ্য থাকে। এর ফলে গুরুত্বপূর্ণ রিসোর্স খুঁজে পেতে দেরি হয়, যা অবশ্যই LCP-কে প্রভাবিত করে। এইসব উদাহরণের ক্ষেত্রে, LCP ছবির জন্য করা অনুরোধ উল্লেখযোগ্যভাবে দেরি করে আসে, যদি একই ধরনের সার্ভার-রেন্ডার করা অভিজ্ঞতার সাথে তুলনা করা হয়, যেখানে দেখানোর জন্য জাভাস্ক্রিপ্টের প্রয়োজন হয় না।

এটি এই নিবন্ধের মূল বিষয় থেকে একটু আলাদা, তবে ক্লায়েন্টে মার্কআপ রেন্ডার করার প্রভাব প্রিলোড স্ক্যানারকে পরাস্ত করার চেয়ে অনেক বেশি। যেমন, জাভাস্ক্রিপ্ট প্রয়োজন নেই এমন অভিজ্ঞতায় জাভাস্ক্রিপ্ট ব্যবহার করলে প্রসেসিংয়ের জন্য অপ্রয়োজনীয় সময় লাগে যা ইন্টার‍্যাকশন টু নেক্সট পেইন্ট (INP)-কে প্রভাবিত করতে পারে। সার্ভার থেকে পাঠানো একই পরিমাণ মার্কআপের তুলনায় ক্লায়েন্টে অত্যন্ত বেশি পরিমাণ মার্কআপ রেন্ডার করলে বড় টাস্ক তৈরি হওয়ার সম্ভাবনা বেশি থাকে। এর কারণ হল—জাভাস্ক্রিপ্টের সাথে জড়িত অতিরিক্ত প্রসেসিং ছাড়াও—ব্রাউজারগুলি সার্ভার থেকে মার্কআপ স্ট্রিম করে এবং এমনভাবে রেন্ডারিং করে যাতে বড় টাস্ক সীমিত করা যায়। অন্যদিকে, ক্লায়েন্ট-রেন্ডার করা মার্কআপকে একটি একক, মনোলিথিক টাস্ক হিসেবে ম্যানেজ করা হয়, যা কোনও পৃষ্ঠার INP-কে প্রভাবিত করতে পারে।

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

আপনার পৃষ্ঠার মার্কআপের কিছু অংশে কার্যকারিতা যোগ করার জন্য যদি আপনার পৃষ্ঠায় জাভাস্ক্রিপ্টের প্রয়োজন হয়, তাহলেও আপনি SSR-এর মাধ্যমে তা করতে পারেন, হয় ভ্যানিলা জাভাস্ক্রিপ্ট ব্যবহার করে অথবা হাইড্রেশন ব্যবহার করে, যাতে আপনি দুটিরই সেরা সুবিধা পেতে পারেন।

প্রিলোড স্ক্যানারকে আপনাকে সাহায্য করতে দিন

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

সংক্ষেপে, এই পোস্ট থেকে আপনি নিম্নলিখিত বিষয়গুলি জানতে পারবেন:

  • ব্রাউজার প্রিলোড স্ক্যানার হল একটি সেকেন্ডারি HTML পার্সার যা প্রাইমারি পার্সার ব্লক করা থাকলে তার আগেই স্ক্যান করে যাতে এটি আরও দ্রুত ফেচ করতে পারে এমন রিসোর্স খুঁজে পেতে পারে।
  • প্রাথমিক নেভিগেশন অনুরোধে সার্ভার দ্বারা প্রদত্ত মার্কআপে উপস্থিত নেই এমন রিসোর্স প্রিলোড স্ক্যানার দ্বারা খুঁজে পাওয়া যাবে না। প্রিলোড স্ক্যানারকে যেসব উপায়ে এড়িয়ে যাওয়া যেতে পারে তার মধ্যে এগুলি অন্তর্ভুক্ত (তবে এগুলির মধ্যেই সীমাবদ্ধ নয়):
    • জাভাস্ক্রিপ্টের মাধ্যমে DOM-এ রিসোর্স ইনজেক্ট করা, তা স্ক্রিপ্ট, ছবি, স্টাইলশিট বা অন্য কিছু হতে পারে যা সার্ভার থেকে প্রাথমিক মার্কআপ পেলোডে থাকলে ভালো হয়।
    • জাভাস্ক্রিপ্ট সমাধান ব্যবহার করে ধীরে ধীরে লোড করা অ্যাবাভ-দ্য-ফোল্ড ছবি বা iframe।
    • ক্লায়েন্টে মার্কআপ রেন্ডার করা যাতে জাভাস্ক্রিপ্ট ব্যবহার করে ডকুমেন্ট সাবরিসোর্সের রেফারেন্স থাকতে পারে।
  • প্রিলোড স্ক্যানার শুধু HTML স্ক্যান করে। এটি অন্যান্য রিসোর্সের কন্টেন্ট পরীক্ষা করে না—বিশেষ করে CSS—যার মধ্যে LCP ক্যান্ডিডেট সহ গুরুত্বপূর্ণ অ্যাসেটের রেফারেন্স থাকতে পারে।

যদি কোনও কারণে, আপনি এমন কোনও প্যাটার্ন এড়াতে না পারেন যা প্রিলোড স্ক্যানারের লোডিং পারফর্ম্যান্সের গতি বাড়ানোর ক্ষমতাকে নেতিবাচকভাবে প্রভাবিত করে, তাহলে rel=preload রিসোর্স হিন্ট বিবেচনা করুন। আপনি rel=preload ব্যবহার করলে, ল্যাব টুলে পরীক্ষা করে দেখুন যে এটি আপনাকে কাঙ্ক্ষিত ফলাফল দিচ্ছে কিনা। সবশেষে, খুব বেশি রিসোর্স প্রিলোড করবেন না, কারণ আপনি সব কিছুকে অগ্রাধিকার দিলে, কোনও কিছুই অগ্রাধিকার পাবে না।

রিসোর্স