অসীম স্ক্রলারের জটিলতা

TL;DR: আপনার DOM উপাদানগুলিকে পুনরায় ব্যবহার করুন এবং ভিউপোর্ট থেকে দূরে থাকাগুলিকে সরিয়ে দিন। বিলম্বিত ডেটার জন্য অ্যাকাউন্টে স্থানধারক ব্যবহার করুন। এখানে একটি ডেমো এবং অসীম স্ক্রলারের কোড

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

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

সঠিক জিনিস™

আমরা ভেবেছিলাম যে এটি একটি রেফারেন্স বাস্তবায়নের সাথে আসা যথেষ্ট কারণ যা পারফরম্যান্সের মান বজায় রেখে পুনরায় ব্যবহারযোগ্য উপায়ে এই সমস্ত সমস্যাগুলি মোকাবেলা করার উপায় দেখায়।

আমরা আমাদের লক্ষ্য অর্জনের জন্য 3টি কৌশল ব্যবহার করতে যাচ্ছি: DOM রিসাইক্লিং, সমাধির পাথর এবং স্ক্রোল অ্যাঙ্করিং।

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

চ্যাট অ্যাপের স্ক্রিনশট

DOM পুনর্ব্যবহারযোগ্য

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

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

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

রানওয়ে সেন্টিনেল ভিউপোর্ট

একই অন্য দিকে স্ক্রোলিং জন্য যায়. যাইহোক, আমরা আমাদের বাস্তবায়নে রানওয়ে কখনই সঙ্কুচিত করব না, যাতে স্ক্রলবারের অবস্থানটি সামঞ্জস্যপূর্ণ থাকে।

সমাধি পাথর

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

এমন সমাধি। খুব পাথর। কি দারুন.

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

স্ক্রোল অ্যাঙ্করিং

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

স্ক্রোল অ্যাঙ্করিং ডায়াগ্রাম।

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

লেআউট

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

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

রক্তপাত-প্রান্তের tweaks

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

আরেকটি বিষয় যা আমরা বিবেচনা করেছি তা হল IntersectionObservers একটি প্রক্রিয়া হিসাবে ব্যবহার করা হচ্ছে যখন ব্যবহারকারী আমাদের উপাদানগুলি পুনর্ব্যবহার করা শুরু করতে এবং নতুন ডেটা লোড করার জন্য যথেষ্ট স্ক্রোল করেছে তা সনাক্ত করার জন্য৷ যাইহোক, IntersectionObservers উচ্চ লেটেন্সি হিসেবে নির্দিষ্ট করা হয়েছে (যেমন requestIdleCallback ব্যবহার করছে), তাই আমরা আসলে IntersectionObservers এর চেয়ে কম প্রতিক্রিয়াশীল বোধ করতে পারি। এমনকি scroll ইভেন্ট ব্যবহার করে আমাদের বর্তমান বাস্তবায়নও এই সমস্যায় ভুগছে, কারণ স্ক্রোল ইভেন্টগুলি "সর্বোত্তম প্রচেষ্টা" ভিত্তিতে পাঠানো হয়। অবশেষে, Houdini এর কম্পোজিটর ওয়ার্কলেট এই সমস্যার উচ্চ বিশ্বস্ততা সমাধান হবে।

এটা এখনও নিখুঁত নয়

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

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

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