নেক্সট পেইন্টের সাথে মিথস্ক্রিয়া বোঝা (আইএনপি)

1. ভূমিকা

ইন্টারঅ্যাকশন টু নেক্সট পেইন্ট (INP) সম্পর্কে শেখার জন্য একটি ইন্টারেক্টিভ ডেমো এবং কোডল্যাব।

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

পূর্বশর্ত

  • এইচটিএমএল এবং জাভাস্ক্রিপ্ট বিকাশের জ্ঞান।
  • প্রস্তাবিত: INP ডকুমেন্টেশন পড়ুন।

আপনি কি শিখুন

  • ব্যবহারকারীর ইন্টারঅ্যাকশনের ইন্টারপ্লে এবং সেই মিথস্ক্রিয়াগুলির আপনার পরিচালনা কীভাবে পৃষ্ঠার প্রতিক্রিয়াশীলতাকে প্রভাবিত করে।
  • মসৃণ ব্যবহারকারীর অভিজ্ঞতার জন্য কীভাবে বিলম্ব কমানো যায় এবং দূর করা যায়।

আপনার যা প্রয়োজন

  • GitHub থেকে কোড ক্লোন করার এবং npm কমান্ড চালানোর ক্ষমতা সহ একটি কম্পিউটার।
  • একজন টেক্সট এডিটর।
  • কাজ করার জন্য সমস্ত মিথস্ক্রিয়া পরিমাপের জন্য Chrome-এর একটি সাম্প্রতিক সংস্করণ।

2. সেট আপ করুন

কোডটি পান এবং চালান

কোডটি web-vitals-codelabs সংগ্রহস্থলে পাওয়া যায়।

  1. আপনার টার্মিনালে রেপো ক্লোন করুন: git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git
  2. ক্লোন করা ডিরেক্টরিতে যান: cd web-vitals-codelabs/understanding-inp
  3. নির্ভরতা ইনস্টল করুন: npm ci
  4. ওয়েব সার্ভার শুরু করুন: npm run start
  5. আপনার ব্রাউজারে http://localhost:5173/understanding-inp/ এ যান

অ্যাপটির ওভারভিউ

পৃষ্ঠার শীর্ষে অবস্থিত একটি স্কোর কাউন্টার এবং ইনক্রিমেন্ট বোতাম। প্রতিক্রিয়াশীলতা এবং প্রতিক্রিয়াশীলতার একটি ক্লাসিক ডেমো!

এই কোডল্যাবের জন্য ডেমো অ্যাপের একটি স্ক্রিনশট

বোতামের নীচে চারটি পরিমাপ রয়েছে:

  • INP: বর্তমান INP স্কোর, যা সাধারণত সবচেয়ে খারাপ ইন্টারঅ্যাকশন।
  • মিথস্ক্রিয়া: সাম্প্রতিক মিথস্ক্রিয়াটির স্কোর।
  • FPS: পৃষ্ঠার প্রতি সেকেন্ডে প্রধান থ্রেড ফ্রেম।
  • টাইমার: জ্যাঙ্ক কল্পনা করতে সাহায্য করার জন্য একটি চলমান টাইমার অ্যানিমেশন।

মিথস্ক্রিয়া পরিমাপের জন্য FPS এবং টাইমার এন্ট্রিগুলি মোটেই প্রয়োজনীয় নয়। এগুলি কেবলমাত্র প্রতিক্রিয়াশীলতাকে কিছুটা সহজ করার জন্য যুক্ত করা হয়েছে।

চেষ্টা করে দেখুন

ইনক্রিমেন্ট বোতামের সাথে ইন্টারঅ্যাক্ট করার চেষ্টা করুন এবং স্কোর বৃদ্ধি দেখুন। INP এবং ইন্টারঅ্যাকশন মান কি প্রতিটি বৃদ্ধির সাথে পরিবর্তিত হয়?

INP পরিমাপ করে যে ব্যবহারকারীর ইন্টারঅ্যাক্ট করার মুহূর্ত থেকে পৃষ্ঠাটি প্রকৃতপক্ষে ব্যবহারকারীকে রেন্ডার করা আপডেট না দেখা পর্যন্ত কতক্ষণ সময় নেয়।

3. Chrome DevTools-এর সাথে মিথস্ক্রিয়া পরিমাপ করা

আরও টুলস > ডেভেলপার টুলস মেনু থেকে DevTools খুলুন , পৃষ্ঠায় রাইট ক্লিক করে পরিদর্শন নির্বাচন করুন বা কীবোর্ড শর্টকাট ব্যবহার করে

পারফরম্যান্স প্যানেলে স্যুইচ করুন, যা আপনি ইন্টারঅ্যাকশন পরিমাপ করতে ব্যবহার করবেন।

অ্যাপের পাশাপাশি DevTools পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট

এরপরে, পারফরম্যান্স প্যানেলে একটি মিথস্ক্রিয়া ক্যাপচার করুন।

  1. রেকর্ড প্রেস করুন।
  2. পৃষ্ঠার সাথে ইন্টারঅ্যাক্ট করুন ( বৃদ্ধি বোতাম টিপুন)।
  3. রেকর্ডিং বন্ধ করুন।

