isInputPending() এর সাথে আরও ভাল JS সময়সূচী, isInputPending() এর সাথে ভাল JS সময়সূচী

একটি নতুন JavaScript API যা আপনাকে লোড কর্মক্ষমতা এবং ইনপুট প্রতিক্রিয়াশীলতার মধ্যে ট্রেড-অফ এড়াতে সাহায্য করতে পারে।

Nate Schloss
Nate Schloss
অ্যান্ড্রু কমিনোস
Andrew Comminos

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

এই ট্রেড-অফ করার প্রয়োজনীয়তা দূর করার জন্য, ফলাফল ছাড়াই প্রতিক্রিয়াশীলতা উন্নত করার জন্য Facebook Chromium-এ isInputPending() API-এর প্রস্তাব এবং প্রয়োগ করেছে৷ অরিজিন ট্রায়াল ফিডব্যাকের উপর ভিত্তি করে, আমরা API-তে অনেকগুলি আপডেট করেছি, এবং ঘোষণা করতে পেরে খুশি যে API এখন Chromium 87-এ ডিফল্টরূপে শিপিং করা হচ্ছে!

ব্রাউজার সামঞ্জস্য

ব্রাউজার সমর্থন

  • 87
  • 87
  • এক্স
  • এক্স

87 সংস্করণ থেকে শুরু হওয়া ক্রোমিয়াম-ভিত্তিক ব্রাউজারে isInputPending() পাঠানো হয়েছে৷ অন্য কোনো ব্রাউজার API পাঠানোর অভিপ্রায়ের সংকেত দেয়নি৷

পটভূমি

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

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

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

একটি ডায়াগ্রাম দেখায় যে আপনি যখন দীর্ঘ JS টাস্ক চালান, ব্রাউজারে ইভেন্টগুলি প্রেরণের জন্য কম সময় থাকে।

Facebook-এ, আমরা দেখতে চেয়েছিলাম যে জিনিসগুলি কেমন হবে যদি আমরা লোড করার জন্য একটি নতুন পদ্ধতি নিয়ে আসি যা এই হতাশাজনক বাণিজ্য বন্ধকে দূর করবে৷ আমরা এই বিষয়ে Chrome এ আমাদের বন্ধুদের সাথে যোগাযোগ করেছি এবং isInputPending() এর জন্য প্রস্তাব নিয়ে এসেছি। isInputPending() API হল সর্বপ্রথম ওয়েবে ব্যবহারকারীর ইনপুটগুলির জন্য ইন্টারাপ্টের ধারণাটি ব্যবহার করে, এবং জাভাস্ক্রিপ্টকে ব্রাউজারে ফল না দিয়ে ইনপুট পরীক্ষা করতে সক্ষম করার অনুমতি দেয়।

একটি ডায়াগ্রাম যা দেখাচ্ছে যে isInputPending() আপনার JS কে ব্রাউজারে সম্পূর্ণরূপে এক্সিকিউশন প্রদান না করে, ব্যবহারকারীর ইনপুট মুলতুবি আছে কিনা তা পরীক্ষা করার অনুমতি দেয়।

যেহেতু API-তে আগ্রহ ছিল, তাই আমরা Chromium-এ বৈশিষ্ট্যটি বাস্তবায়ন এবং শিপ করার জন্য Chrome-এ আমাদের সহকর্মীদের সাথে অংশীদারি করেছি। ক্রোম ইঞ্জিনিয়ারদের সাহায্যে, আমরা একটি অরিজিন ট্রায়ালের পিছনে প্যাচগুলি পেয়েছি (যা Chrome এর জন্য পরিবর্তনগুলি পরীক্ষা করার এবং একটি API সম্পূর্ণরূপে প্রকাশ করার আগে বিকাশকারীদের কাছ থেকে প্রতিক্রিয়া পাওয়ার একটি উপায়)৷

আমরা এখন অরিজিন ট্রায়াল এবং W3C ওয়েব পারফরম্যান্স ওয়ার্কিং গ্রুপের অন্যান্য সদস্যদের কাছ থেকে প্রতিক্রিয়া নিয়েছি এবং API-তে পরিবর্তনগুলি বাস্তবায়ন করেছি।

উদাহরণ: একটি ফলনশীল সময়সূচী

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

const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
  if (performance.now() >= DEADLINE) {
    // Yield the event loop if we're out of time.
    setTimeout(processWorkQueue);
    return;
  }
  let job = workQueue.shift();
  job.execute();
}

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

