অনেক সাইট এবং অ্যাপে এক্সিকিউট করার জন্য অনেক স্ক্রিপ্ট আছে। আপনার জাভাস্ক্রিপ্ট প্রায়ই যত তাড়াতাড়ি সম্ভব চালানো প্রয়োজন, কিন্তু একই সময়ে আপনি এটি ব্যবহারকারীর পথে পেতে চান না। ব্যবহারকারী যখন পৃষ্ঠাটি স্ক্রোল করছে তখন আপনি যদি বিশ্লেষণ ডেটা পাঠান, বা বোতামে ট্যাপ করার সময় আপনি DOM-এ উপাদান যুক্ত করেন, তাহলে আপনার ওয়েব অ্যাপ প্রতিক্রিয়াহীন হয়ে উঠতে পারে, যার ফলে ব্যবহারকারীর অভিজ্ঞতা খারাপ হতে পারে।
ভাল খবর হল যে এখন একটি API আছে যা সাহায্য করতে পারে: requestIdleCallback
। একইভাবে requestAnimationFrame
গ্রহণ করা আমাদের অ্যানিমেশনগুলিকে সঠিকভাবে সময়সূচী করতে এবং 60fps আঘাত করার সম্ভাবনাকে সর্বাধিক করতে দেয়, ফ্রেমের শেষে ফ্রি সময় থাকলে বা ব্যবহারকারী নিষ্ক্রিয় থাকলে requestIdleCallback
কাজ নির্ধারণ করবে। এর মানে হল যে ব্যবহারকারীর পথে না গিয়ে আপনার কাজ করার সুযোগ রয়েছে৷ এটি Chrome 47 হিসাবে উপলব্ধ, তাই আপনি Chrome ক্যানারি ব্যবহার করে আজ এটিকে একটি ঘূর্ণি দিতে পারেন! এটি একটি পরীক্ষামূলক বৈশিষ্ট্য , এবং বৈশিষ্ট্যটি এখনও প্রবাহিত রয়েছে, তাই ভবিষ্যতে জিনিসগুলি পরিবর্তন হতে পারে৷
কেন আমি requestIdleCallback ব্যবহার করব?
অপ্রয়োজনীয় কাজের সময়সূচী নিজে করা খুব কঠিন। ঠিক কতটা ফ্রেম টাইম বাকি আছে তা বের করা অসম্ভব কারণ requestAnimationFrame
কলব্যাকগুলি কার্যকর করার পরে শৈলী গণনা, লেআউট, পেইন্ট এবং অন্যান্য ব্রাউজার ইন্টারনাল যা চালানো দরকার। একটি হোম-ঘূর্ণিত সমাধান সেগুলির কোনওটির জন্য অ্যাকাউন্ট করতে পারে না। একজন ব্যবহারকারী কোনোভাবে ইন্টারঅ্যাকশন করছে না তা নিশ্চিত করার জন্য আপনাকে শ্রোতাদের প্রতিটি ধরনের ইন্টারঅ্যাকশন ইভেন্টে ( scroll
, touch
, click
) সংযুক্ত করতে হবে, এমনকি যদি আপনার কার্যকারিতার জন্য তাদের প্রয়োজন নাও হয়, ঠিক তাই আপনি নিশ্চিত হতে পারেন যে ব্যবহারকারী ইন্টারঅ্যাক্ট করছে না। অন্যদিকে, ব্রাউজারটি জানে যে ফ্রেমের শেষে কতটা সময় পাওয়া যায় এবং ব্যবহারকারী যদি ইন্টারঅ্যাক্ট করে এবং তাই requestIdleCallback
মাধ্যমে আমরা একটি এপিআই লাভ করি যা আমাদের যেকোন অতিরিক্ত সময়কে সবচেয়ে বেশি ব্যবহার করতে দেয়। কার্যকর উপায় সম্ভব।
আসুন এটিকে আরও বিশদে দেখে নেওয়া যাক এবং আমরা কীভাবে এটি ব্যবহার করতে পারি তা দেখুন।
অনুরোধ আইডলকলব্যাকের জন্য পরীক্ষা করা হচ্ছে
এটি requestIdleCallback
এর প্রথম দিন, তাই এটি ব্যবহার করার আগে আপনার এটি ব্যবহারের জন্য উপলব্ধ কিনা তা পরীক্ষা করা উচিত:
if ('requestIdleCallback' in window) {
// Use requestIdleCallback to schedule work.
} else {
// Do what you’d do today.
}
আপনি এটির আচরণকেও শিম করতে পারেন, যার জন্য setTimeout
ফিরে আসা প্রয়োজন:
window.requestIdleCallback =
window.requestIdleCallback ||
function (cb) {
var start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
}
});
}, 1);
}
window.cancelIdleCallback =
window.cancelIdleCallback ||
function (id) {
clearTimeout(id);
}
setTimeout
ব্যবহার করা দুর্দান্ত নয় কারণ এটি requestIdleCallback
মতো নিষ্ক্রিয় সময় সম্পর্কে জানে না, তবে requestIdleCallback
উপলব্ধ না থাকলে আপনি সরাসরি আপনার ফাংশনকে কল করবেন, তাই আপনি এইভাবে ঝিমঝিম করার থেকে খারাপ কিছু নন। শিমের সাথে, IdleCallback উপলব্ধ হওয়ার requestIdleCallback
করা উচিত, আপনার কলগুলি নীরবে পুনঃনির্দেশিত হবে, যা দুর্দান্ত।
আপাতত, যদিও, অনুমান করা যাক যে এটি বিদ্যমান।
RequestIdleCallback ব্যবহার করে
requestIdleCallback
কল করা requestAnimationFrame
মতোই যে এটি একটি কলব্যাক ফাংশনকে তার প্রথম প্যারামিটার হিসেবে নেয়:
requestIdleCallback(myNonEssentialWork);
যখন myNonEssentialWork
কল করা হয়, তখন এটিকে একটি deadline
অবজেক্ট দেওয়া হবে যাতে একটি ফাংশন থাকে যা আপনার কাজের জন্য কত সময় বাকি আছে তা নির্দেশ করে একটি সংখ্যা প্রদান করে:
function myNonEssentialWork (deadline) {
while (deadline.timeRemaining() > 0)
doWorkIfNeeded();
}
সর্বশেষ মান পেতে timeRemaining
ফাংশন কল করা যেতে পারে। যখন timeRemaining()
শূন্য ফেরত দেয় তখন আপনি অন্য requestIdleCallback
সময় নির্ধারণ করতে পারেন যদি আপনার এখনও আরও কাজ করতে হয়:
function myNonEssentialWork (deadline) {
while (deadline.timeRemaining() > 0 && tasks.length > 0)
doWorkIfNeeded();
if (tasks.length > 0)
requestIdleCallback(myNonEssentialWork);
}
আপনার ফাংশন গ্যারান্টি বলা হয়
জিনিসগুলি সত্যিই ব্যস্ত থাকলে আপনি কী করবেন? আপনি উদ্বিগ্ন হতে পারেন যে আপনার কলব্যাক কখনই কল করা যাবে না। ঠিক আছে, যদিও requestIdleCallback
অনুরূপ requestAnimationFrame
, এটি একটি ঐচ্ছিক দ্বিতীয় পরামিতি লাগে: একটি টাইমআউট বৈশিষ্ট্য সহ একটি বিকল্প অবজেক্টের মধ্যেও পার্থক্য। এই টাইমআউট, যদি সেট করা থাকে, ব্রাউজারকে মিলিসেকেন্ডে একটি সময় দেয় যার মাধ্যমে এটি কলব্যাকটি চালাতে হবে:
// Wait at most two seconds before processing events.
requestIdleCallback(processPendingAnalyticsEvents, { timeout: 2000 });
টাইমআউট ফায়ারিংয়ের কারণে যদি আপনার কলব্যাকটি কার্যকর করা হয় তবে আপনি দুটি জিনিস লক্ষ্য করবেন:
-
timeRemaining()
শূন্য রিটার্ন করবে। -
deadline
অবজেক্টেরdidTimeout
সম্পত্তি সত্য হবে।
আপনি যদি দেখেন যে didTimeout
সত্য, আপনি সম্ভবত কাজটি চালাতে চান এবং এটি দিয়ে সম্পন্ন করতে চান:
function myNonEssentialWork (deadline) {
// Use any remaining time, or, if timed out, just run through the tasks.
while ((deadline.timeRemaining() > 0 || deadline.didTimeout) &&
tasks.length > 0)
doWorkIfNeeded();
if (tasks.length > 0)
requestIdleCallback(myNonEssentialWork);
}
সম্ভাব্য ব্যাঘাতের কারণে এই টাইমআউট আপনার ব্যবহারকারীদের (কাজের কারণে আপনার অ্যাপটি প্রতিক্রিয়াশীল বা অপ্রীতিকর হয়ে উঠতে পারে) এই প্যারামিটার সেট করার ক্ষেত্রে সতর্ক থাকুন। আপনি যেখানে পারেন, ব্রাউজারকে সিদ্ধান্ত নিতে দিন কখন কলব্যাক করতে হবে।
বিশ্লেষণ ডেটা পাঠানোর জন্য requestIdleCallback ব্যবহার করে
অ্যানালিটিক্স ডেটা পাঠাতে requestIdleCallback
ব্যবহার করে দেখে নেওয়া যাক। এই ক্ষেত্রে, আমরা সম্ভবত একটি ইভেন্ট ট্র্যাক করতে চাই যেমন -- বলুন -- একটি নেভিগেশন মেনুতে ট্যাপ করা। যাইহোক, যেহেতু তারা সাধারণত স্ক্রিনে অ্যানিমেট করে, তাই আমরা অবিলম্বে এই ইভেন্টটি Google Analytics-এ পাঠানো এড়াতে চাই। আমরা পাঠাব এবং অনুরোধ করার জন্য ইভেন্টের একটি বিন্যাস তৈরি করব যাতে ভবিষ্যতে কোনও সময়ে সেগুলি পাঠানো হয়:
var eventsToSend = [];
function onNavOpenClick () {
// Animate the menu.
menu.classList.add('open');
// Store the event for later.
eventsToSend.push(
{
category: 'button',
action: 'click',
label: 'nav',
value: 'open'
});
schedulePendingEvents();
}
এখন আমাদের যেকোনো মুলতুবি ইভেন্ট প্রক্রিয়া করার জন্য requestIdleCallback
ব্যবহার করতে হবে:
function schedulePendingEvents() {
// Only schedule the rIC if one has not already been set.
if (isRequestIdleCallbackScheduled)
return;
isRequestIdleCallbackScheduled = true;
if ('requestIdleCallback' in window) {
// Wait at most two seconds before processing events.
requestIdleCallback(processPendingAnalyticsEvents, { timeout: 2000 });
} else {
processPendingAnalyticsEvents();
}
}
এখানে আপনি দেখতে পাচ্ছেন যে আমি 2 সেকেন্ডের একটি টাইমআউট সেট করেছি, তবে এই মানটি আপনার অ্যাপ্লিকেশনের উপর নির্ভর করবে। অ্যানালিটিক্স ডেটার জন্য, এটি বোঝায় যে ভবিষ্যতের কোনো সময়ে ডেটার পরিবর্তে যুক্তিসঙ্গত সময়সীমার মধ্যে ডেটা রিপোর্ট করা নিশ্চিত করতে একটি টাইমআউট ব্যবহার করা হবে।
অবশেষে আমাদের যে ফাংশনটি requestIdleCallback
এক্সিকিউট করবে তা লিখতে হবে।
function processPendingAnalyticsEvents (deadline) {
// Reset the boolean so future rICs can be set.
isRequestIdleCallbackScheduled = false;
// If there is no deadline, just run as long as necessary.
// This will be the case if requestIdleCallback doesn’t exist.
if (typeof deadline === 'undefined')
deadline = { timeRemaining: function () { return Number.MAX_VALUE } };
// Go for as long as there is time remaining and work to do.
while (deadline.timeRemaining() > 0 && eventsToSend.length > 0) {
var evt = eventsToSend.pop();
ga('send', 'event',
evt.category,
evt.action,
evt.label,
evt.value);
}
// Check if there are more events still to send.
if (eventsToSend.length > 0)
schedulePendingEvents();
}
এই উদাহরণের জন্য আমি অনুমান করেছি যে যদি requestIdleCallback
বিদ্যমান না থাকে তবে বিশ্লেষণ ডেটা অবিলম্বে পাঠানো উচিত। একটি প্রোডাকশন অ্যাপ্লিকেশানে, যাইহোক, এটি কোনও ইন্টারঅ্যাকশনের সাথে বিরোধ না করে এবং জ্যাঙ্ক সৃষ্টি করে না তা নিশ্চিত করার জন্য একটি টাইমআউট সহ পাঠাতে বিলম্ব করা ভাল হবে।
DOM পরিবর্তন করতে requestIdleCallback ব্যবহার করে
আরেকটি পরিস্থিতি যেখানে requestIdleCallback
কার্যক্ষমতাকে সত্যিই সাহায্য করতে পারে তা হল যখন আপনার কাছে অ-প্রয়োজনীয় DOM পরিবর্তনগুলি থাকে, যেমন একটি ক্রমবর্ধমান, অলস-লোড করা তালিকার শেষে আইটেম যোগ করা। আসুন দেখি কিভাবে requestIdleCallback
একটি সাধারণ ফ্রেমে ফিট করে।
এটা সম্ভব যে ব্রাউজারটি একটি প্রদত্ত ফ্রেমে কলব্যাক চালানোর জন্য খুব ব্যস্ত থাকবে, তাই আপনার আশা করা উচিত নয় যে ফ্রেমের শেষে আর কোন কাজ করার জন্য কোন অবসর সময় থাকবে। এটি setImmediate
মত কিছু থেকে আলাদা করে তোলে, যা প্রতি ফ্রেমে চলে ।
যদি ফ্রেমের শেষে কলব্যাক ফায়ার করা হয় , তবে বর্তমান ফ্রেমটি প্রতিশ্রুতিবদ্ধ হওয়ার পরে এটি যাওয়ার জন্য নির্ধারিত হবে, যার মানে শৈলী পরিবর্তনগুলি প্রয়োগ করা হবে এবং, গুরুত্বপূর্ণভাবে, লেআউট গণনা করা হবে৷ যদি আমরা নিষ্ক্রিয় কলব্যাকের ভিতরে DOM পরিবর্তন করি, তাহলে সেই বিন্যাস গণনাগুলি অবৈধ হয়ে যাবে। যদি পরবর্তী ফ্রেমে কোনো ধরনের লেআউট পড়ে থাকে, যেমন getBoundingClientRect
, clientWidth
, ইত্যাদি, ব্রাউজারটিকে একটি ফোর্সড সিঙ্ক্রোনাস লেআউট সঞ্চালন করতে হবে, যা একটি সম্ভাব্য কর্মক্ষমতা বাধা।
নিষ্ক্রিয় কলব্যাকে DOM পরিবর্তনগুলি ট্রিগার না করার আরেকটি কারণ হল DOM পরিবর্তনের সময় প্রভাব অপ্রত্যাশিত, এবং এর ফলে আমরা ব্রাউজার প্রদত্ত সময়সীমা অতিক্রম করতে পারি।
সর্বোত্তম অভ্যাস হল শুধুমাত্র একটি requestAnimationFrame
কলব্যাকের ভিতরে DOM পরিবর্তন করা, যেহেতু এটি ব্রাউজার দ্বারা এই ধরনের কাজের কথা মাথায় রেখে নির্ধারিত হয়। এর মানে হল যে আমাদের কোডটিকে একটি নথির খণ্ড ব্যবহার করতে হবে, যা পরবর্তী requestAnimationFrame
কলব্যাকে যুক্ত করা যেতে পারে। আপনি যদি একটি VDOM লাইব্রেরি ব্যবহার করেন, তাহলে আপনি পরিবর্তন করতে requestIdleCallback
ব্যবহার করবেন, কিন্তু আপনি পরবর্তী requestAnimationFrame
কলব্যাকে DOM প্যাচ প্রয়োগ করবেন , নিষ্ক্রিয় কলব্যাকে নয়।
তাই এটি মাথায় রেখে, আসুন কোডটি একবার দেখে নেওয়া যাক:
function processPendingElements (deadline) {
// If there is no deadline, just run as long as necessary.
if (typeof deadline === 'undefined')
deadline = { timeRemaining: function () { return Number.MAX_VALUE } };
if (!documentFragment)
documentFragment = document.createDocumentFragment();
// Go for as long as there is time remaining and work to do.
while (deadline.timeRemaining() > 0 && elementsToAdd.length > 0) {
// Create the element.
var elToAdd = elementsToAdd.pop();
var el = document.createElement(elToAdd.tag);
el.textContent = elToAdd.content;
// Add it to the fragment.
documentFragment.appendChild(el);
// Don't append to the document immediately, wait for the next
// requestAnimationFrame callback.
scheduleVisualUpdateIfNeeded();
}
// Check if there are more events still to send.
if (elementsToAdd.length > 0)
scheduleElementCreation();
}
এখানে আমি উপাদান তৈরি করি এবং এটিকে পপুলেট করার জন্য textContent
সম্পত্তি ব্যবহার করি, তবে আপনার উপাদান তৈরির কোড আরও জড়িত হওয়ার সম্ভাবনা রয়েছে! উপাদানের scheduleVisualUpdateIfNeeded
কল করা হয়, যা একটি একক requestAnimationFrame
কলব্যাক সেট আপ করবে যা পরিবর্তে, নথির খণ্ডটি শরীরে যুক্ত করবে:
function scheduleVisualUpdateIfNeeded() {
if (isVisualUpdateScheduled)
return;
isVisualUpdateScheduled = true;
requestAnimationFrame(appendDocumentFragment);
}
function appendDocumentFragment() {
// Append the fragment and reset.
document.body.appendChild(documentFragment);
documentFragment = null;
}
সবকিছু ঠিক আছে, আমরা এখন DOM-এ আইটেম যুক্ত করার সময় অনেক কম জ্যাঙ্ক দেখতে পাব। চমৎকার!
FAQ
- একটি পলিফিল আছে? দুঃখজনকভাবে নয়, তবে আপনি যদি
setTimeout
একটি স্বচ্ছ পুনঃনির্দেশ করতে চান তবে একটি শিম আছে । এই APIটির অস্তিত্বের কারণ হল এটি ওয়েব প্ল্যাটফর্মে একটি খুব বাস্তব ফাঁক প্লাগ করে। ক্রিয়াকলাপের অভাব অনুমান করা কঠিন, তবে ফ্রেমের শেষে ফাঁকা সময়ের পরিমাণ নির্ধারণ করার জন্য কোনও জাভাস্ক্রিপ্ট এপিআই বিদ্যমান নেই, তাই সর্বোত্তমভাবে আপনাকে অনুমান করতে হবে।setTimeout
,setInterval
, বাsetImmediate
মতো APIগুলি কাজের সময় নির্ধারণের জন্য ব্যবহার করা যেতে পারে, কিন্তু ব্যবহারকারীর ইন্টারঅ্যাকশন এড়ানোর জন্য সেগুলিকেrequestIdleCallback
মতো সময় দেওয়া হয় না৷ - আমি সময়সীমা অতিক্রম করলে কি হবে? যদি
timeRemaining()
শূন্য ফেরত দেয়, কিন্তু আপনি দীর্ঘ সময়ের জন্য চালানোর জন্য বেছে নেন, আপনি ব্রাউজার আপনার কাজ বন্ধ করার ভয় ছাড়াই তা করতে পারেন। যাইহোক, ব্রাউজারটি আপনাকে চেষ্টা করার সময়সীমা দেয় এবং আপনার ব্যবহারকারীদের জন্য একটি মসৃণ অভিজ্ঞতা নিশ্চিত করার জন্য, তাই খুব ভাল কারণ না থাকলে, আপনার সর্বদা সময়সীমা মেনে চলা উচিত। - সর্বোচ্চ মান আছে যে
timeRemaining()
ফিরে আসবে? হ্যাঁ, এটি বর্তমানে 50ms। একটি প্রতিক্রিয়াশীল অ্যাপ্লিকেশন বজায় রাখার চেষ্টা করার সময়, ব্যবহারকারীর ইন্টারঅ্যাকশনের সমস্ত প্রতিক্রিয়া 100ms এর নিচে রাখা উচিত। ব্যবহারকারী যদি 50ms উইন্ডোতে ইন্টারঅ্যাক্ট করেন, বেশিরভাগ ক্ষেত্রে, নিষ্ক্রিয় কলব্যাক সম্পূর্ণ করার জন্য এবং ব্রাউজারটিকে ব্যবহারকারীর ইন্টারঅ্যাকশনে সাড়া দেওয়ার অনুমতি দেওয়া উচিত। আপনি একাধিক নিষ্ক্রিয় কলব্যাক ব্যাক-টু-ব্যাক নির্ধারিত পেতে পারেন (যদি ব্রাউজার নির্ধারণ করে যে সেগুলি চালানোর জন্য যথেষ্ট সময় আছে)। - রিকোয়েস্ট আইডলকলব্যাকে কি এমন কোন কাজ আছে যা আমার করা উচিত নয়? আদর্শভাবে আপনি যে কাজটি করেন তা ছোট খণ্ডে (মাইক্রোটাস্ক) হওয়া উচিত যার তুলনামূলকভাবে অনুমানযোগ্য বৈশিষ্ট্য রয়েছে। উদাহরণস্বরূপ, বিশেষ করে DOM পরিবর্তন করার সময় অপ্রত্যাশিত এক্সিকিউশন সময় থাকবে, কারণ এটি শৈলী গণনা, লেআউট, পেইন্টিং এবং কম্পোজিটিংকে ট্রিগার করবে। যেমন আপনি উপরে প্রস্তাবিত হিসাবে শুধুমাত্র একটি
requestAnimationFrame
কলব্যাক DOM পরিবর্তন করা উচিত. আরেকটা বিষয়ে সতর্ক থাকতে হবে তা হল প্রতিশ্রুতি সমাধান করা (বা প্রত্যাখ্যান করা), কারণ নিষ্ক্রিয় কলব্যাক শেষ হওয়ার সাথে সাথেই কলব্যাকগুলি কার্যকর হবে, এমনকি যদি আর বেশি সময় না থাকে। - আমি কি সবসময় একটি ফ্রেমের শেষে একটি
requestIdleCallback
পাব? না, সবসময় নয়। ব্রাউজারটি যখনই একটি ফ্রেমের শেষে অবসর সময় থাকে বা ব্যবহারকারী নিষ্ক্রিয় থাকে এমন সময়কালে কলব্যাকের সময় নির্ধারণ করবে। আপনার প্রতি ফ্রেমে কলব্যাক কল করার আশা করা উচিত নয়, এবং যদি আপনার এটি একটি নির্দিষ্ট সময়সীমার মধ্যে চালানোর প্রয়োজন হয় তবে আপনাকে টাইমআউট ব্যবহার করা উচিত। - আমি কি একাধিক
requestIdleCallback
কলব্যাক করতে পারি? হ্যাঁ, আপনি করতে পারেন, আপনার একাধিকrequestAnimationFrame
কলব্যাক থাকতে পারে। যদিও এটা মনে রাখা যোগ্য যে, যদি আপনার প্রথম কলব্যাক তার কলব্যাকের সময় অবশিষ্ট সময় ব্যবহার করে তাহলে অন্য কোনো কলব্যাকের জন্য আর বেশি সময় থাকবে না। অন্যান্য কলব্যাকগুলি চালানোর আগে ব্রাউজারটি পরবর্তী নিষ্ক্রিয় না হওয়া পর্যন্ত অপেক্ষা করতে হবে। আপনি যে কাজটি সম্পন্ন করার চেষ্টা করছেন তার উপর নির্ভর করে, একটি একক নিষ্ক্রিয় কলব্যাক থাকা এবং সেখানে কাজটি ভাগ করা ভাল হতে পারে। বিকল্পভাবে আপনি টাইমআউট ব্যবহার করতে পারেন যাতে কোনো কলব্যাক সময়ের জন্য ক্ষুধার্ত না হয়। - আমি যদি অন্যের ভিতরে একটি নতুন নিষ্ক্রিয় কলব্যাক সেট করি তাহলে কি হবে? নতুন নিষ্ক্রিয় কলব্যাক যত তাড়াতাড়ি সম্ভব চালানোর জন্য নির্ধারিত হবে, পরবর্তী ফ্রেম থেকে শুরু করে (বর্তমানের পরিবর্তে)।
নিষ্ক্রিয়!
আপনি আপনার কোড চালাতে পারেন তা নিশ্চিত করার জন্য requestIdleCallback
একটি দুর্দান্ত উপায়, কিন্তু ব্যবহারকারীর পথে না গিয়ে। এটি ব্যবহার করা সহজ, এবং খুব নমনীয়। এটি এখনও প্রাথমিক দিন, যদিও, এবং স্পেক সম্পূর্ণরূপে নিষ্পত্তি করা হয়নি, তাই আপনার কোন প্রতিক্রিয়া স্বাগত জানাই।
Chrome ক্যানারিতে এটি পরীক্ষা করে দেখুন, এটিকে আপনার প্রকল্পগুলির জন্য একটি স্পিন দিন এবং আপনি কীভাবে এগিয়ে যাচ্ছেন তা আমাদের জানান!