ফলস্বরূপ টাইমলাইনে, আপনি একটি ইন্টারঅ্যাকশন ট্র্যাক পাবেন। বাম দিকের ত্রিভুজটিতে ক্লিক করে এটি প্রসারিত করুন।

DevTools পারফরম্যান্স প্যানেল ব্যবহার করে একটি মিথস্ক্রিয়া রেকর্ড করার একটি অ্যানিমেটেড প্রদর্শন

দুটি মিথস্ক্রিয়া প্রদর্শিত হয়। W কী স্ক্রোল করে বা ধরে রেখে দ্বিতীয়টিতে জুম ইন করুন।

DevTools পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট, প্যানেলে ইন্টারঅ্যাকশনের উপরে কার্সার ঘোরাফেরা করছে এবং ইন্টারঅ্যাকশনের সংক্ষিপ্ত সময় তালিকাভুক্ত একটি টুলটিপ

ইন্টারঅ্যাকশনের উপর ঘোরাঘুরি করে, আপনি দেখতে পারেন মিথস্ক্রিয়াটি দ্রুত ছিল, প্রক্রিয়াকরণের সময়কালের জন্য কোন সময় ব্যয় করেনি এবং ইনপুট বিলম্ব এবং উপস্থাপনা বিলম্বে ন্যূনতম পরিমাণ সময়, যার সঠিক দৈর্ঘ্য আপনার মেশিনের গতির উপর নির্ভর করবে।

4. দীর্ঘ-চলমান ইভেন্ট শ্রোতা

index.js ফাইলটি খুলুন এবং ইভেন্ট লিসেনারের ভিতরে blockFor ফাংশনটি আনকমেন্ট করুন।

সম্পূর্ণ কোড দেখুন: click_block.html

button.addEventListener('click', () => {
  blockFor(1000);
  score.incrementAndUpdateUI();
});

ফাইলটি সংরক্ষণ করুন। সার্ভার পরিবর্তনটি দেখতে পাবে এবং আপনার জন্য পৃষ্ঠাটি রিফ্রেশ করবে।

পৃষ্ঠাটির সাথে আবার ইন্টারঅ্যাক্ট করার চেষ্টা করুন। মিথস্ক্রিয়া এখন লক্ষণীয়ভাবে ধীর হবে।

কর্মক্ষমতা ট্রেস

এটি দেখতে কেমন তা দেখতে পারফরম্যান্স প্যানেলে আরেকটি রেকর্ডিং নিন।

পারফরম্যান্স প্যানেলে এক-সেকেন্ড-দীর্ঘ মিথস্ক্রিয়া

এক সময় যা ছিল একটি সংক্ষিপ্ত মিথস্ক্রিয়া এখন সম্পূর্ণ সেকেন্ড লাগে।

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

5. পরীক্ষা: প্রক্রিয়াকরণের সময়কাল

INP-তে প্রভাব দেখতে ইভেন্ট-শ্রোতার কাজকে পুনর্বিন্যাস করার উপায়গুলি ব্যবহার করে দেখুন।

প্রথমে UI আপডেট করুন

আপনি js কলের ক্রম অদলবদল করলে কী হবে—প্রথমে UI আপডেট করুন, তারপর ব্লক করুন?

সম্পূর্ণ কোড দেখুন: ui_first.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
  blockFor(1000);
});

আপনি UI আগে প্রদর্শিত লক্ষ্য করেছেন? অর্ডারটি কি INP স্কোরকে প্রভাবিত করে?

কোন পার্থক্য আছে কিনা তা দেখতে একটি ট্রেস নেওয়ার এবং মিথস্ক্রিয়া পরীক্ষা করার চেষ্টা করুন।

আলাদা শ্রোতা

যদি আপনি একটি পৃথক ইভেন্ট শ্রোতা কাজ সরান? একটি ইভেন্ট শ্রোতার মধ্যে UI আপডেট করুন, এবং একটি পৃথক শ্রোতা থেকে পৃষ্ঠাটি ব্লক করুন৷

সম্পূর্ণ কোড দেখুন: two_click.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('click', () => {
  blockFor(1000);
});

পারফরম্যান্স প্যানেলে এটি এখন কেমন দেখাচ্ছে?

বিভিন্ন ধরনের ইভেন্ট

বেশিরভাগ ইন্টারঅ্যাকশনগুলি পয়েন্টার বা কী ইভেন্ট থেকে শুরু করে হোভার, ফোকাস/ব্লার, এবং সিন্থেটিক ইভেন্ট যেমন পরিবর্তন এবং আগে ইনপুট পর্যন্ত অনেক ধরনের ইভেন্টগুলিকে ফায়ার করবে।

অনেক বাস্তব পৃষ্ঠার বিভিন্ন ইভেন্টের জন্য শ্রোতা রয়েছে।