এটা ঠিক আছে, কিন্তু আমরা কি আরও ভাল করতে পারি? একেবারেই!

const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
  if (navigator.scheduling.isInputPending() || performance.now() >= DEADLINE) {
    // Yield if we have to handle an input event, or we're out of time.
    setTimeout(processWorkQueue);
    return;
  }
  let job = workQueue.shift();
  job.execute();
}

navigator.scheduling.isInputPending() এ একটি কল প্রবর্তন করে, আমরা ইনপুটকে দ্রুত সাড়া দিতে সক্ষম হচ্ছি এবং এখনও নিশ্চিত করছি যে আমাদের ডিসপ্লে-ব্লকিং কাজ অন্যথায় নিরবচ্ছিন্নভাবে সম্পাদন করে। কাজ সম্পূর্ণ না হওয়া পর্যন্ত আমরা যদি ইনপুট (যেমন পেইন্টিং) ছাড়া অন্য কিছু পরিচালনা করতে আগ্রহী না হই, তাহলে আমরা সহজেই QUANTUM দৈর্ঘ্য বাড়াতে পারি।

ডিফল্টরূপে, isInputPending() থেকে "অবিচ্ছিন্ন" ইভেন্টগুলি ফেরত দেওয়া হয় না। এর মধ্যে রয়েছে mousemove , pointermove , এবং অন্যান্য। আপনি যদি এইগুলির জন্য ফলন করতে আগ্রহী হন তবে কোন সমস্যা নেই। একটি বস্তু প্রদান করে isInputPending() সহ includeContinuous সেট true , আমরা যেতে ভালো:

const DEADLINE = performance.now() + QUANTUM;
const options = { includeContinuous: true };
while (workQueue.length > 0) {
  if (navigator.scheduling.isInputPending(options) || performance.now() >= DEADLINE) {
    // Yield if we have to handle an input event (any of them!), or we're out of time.
    setTimeout(processWorkQueue);
    return;
  }
  let job = workQueue.shift();
  job.execute();
}

এটাই! রিঅ্যাক্টের মতো ফ্রেমওয়ার্কগুলি অনুরূপ যুক্তি ব্যবহার করে তাদের মূল শিডিউলিং লাইব্রেরিতে isInputPending() সমর্থন তৈরি করছে। আশা করি, এটি এমন ডেভেলপারদের নেতৃত্ব দেবে যারা এই ফ্রেমওয়ার্কগুলি ব্যবহার করে উল্লেখযোগ্য পুনর্লিখন ছাড়াই পর্দার পিছনে isInputPending() থেকে উপকৃত হতে সক্ষম হবে।

ফলন সবসময় খারাপ হয় না

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

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

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

আমরা আপনাকে বিচক্ষণতার সাথে isInputPending() ব্যবহার করতে উত্সাহিত করি। যদি ব্যবহারকারী-অবরুদ্ধ করার কাজ না করা হয়, তাহলে ইভেন্ট লুপে আরও ঘন ঘন ফলন করে অন্যদের প্রতি সদয় হন। দীর্ঘ কাজ ক্ষতিকর হতে পারে

প্রতিক্রিয়া

  • ইজ-ইনপুট-পেন্ডিং রিপোজিটরিতে স্পেক সম্পর্কে মতামত দিন।
  • টুইটারে @acomminos (নির্দিষ্ট লেখকদের একজন) সাথে যোগাযোগ করুন।

উপসংহার

আমরা উত্তেজিত যে isInputPending() চালু হচ্ছে, এবং ডেভেলপাররা আজ এটি ব্যবহার শুরু করতে সক্ষম। এই APIটি প্রথমবার যে Facebook একটি নতুন ওয়েব API তৈরি করেছে এবং এটিকে আইডিয়া ইনকিউবেশন থেকে স্ট্যান্ডার্ড প্রস্তাবে নিয়ে গেছে যা আসলে একটি ব্রাউজারে শিপিং করার জন্য। আমরা তাদের প্রত্যেককে ধন্যবাদ জানাতে চাই যারা আমাদের এই পয়েন্টে পৌঁছাতে সাহায্য করেছে, এবং Chrome-এর প্রত্যেককে একটি বিশেষ চিৎকার দিতে চাই যারা আমাদের এই ধারণাটি বের করতে এবং এটি প্রেরণ করতে সাহায্য করেছে!

আনস্প্ল্যাশে উইল এইচ ম্যাকমাহানের হিরো ছবি।