আপনি ইভেন্ট শ্রোতাদের জন্য ইভেন্টের ধরন পরিবর্তন করলে কি হবে? উদাহরণস্বরূপ, pointerup বা mouseup দিয়ে click ইভেন্ট শ্রোতাদের একজনকে প্রতিস্থাপন করুন?

সম্পূর্ণ কোড দেখুন: diff_handlers.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('pointerup', () => {
  blockFor(1000);
});

কোন UI আপডেট নেই

আপনি ইভেন্ট লিসেনার থেকে UI আপডেট করার জন্য কলটি সরিয়ে দিলে কী হবে?

সম্পূর্ণ কোড দেখুন: no_ui.html

button.addEventListener('click', () => {
  blockFor(1000);
  // score.incrementAndUpdateUI();
});

6. সময়কাল পরীক্ষার ফলাফল প্রক্রিয়াকরণ

কর্মক্ষমতা ট্রেস: প্রথমে UI আপডেট করুন

সম্পূর্ণ কোড দেখুন: ui_first.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
  blockFor(1000);
});

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

পারফরম্যান্স প্যানেলে এখনও এক-সেকেন্ড-দীর্ঘ মিথস্ক্রিয়া

কর্মক্ষমতা ট্রেস: পৃথক শ্রোতা

সম্পূর্ণ কোড দেখুন: two_click.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('click', () => {
  blockFor(1000);
});

আবার, কার্যকরীভাবে কোন পার্থক্য নেই। মিথস্ক্রিয়া এখনও একটি সম্পূর্ণ সেকেন্ড লাগে.

আপনি যদি ক্লিক ইন্টারঅ্যাকশনের দিকে জুম করেন, আপনি দেখতে পাবেন যে click ইভেন্টের ফলে আসলেই দুটি ভিন্ন ফাংশন বলা হচ্ছে।

প্রত্যাশিত হিসাবে, প্রথমটি-ইউআই আপডেট করা-অবিশ্বাস্যভাবে দ্রুত চলে, যখন দ্বিতীয়টি সম্পূর্ণ সেকেন্ড সময় নেয়। যাইহোক, তাদের প্রভাবের যোগফল শেষ ব্যবহারকারীর সাথে একই ধীর মিথস্ক্রিয়া ঘটায়।

এই উদাহরণে এক-সেকেন্ড-দীর্ঘ ইন্টারঅ্যাকশনের একটি জুম-ইন চেহারা, প্রথম ফাংশন কলটি সম্পূর্ণ হতে এক মিলিসেকেন্ডের কম সময় নেয়

কর্মক্ষমতা ট্রেস: বিভিন্ন ইভেন্টের ধরন

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('pointerup', () => {
  blockFor(1000);
});

এই ফলাফল খুব অনুরূপ. মিথস্ক্রিয়া এখনও একটি সম্পূর্ণ সেকেন্ড; একমাত্র পার্থক্য হল ছোট UI-আপডেট-শুধু click লিসেনার এখন ব্লকিং pointerup লিসেনারের পরে চলে।

এই উদাহরণে এক-সেকেন্ড-দীর্ঘ ইন্টারঅ্যাকশনের একটি জুম-ইন লুক, পয়েন্টারআপ শ্রোতার পরে ক্লিক ইভেন্ট লিসেনার সম্পূর্ণ হতে এক মিলিসেকেন্ডেরও কম সময় নেয়।

কর্মক্ষমতা ট্রেস: কোন UI আপডেট নেই

সম্পূর্ণ কোড দেখুন: no_ui.html

button.addEventListener('click', () => {
  blockFor(1000);
  // score.incrementAndUpdateUI();
});
  • স্কোর আপডেট হয় না, কিন্তু পৃষ্ঠা এখনও করে!
  • অ্যানিমেশন, CSS প্রভাব, ডিফল্ট ওয়েব কম্পোনেন্ট অ্যাকশন (ফর্ম ইনপুট), টেক্সট এন্ট্রি, টেক্সট হাইলাইটিং সবই আপডেট হতে থাকে।

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

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

একটি পারফরম্যান্স প্যানেল রেকর্ডিং গ্রহণ করা মিথস্ক্রিয়াটি কার্যত আগেরগুলির সাথে অভিন্ন দেখায়৷

পারফরম্যান্স প্যানেলে এখনও এক-সেকেন্ড-দীর্ঘ মিথস্ক্রিয়া

টেকঅ্যাওয়ে

কোনো ইভেন্ট শ্রোতার মধ্যে চলমান কোনো কোড মিথস্ক্রিয়া বিলম্বিত হবে.

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

এটা একটা সাধারণ সমস্যা!

পরিশেষে: আপনার কোড একটি পেইন্ট ট্রিগার না করার মানে এই নয় যে একটি পেইন্ট ধীর ইভেন্ট শ্রোতাদের সম্পূর্ণ হওয়ার জন্য অপেক্ষা করবে না।

7. পরীক্ষা: ইনপুট বিলম্ব

ইভেন্ট শ্রোতাদের বাইরে দীর্ঘ চলমান কোড সম্পর্কে কী? যেমন:

  • যদি আপনার একটি দেরী-লোডিং <script> থাকে যা লোডের সময় এলোমেলোভাবে পৃষ্ঠাটিকে অবরুদ্ধ করে।
  • একটি API কল, যেমন setInterval , যা পর্যায়ক্রমে পৃষ্ঠাটিকে ব্লক করে?

ইভেন্ট শ্রোতা থেকে blockFor অপসারণ করার চেষ্টা করুন এবং এটি একটি setInterval() এ যোগ করুন :

সম্পূর্ণ কোড দেখুন: input_delay.html

setInterval(() => {
  blockFor(1000);
}, 3000);


button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

কি হয়?

8. ইনপুট বিলম্ব পরীক্ষার ফলাফল

সম্পূর্ণ কোড দেখুন: input_delay.html

setInterval(() => {
  blockFor(1000);
}, 3000);


button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

setInterval ব্লকিং টাস্কটি চলাকালীন একটি বোতাম ক্লিক রেকর্ড করার ফলে একটি দীর্ঘমেয়াদী ইন্টারঅ্যাকশন হয়, এমনকি ইন্টারঅ্যাকশনে কোন ব্লকিং কাজ করা হয় না!

এই দীর্ঘ-চলমান সময়কে প্রায়ই দীর্ঘ কাজ বলা হয়।

DevTools-এ ইন্টারঅ্যাকশনের উপর হোভার করে, আপনি দেখতে সক্ষম হবেন যে ইন্টারঅ্যাকশনের সময়টি এখন প্রাথমিকভাবে ইনপুট বিলম্বের জন্য দায়ী, প্রক্রিয়াকরণের সময়কাল নয়।

DevTools পারফরম্যান্স প্যানেল একটি এক-সেকেন্ড ব্লকিং টাস্ক দেখাচ্ছে, সেই টাস্কের মধ্য দিয়ে আংশিকভাবে একটি ইন্টারঅ্যাকশন আসছে এবং একটি 642 মিলিসেকেন্ড ইন্টারঅ্যাকশন, যা বেশিরভাগ ইনপুট বিলম্বের জন্য দায়ী

লক্ষ্য করুন, এটি সর্বদা মিথস্ক্রিয়াকে প্রভাবিত করে না! টাস্ক চলাকালীন আপনি ক্লিক না করলে, আপনি ভাগ্যবান হতে পারেন। এই ধরনের "এলোমেলো" হাঁচি ডিবাগ করার জন্য একটি দুঃস্বপ্ন হতে পারে যখন তারা শুধুমাত্র কখনও কখনও সমস্যার সৃষ্টি করে।

এইগুলি ট্র্যাক করার একটি উপায় হল দীর্ঘ কাজগুলি (বা দীর্ঘ অ্যানিমেশন ফ্রেমগুলি ) এবং মোট ব্লকিং সময় পরিমাপ করা।

9. ধীর উপস্থাপনা

এখন পর্যন্ত, আমরা ইনপুট বিলম্ব বা ইভেন্ট শ্রোতাদের মাধ্যমে জাভাস্ক্রিপ্টের কর্মক্ষমতা দেখেছি, কিন্তু পরবর্তী পেইন্ট রেন্ডারিংকে আর কী প্রভাবিত করে?

ওয়েল, ব্যয়বহুল প্রভাব সঙ্গে পৃষ্ঠা আপডেট!

এমনকি যদি পৃষ্ঠা আপডেট দ্রুত আসে, তবুও ব্রাউজারকে তাদের রেন্ডার করার জন্য কঠোর পরিশ্রম করতে হতে পারে!

মূল থ্রেডে:

  • UI ফ্রেমওয়ার্ক যা রাষ্ট্র পরিবর্তনের পরে আপডেট রেন্ডার করতে হবে
  • DOM পরিবর্তন, বা অনেক দামী CSS ক্যোয়ারী সিলেক্টর টগল করা অনেক স্টাইল, লেআউট এবং পেইন্টকে ট্রিগার করতে পারে।

মূল থ্রেড বন্ধ:

  • GPU ইফেক্ট পাওয়ার জন্য CSS ব্যবহার করা
  • খুব বড় উচ্চ-রেজোলিউশনের ছবি যোগ করা হচ্ছে
  • জটিল দৃশ্য আঁকতে SVG/Canvas ব্যবহার করে

ওয়েবে রেন্ডারিংয়ের বিভিন্ন উপাদানের স্কেচ

রেন্ডারিংএনজি

কিছু উদাহরণ সাধারণত ওয়েবে পাওয়া যায়:

  • একটি SPA সাইট যেটি একটি লিঙ্কে ক্লিক করার পরে, একটি প্রাথমিক ভিজ্যুয়াল প্রতিক্রিয়া প্রদান না করে সম্পূর্ণ DOM পুনর্নির্মাণ করে৷
  • একটি অনুসন্ধান পৃষ্ঠা যা একটি ডায়নামিক ইউজার ইন্টারফেস সহ জটিল অনুসন্ধান ফিল্টার অফার করে, কিন্তু এটি করার জন্য ব্যয়বহুল শ্রোতাদের চালায়।
  • একটি অন্ধকার মোড টগল যা পুরো পৃষ্ঠার জন্য স্টাইল/লেআউট ট্রিগার করে

10. পরীক্ষা: উপস্থাপনা বিলম্ব

ধীর requestAnimationFrame

requestAnimationFrame() API ব্যবহার করে একটি দীর্ঘ উপস্থাপনা বিলম্ব অনুকরণ করা যাক।

একটি requestAnimationFrame অ্যানিমেশনফ্রেম কলব্যাকে blockFor কলটি সরান যাতে ইভেন্ট শ্রোতা ফিরে আসার পরে এটি চলে:

সম্পূর্ণ কোড দেখুন: presentation_delay.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
  requestAnimationFrame(() => {
    blockFor(1000);
  });
});

কি হয়?

11. উপস্থাপনা বিলম্ব পরীক্ষার ফলাফল

সম্পূর্ণ কোড দেখুন: presentation_delay.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
  requestAnimationFrame(() => {
    blockFor(1000);
  });
});

মিথস্ক্রিয়া একটি সেকেন্ড দীর্ঘ অবশেষ, তাই কি হয়েছে?

requestAnimationFrame পরবর্তী পেইন্টের আগে একটি কলব্যাক অনুরোধ করে। যেহেতু INP ইন্টারঅ্যাকশন থেকে পরবর্তী পেইন্ট পর্যন্ত সময় পরিমাপ করে, তাই requestAnimationFrame blockFor(1000) পুরো সেকেন্ডের জন্য পরবর্তী পেইন্টটিকে ব্লক করতে থাকে।

পারফরম্যান্স প্যানেলে এখনও এক-সেকেন্ড-দীর্ঘ মিথস্ক্রিয়া

যাইহোক, দুটি জিনিস লক্ষ্য করুন:

  • হোভারে, আপনি দেখতে পাবেন সমস্ত মিথস্ক্রিয়া সময় এখন "প্রেজেন্টেশন বিলম্বে" ব্যয় হচ্ছে কারণ ইভেন্ট শ্রোতা ফিরে আসার পরে মূল-থ্রেড ব্লক করা হচ্ছে।
  • মূল-থ্রেড কার্যকলাপের মূলটি আর ক্লিক ইভেন্ট নয়, কিন্তু "অ্যানিমেশন ফ্রেম ফায়ারড"।

12. মিথস্ক্রিয়া নির্ণয়

এই পরীক্ষার পৃষ্ঠায়, স্কোর এবং টাইমার এবং কাউন্টার UI সহ প্রতিক্রিয়াশীলতা অতি দৃশ্যমান...কিন্তু গড় পৃষ্ঠা পরীক্ষা করার সময় এটি আরও সূক্ষ্ম।

যখন মিথস্ক্রিয়া দীর্ঘস্থায়ী হয়, তখন অপরাধী কী তা সবসময় পরিষ্কার হয় না। এটা কি:

  • ইনপুট বিলম্ব?
  • ইভেন্ট প্রক্রিয়াকরণের সময়কাল?
  • উপস্থাপনা বিলম্ব?

আপনি যে কোনো পৃষ্ঠায়, প্রতিক্রিয়াশীলতা পরিমাপ করতে সাহায্য করতে DevTools ব্যবহার করতে পারেন। অভ্যাস পেতে, এই প্রবাহ চেষ্টা করুন:

  1. ওয়েবে নেভিগেট করুন, যেমন আপনি সাধারণত করেন।
  2. ঐচ্ছিক: Web Vitals এক্সটেনশন লগ ইন্টারঅ্যাকশন করার সময় DevTools কনসোল খোলা রেখে দিন।
  3. যদি আপনি একটি খারাপ পারফরম্যান্স দেখান, এটি পুনরাবৃত্তি করার চেষ্টা করুন:
  • আপনি যদি এটি পুনরাবৃত্তি করতে না পারেন, তাহলে অন্তর্দৃষ্টি পেতে কনসোল লগগুলি ব্যবহার করুন৷
  • আপনি যদি এটি পুনরাবৃত্তি করতে পারেন, পারফরম্যান্স প্যানেলে রেকর্ড করুন।

সব বিলম্ব

পৃষ্ঠায় এই সমস্ত সমস্যাগুলির একটি বিট যোগ করার চেষ্টা করুন:

সম্পূর্ণ কোড দেখুন: all_the_things.html

setInterval(() => {
  blockFor(1000);
}, 3000);

button.addEventListener('click', () => {
  blockFor(1000);
  score.incrementAndUpdateUI();

  requestAnimationFrame(() => {
    blockFor(1000);
  });
});

তারপর সমস্যাগুলি নির্ণয় করতে কনসোল এবং কর্মক্ষমতা প্যানেল ব্যবহার করুন!

13. পরীক্ষা: async কাজ

যেহেতু আপনি ইন্টারঅ্যাকশনের মধ্যে অ-ভিজ্যুয়াল ইফেক্ট শুরু করতে পারেন, যেমন নেটওয়ার্ক অনুরোধ করা, টাইমার শুরু করা বা শুধু গ্লোবাল স্টেট আপডেট করা, সেগুলি অবশেষে পৃষ্ঠা আপডেট করলে কী হবে?

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

এটি চেষ্টা করার জন্য, ক্লিক লিসেনার থেকে UI আপডেট করা চালিয়ে যান, তবে টাইমআউট থেকে ব্লক করার কাজটি চালান।

সম্পূর্ণ কোড দেখুন: timeout_100.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();

  setTimeout(() => {
    blockFor(1000);
  }, 100);
});

এখন কি হবে?

14. অ্যাসিঙ্ক কাজের পরীক্ষার ফলাফল

সম্পূর্ণ কোড দেখুন: timeout_100.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();

  setTimeout(() => {
    blockFor(1000);
  }, 100);
});

একটি 27 মিলিসেকেন্ডের ইন্টারঅ্যাকশন একটি এক সেকেন্ডের দীর্ঘ টাস্কের সাথে এখন ট্রেসে পরে ঘটছে৷

ইন্টারঅ্যাকশনটি এখন সংক্ষিপ্ত কারণ মূল থ্রেডটি UI আপডেট হওয়ার পরপরই উপলব্ধ। দীর্ঘ ব্লকিং টাস্ক এখনও চলে, এটি পেইন্টের কিছু পরে চলে, তাই ব্যবহারকারী তাত্ক্ষণিক UI প্রতিক্রিয়া পাবেন।

পাঠ: যদি আপনি এটি সরাতে না পারেন, অন্তত এটি সরান!

পদ্ধতি

আমরা কি একটি নির্দিষ্ট 100 মিলিসেকেন্ড setTimeout চেয়ে ভাল করতে পারি? আমরা সম্ভবত এখনও কোডটি যত তাড়াতাড়ি সম্ভব চালাতে চাই, অন্যথায় আমাদের এটি সরিয়ে ফেলা উচিত ছিল!

লক্ষ্য:

  • ইন্টারঅ্যাকশনটি incrementAndUpdateUI() চালাবে।
  • blockFor() যত তাড়াতাড়ি সম্ভব চালানো হবে, কিন্তু পরবর্তী পেইন্ট ব্লক করবে না।
  • এটি "ম্যাজিক টাইমআউট" ছাড়াই অনুমানযোগ্য আচরণের ফলাফল করে।

এটি সম্পন্ন করার কিছু উপায় জড়িত:

  • setTimeout(0)
  • Promise.then()
  • requestAnimationFrame
  • requestIdleCallback
  • scheduler.postTask()

"অনুরোধ পোস্ট অ্যানিমেশন ফ্রেম"

requestAnimationFrame এর নিজস্ব (যা পরবর্তী পেইন্টের আগে চালানোর চেষ্টা করবে এবং সাধারণত একটি ধীর মিথস্ক্রিয়া তৈরি করবে) এর বিপরীতে, requestAnimationFrame + setTimeout requestPostAnimationFrame জন্য একটি সাধারণ পলিফিল তৈরি করে, পরবর্তী পেইন্টের পরে কলব্যাক চালায়।

সম্পূর্ণ কোড দেখুন: raf+task.html

function afterNextPaint(callback) {
  requestAnimationFrame(() => {
    setTimeout(callback, 0);
  });
}

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();

  afterNextPaint(() => {
    blockFor(1000);
  });
});

ergonomics জন্য, আপনি এমনকি একটি প্রতিশ্রুতি মধ্যে এটি মোড়ানো করতে পারেন:

সম্পূর্ণ কোড দেখুন: raf+task2.html

async function nextPaint() {
  return new Promise(resolve => afterNextPaint(resolve));
}

button.addEventListener('click', async () => {
  score.incrementAndUpdateUI();

  await nextPaint();
  blockFor(1000);
});

15. একাধিক মিথস্ক্রিয়া (এবং রাগ ক্লিক)

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

পৃষ্ঠাটির অ্যাসিঙ্ক ব্লকিং ওয়ার্ক সংস্করণটি আবার চেষ্টা করুন (অথবা আপনি যদি শেষ ধাপে কাজ স্থগিত করার বিষয়ে আপনার নিজস্ব পরিবর্তন নিয়ে আসেন):

সম্পূর্ণ কোড দেখুন: timeout_100.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();

  setTimeout(() => {
    blockFor(1000);
  }, 100);
});

আপনি যদি একাধিকবার দ্রুত ক্লিক করেন তাহলে কী হবে?

কর্মক্ষমতা ট্রেস

প্রতিটি ক্লিকের জন্য, একটি এক-সেকেন্ড-দীর্ঘ টাস্ক সারিবদ্ধ থাকে, নিশ্চিত করে যে মূল থ্রেডটি যথেষ্ট সময়ের জন্য ব্লক করা হয়েছে।

মূল থ্রেডে একাধিক দ্বিতীয়-দীর্ঘ কাজ, যার ফলে মিথস্ক্রিয়া 800ms এর মতো ধীর হয়

যখন সেই দীর্ঘ কাজগুলি নতুন ক্লিকের সাথে ওভারল্যাপ করে, তখন এটি ধীর মিথস্ক্রিয়ায় পরিণত হয় যদিও ইভেন্ট শ্রোতা নিজেই প্রায় সাথে সাথে ফিরে আসে। আমরা ইনপুট বিলম্ব নিয়ে আগের পরীক্ষার মতো একই পরিস্থিতি তৈরি করেছি। শুধুমাত্র এই সময়, ইনপুট বিলম্ব একটি setInterval থেকে আসছে না, কিন্তু আগের ইভেন্ট শ্রোতাদের দ্বারা ট্রিগার করা কাজ থেকে আসছে।

কৌশল

আদর্শভাবে, আমরা দীর্ঘ টাস্ক সম্পূর্ণরূপে অপসারণ করতে চাই!

  • অপ্রয়োজনীয় কোড সম্পূর্ণভাবে সরান-বিশেষ করে স্ক্রিপ্ট।
  • দীর্ঘ কাজ চালানো এড়াতে কোড অপ্টিমাইজ করুন।
  • নতুন মিথস্ক্রিয়া এলে বাসি কাজ বাতিল করুন।

16. কৌশল 1: debounce

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

  • একটি টাইমার সহ, সম্ভবত 500 থেকে 1000 মিলিসেকেন্ড, ব্যয়বহুল কাজ শুরু করতে বিলম্ব করতে setTimeout ব্যবহার করুন।
  • আপনি যখন তা করবেন তখন টাইমার আইডি সংরক্ষণ করুন।
  • যদি একটি নতুন ইন্টারঅ্যাকশন আসে, clearTimeout ব্যবহার করে আগের টাইমারটি বাতিল করুন।

সম্পূর্ণ কোড দেখুন: debounce.html

let timer;
button.addEventListener('click', () => {
  score.incrementAndUpdateUI();

  if (timer) {
    clearTimeout(timer);
  }
  timer = setTimeout(() => {
    blockFor(1000);
  }, 1000);
});

কর্মক্ষমতা ট্রেস

একাধিক মিথস্ক্রিয়া, কিন্তু তাদের সকলের ফলস্বরূপ শুধুমাত্র একটি দীর্ঘ কাজ

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

17. কৌশল 2: দীর্ঘ চলমান কাজকে বাধা দেয়

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

আদর্শভাবে যদি আমাদের কাজের মাঝখানে একটি মিথস্ক্রিয়া আসে, আমরা আমাদের ব্যস্ত কাজকে বিরতি দিতে চাই যাতে যেকোনো নতুন মিথস্ক্রিয়া এখনই পরিচালনা করা হয়। আমরা কিভাবে তা করতে পারি?

কিছু এপিআই আছে যেমন isInputPending , কিন্তু সাধারণত লম্বা কাজগুলোকে খণ্ডে ভাগ করা ভালো

setTimeout প্রচুর

প্রথম প্রচেষ্টা: সহজ কিছু করুন।

সম্পূর্ণ কোড দেখুন: small_tasks.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();

  requestAnimationFrame(() => {
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
    setTimeout(() => blockFor(100), 0);
  });
});

এটি ব্রাউজারকে প্রতিটি কাজকে পৃথকভাবে নির্ধারিত করার অনুমতি দিয়ে কাজ করে এবং ইনপুট উচ্চ অগ্রাধিকার নিতে পারে!

একাধিক মিথস্ক্রিয়া, কিন্তু সমস্ত নির্ধারিত কাজ অনেকগুলি ছোট ছোট কাজের মধ্যে ভেঙে গেছে

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

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

যাইহোক, এই কৌশলটি আঁটসাঁটভাবে-কাপল করা কোড ভাঙ্গার জন্যও কাজ করে না, যেমন লুপের for যা শেয়ার্ড স্টেট ব্যবহার করে।

এখন yield() সহ

যাইহোক, আমরা আধুনিক async লিভারেজ করতে পারি এবং যেকোনো জাভাস্ক্রিপ্ট ফাংশনে সহজেই "ইল্ড পয়েন্ট" যোগ করার জন্য await

যেমন:

সম্পূর্ণ কোড দেখুন: yieldy.html

// Polyfill for scheduler.yield()
async function schedulerDotYield() {
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

async function blockInPiecesYieldy(ms) {
  const ms_per_part = 10;
  const parts = ms / ms_per_part;
  for (let i = 0; i < parts; i++) {
    await schedulerDotYield();

    blockFor(ms_per_part);
  }
}

button.addEventListener('click', async () => {
  score.incrementAndUpdateUI();
  await blockInPiecesYieldy(1000);
});

আগের মতই, মূল থ্রেডটি কিছু কাজ করার পরে পাওয়া যায় এবং ব্রাউজার যেকোনো ইনকামিং ইন্টারঅ্যাকশনের প্রতিক্রিয়া জানাতে সক্ষম হয়, কিন্তু এখন যা প্রয়োজন তা হল পৃথক setTimeout পরিবর্তে একটি await schedulerDotYield() ব্যবহার করার জন্য এটি যথেষ্ট ergonomic করে তোলে লুপের for a এর মাঝখানে।

এখন AbortContoller() এর সাথে

এটি কাজ করেছে, কিন্তু প্রতিটি ইন্টারঅ্যাকশন আরও কাজের সময়সূচী করে, এমনকি যদি নতুন ইন্টারঅ্যাকশন আসে এবং যে কাজটি করা দরকার তা পরিবর্তন করে থাকতে পারে।

ডিবাউন্সিং কৌশলের সাথে, আমরা প্রতিটি নতুন ইন্টারঅ্যাকশনের সাথে আগের টাইমআউট বাতিল করেছি। আমরা এখানে অনুরূপ কিছু করতে পারি? এটি করার একটি উপায় হল একটি AbortController() ব্যবহার করা:

সম্পূর্ণ কোড দেখুন: aborty.html

// Polyfill for scheduler.yield()
async function schedulerDotYield() {
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

async function blockInPiecesYieldyAborty(ms, signal) {
  const parts = ms / 10;
  for (let i = 0; i < parts; i++) {
    // If AbortController has been asked to stop, abandon the current loop.
    if (signal.aborted) return;

    await schedulerDotYield();

    blockFor(10);
  }
}

let abortController = new AbortController();

button.addEventListener('click', async () => {
  score.incrementAndUpdateUI();

  abortController.abort();
  abortController = new AbortController();

  await blockInPiecesYieldyAborty(1000, abortController.signal);
});

যখন একটি ক্লিক আসে, এটি blockInPiecesYieldyAborty চালু করে লুপ করার for যা কিছু কাজ করার সময় পর্যায়ক্রমে মূল থ্রেড প্রদান করে যাতে ব্রাউজারটি নতুন ইন্টারঅ্যাকশনের জন্য প্রতিক্রিয়াশীল থাকে।

যখন একটি দ্বিতীয় ক্লিক আসে, প্রথম লুপটি AbortController এর সাথে বাতিল হিসাবে ফ্ল্যাগ করা হয় এবং একটি নতুন blockInPiecesYieldyAborty লুপ শুরু হয় - পরের বার প্রথম লুপটি আবার চালানোর জন্য নির্ধারিত হয়, এটি লক্ষ্য করে যে signal.aborted এখন true এবং অবিলম্বে ফিরে আসে আরও কাজ করছেন।

মূল থ্রেডের কাজ এখন অনেক ছোট ছোট টুকরোতে রয়েছে, মিথস্ক্রিয়া ছোট, এবং কাজটি যতক্ষণ প্রয়োজন ততক্ষণ স্থায়ী হয়

18. উপসংহার

সমস্ত দীর্ঘ টাস্ক ব্রেক আপ একটি সাইট নতুন মিথস্ক্রিয়া প্রতিক্রিয়াশীল হতে অনুমতি দেয়. এটি আপনাকে দ্রুত প্রাথমিক প্রতিক্রিয়া প্রদান করতে দেয় এবং আপনাকে অগ্রগতির কাজ বাতিল করার মতো সিদ্ধান্ত নিতে দেয়। কখনও কখনও এর অর্থ পৃথক কাজ হিসাবে এন্ট্রি পয়েন্ট নির্ধারণ করা। কখনও কখনও এর অর্থ যেখানে সুবিধাজনক সেখানে "ফলন" পয়েন্ট যোগ করা।

মনে রাখবেন

  • INP সমস্ত মিথস্ক্রিয়া পরিমাপ করে।
  • প্রতিটি মিথস্ক্রিয়া ইনপুট থেকে পরবর্তী পেইন্টে পরিমাপ করা হয়—যেভাবে ব্যবহারকারী প্রতিক্রিয়াশীলতা দেখেন
  • ইনপুট বিলম্ব, ইভেন্ট প্রক্রিয়াকরণের সময়কাল, এবং উপস্থাপনা বিলম্ব সবই মিথস্ক্রিয়া প্রতিক্রিয়াশীলতাকে প্রভাবিত করে।
  • আপনি DevTools দিয়ে সহজেই INP এবং ইন্টারঅ্যাকশন ব্রেকডাউন পরিমাপ করতে পারেন!

কৌশল

  • আপনার পৃষ্ঠাগুলিতে দীর্ঘ-চলমান কোড (দীর্ঘ কাজ) নেই।
  • পরবর্তী পেইন্ট না হওয়া পর্যন্ত ইভেন্ট শ্রোতাদের বাইরে অপ্রয়োজনীয় কোড সরান।
  • নিশ্চিত করুন যে রেন্ডারিং আপডেট নিজেই ব্রাউজারের জন্য দক্ষ।

আরও জানুন