প্রকাশিত: ডিসেম্বর 31, 2013
জাভাস্ক্রিপ্ট আমাদের পৃষ্ঠার প্রায় প্রতিটি দিক পরিবর্তন করতে দেয়: বিষয়বস্তু, স্টাইলিং এবং ব্যবহারকারীর মিথস্ক্রিয়ায় এর প্রতিক্রিয়া। যাইহোক, JavaScript DOM নির্মাণকে ব্লক করতে পারে এবং পৃষ্ঠাটি রেন্ডার করার সময় বিলম্ব করতে পারে। সর্বোত্তম কর্মক্ষমতা প্রদান করতে, আপনার জাভাস্ক্রিপ্ট অ্যাসিঙ্ক করুন এবং গুরুত্বপূর্ণ রেন্ডারিং পাথ থেকে যেকোনো অপ্রয়োজনীয় জাভাস্ক্রিপ্ট বাদ দিন।
সারাংশ
- জাভাস্ক্রিপ্ট ডম এবং সিএসএসওএমকে অনুসন্ধান এবং পরিবর্তন করতে পারে।
- CSSOM-এ জাভাস্ক্রিপ্ট এক্সিকিউশন ব্লক করে।
- JavaScript DOM নির্মাণ ব্লক করে যদি না স্পষ্টভাবে async হিসাবে ঘোষণা করা হয়।
জাভাস্ক্রিপ্ট হল একটি গতিশীল ভাষা যা একটি ব্রাউজারে চলে এবং পৃষ্ঠাটি কীভাবে আচরণ করে তার প্রায় প্রতিটি দিক পরিবর্তন করার অনুমতি দেয়: আমরা DOM ট্রি থেকে উপাদান যোগ এবং অপসারণের মাধ্যমে বিষয়বস্তু পরিবর্তন করতে পারি; আমরা প্রতিটি উপাদানের CSSOM বৈশিষ্ট্য পরিবর্তন করতে পারি; আমরা ব্যবহারকারীর ইনপুট পরিচালনা করতে পারি; এবং আরো অনেক কিছু। এটি ব্যাখ্যা করার জন্য, একটি সংক্ষিপ্ত ইনলাইন স্ক্রিপ্ট যোগ করতে পূর্ববর্তী "হ্যালো ওয়ার্ল্ড" উদাহরণটি পরিবর্তন করা হলে কী ঘটে তা দেখুন:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link href="style.css" rel="stylesheet" />
<title>Critical Path: Script</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg" /></div>
<script>
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);
</script>
</body>
</html>
জাভাস্ক্রিপ্ট আমাদের DOM-এ পৌঁছাতে এবং লুকানো স্প্যান নোডের রেফারেন্স বের করতে দেয়; নোডটি রেন্ডার ট্রিতে দৃশ্যমান নাও হতে পারে, তবে এটি এখনও DOM-এ রয়েছে। তারপর, যখন আমাদের কাছে রেফারেন্স থাকে, তখন আমরা এর পাঠ্য (.textContent এর মাধ্যমে) পরিবর্তন করতে পারি এবং এমনকি এর গণনাকৃত ডিসপ্লে শৈলী বৈশিষ্ট্যকে "কোনটি" থেকে "ইনলাইন" এ ওভাররাইড করতে পারি। এখন আমাদের পৃষ্ঠা " হ্যালো ইন্টারেক্টিভ স্টুডেন্টস! " প্রদর্শন করে।
জাভাস্ক্রিপ্ট আমাদের DOM-এ নতুন উপাদান তৈরি, স্টাইল, যোগ এবং অপসারণ করতে দেয়। টেকনিক্যালি, আমাদের পুরো পেজ হতে পারে একটি বড় জাভাস্ক্রিপ্ট ফাইল যা একে একে এলিমেন্ট তৈরি ও স্টাইল করে। যদিও এটি কাজ করবে, বাস্তবে HTML এবং CSS ব্যবহার করা অনেক সহজ। আমাদের জাভাস্ক্রিপ্ট ফাংশনের দ্বিতীয় অংশে আমরা একটি নতুন ডিভ উপাদান তৈরি করি, এর পাঠ্য বিষয়বস্তু সেট করি, স্টাইল করি এবং এটিকে বডিতে যুক্ত করি।
এর সাথে, আমরা একটি বিদ্যমান DOM নোডের বিষয়বস্তু এবং CSS শৈলী পরিবর্তন করেছি এবং নথিতে একটি সম্পূর্ণ নতুন নোড যুক্ত করেছি। আমাদের পৃষ্ঠাটি কোন ডিজাইন পুরষ্কার জিতবে না, তবে এটি জাভাস্ক্রিপ্ট আমাদের যে শক্তি এবং নমনীয়তা প্রদান করে তা চিত্রিত করে।
যাইহোক, যদিও জাভাস্ক্রিপ্ট আমাদের প্রচুর শক্তি দেয়, এটি কীভাবে এবং কখন পৃষ্ঠাটি রেন্ডার করা হয় তার উপর প্রচুর অতিরিক্ত সীমাবদ্ধতা তৈরি করে।
প্রথমত, লক্ষ্য করুন যে আগের উদাহরণে আমাদের ইনলাইন স্ক্রিপ্টটি পৃষ্ঠার নীচের দিকে রয়েছে। কেন? ঠিক আছে, আপনার নিজের চেষ্টা করা উচিত, কিন্তু যদি আমরা স্ক্রিপ্টটিকে <span>
উপাদানের উপরে স্থানান্তরিত করি, আপনি লক্ষ্য করবেন যে স্ক্রিপ্টটি ব্যর্থ হয় এবং অভিযোগ করে যে এটি নথিতে কোনো <span>
উপাদানের রেফারেন্স খুঁজে পাচ্ছে না; অর্থাৎ, getElementsByTagName('span')
null
প্রদান করে। এটি একটি গুরুত্বপূর্ণ সম্পত্তি প্রদর্শন করে: আমাদের স্ক্রিপ্টটি নথিতে যেখানে ঢোকানো হয় ঠিক সেই স্থানেই কার্যকর করা হয়। যখন HTML পার্সার একটি স্ক্রিপ্ট ট্যাগের মুখোমুখি হয়, তখন এটি DOM নির্মাণের প্রক্রিয়াকে বিরতি দেয় এবং জাভাস্ক্রিপ্ট ইঞ্জিনে নিয়ন্ত্রণ প্রদান করে; জাভাস্ক্রিপ্ট ইঞ্জিন চালানো শেষ হওয়ার পর, ব্রাউজারটি সেখান থেকে শুরু করে যেখানে এটি ছেড়েছিল এবং DOM নির্মাণ পুনরায় শুরু করে।
অন্য কথায়, আমাদের স্ক্রিপ্ট ব্লক পৃষ্ঠায় পরে কোনো উপাদান খুঁজে পায় না কারণ সেগুলি এখনও প্রক্রিয়া করা হয়নি! অথবা, একটু ভিন্নভাবে লিখুন: আমাদের ইনলাইন স্ক্রিপ্ট চালানো DOM নির্মাণকে ব্লক করে, যা প্রাথমিক রেন্ডারকেও বিলম্বিত করে।
আমাদের পৃষ্ঠায় স্ক্রিপ্ট প্রবর্তনের আরেকটি সূক্ষ্ম বৈশিষ্ট্য হল যে তারা কেবল DOM নয়, CSSOM বৈশিষ্ট্যগুলিও পড়তে এবং সংশোধন করতে পারে। প্রকৃতপক্ষে, আমরা আমাদের উদাহরণে ঠিক সেটাই করছি যখন আমরা স্প্যান এলিমেন্টের ডিসপ্লে প্রপার্টি নন থেকে ইনলাইনে পরিবর্তন করি। শেষ ফলাফল? আমরা এখন একটি রেস শর্ত আছে.
আমরা যখন আমাদের স্ক্রিপ্ট চালাতে চাই তখন ব্রাউজার CSSOM ডাউনলোড এবং নির্মাণ শেষ না করলে কী হবে? উত্তরটি পারফরম্যান্সের জন্য খুব ভাল নয়: ব্রাউজারটি CSSOM ডাউনলোড এবং নির্মাণ শেষ না হওয়া পর্যন্ত স্ক্রিপ্ট সম্পাদন এবং DOM নির্মাণ বিলম্বিত করে।
সংক্ষেপে, জাভাস্ক্রিপ্ট DOM, CSSOM এবং জাভাস্ক্রিপ্ট এক্সিকিউশনের মধ্যে অনেক নতুন নির্ভরতা প্রবর্তন করে। এটি স্ক্রীনে পৃষ্ঠাটি প্রক্রিয়াকরণ এবং রেন্ডার করতে ব্রাউজারকে উল্লেখযোগ্য বিলম্ব ঘটাতে পারে:
- নথিতে স্ক্রিপ্টের অবস্থান উল্লেখযোগ্য।
- যখন ব্রাউজার একটি স্ক্রিপ্ট ট্যাগের মুখোমুখি হয়, তখন স্ক্রিপ্টটি কার্যকর করা শেষ না হওয়া পর্যন্ত DOM নির্মাণ বিরতি দেয়।
- জাভাস্ক্রিপ্ট ডম এবং সিএসএসওএমকে অনুসন্ধান এবং পরিবর্তন করতে পারে।
- CSSOM প্রস্তুত না হওয়া পর্যন্ত জাভাস্ক্রিপ্ট এক্সিকিউশন বিরতি দেয়।
একটি বড় মাত্রায়, "ক্রিটিকাল রেন্ডারিং পাথ অপ্টিমাইজ করা" বলতে বোঝায় এবং এইচটিএমএল, সিএসএস এবং জাভাস্ক্রিপ্টের মধ্যে নির্ভরতা গ্রাফকে অপ্টিমাইজ করা।
পার্সার ব্লকিং বনাম অ্যাসিঙ্ক্রোনাস জাভাস্ক্রিপ্ট
ডিফল্টরূপে, জাভাস্ক্রিপ্ট এক্সিকিউশন হল "পার্সার ব্লকিং": যখন ব্রাউজারটি ডকুমেন্টে একটি স্ক্রিপ্টের সম্মুখীন হয় তখন এটিকে অবশ্যই DOM নির্মাণকে বিরতি দিতে হবে, জাভাস্ক্রিপ্ট রানটাইমকে নিয়ন্ত্রণ হস্তান্তর করতে হবে এবং DOM নির্মাণের সাথে এগিয়ে যাওয়ার আগে স্ক্রিপ্টটি কার্যকর করতে হবে। আমরা আমাদের আগের উদাহরণে একটি ইনলাইন স্ক্রিপ্টের সাথে এটিকে দেখেছি। প্রকৃতপক্ষে, ইনলাইন স্ক্রিপ্টগুলি সর্বদা পার্সার ব্লক করা হয় যদি না আপনি তাদের সম্পাদন স্থগিত করতে অতিরিক্ত কোড না লেখেন।
স্ক্রিপ্ট ট্যাগ ব্যবহার করে অন্তর্ভুক্ত স্ক্রিপ্ট সম্পর্কে কি? পূর্ববর্তী উদাহরণ নিন এবং একটি পৃথক ফাইলে কোডটি বের করুন:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link href="style.css" rel="stylesheet" />
<title>Critical Path: Script External</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg" /></div>
<script src="app.js"></script>
</body>
</html>
app.js
var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);
আমরা একটি <script> ট্যাগ বা একটি ইনলাইন জাভাস্ক্রিপ্ট স্নিপেট ব্যবহার করি না কেন, আপনি উভয়ই একইভাবে আচরণ করবেন বলে আশা করবেন। উভয় ক্ষেত্রেই, ব্রাউজারটি নথির অবশিষ্টাংশ প্রক্রিয়া করার আগে স্ক্রিপ্টটিকে বিরতি দেয় এবং কার্যকর করে। যাইহোক, একটি বাহ্যিক জাভাস্ক্রিপ্ট ফাইলের ক্ষেত্রে ব্রাউজারটিকে ডিস্ক, ক্যাশে বা রিমোট সার্ভার থেকে স্ক্রিপ্ট আনার জন্য অপেক্ষা করতে বিরতি দিতে হবে, যা ক্রিটিক্যাল রেন্ডারিং পাথে হাজার হাজার মিলিসেকেন্ড বিলম্ব করতে পারে।
ডিফল্টরূপে সমস্ত জাভাস্ক্রিপ্ট পার্সার ব্লকিং। কারণ ব্রাউজার জানে না যে স্ক্রিপ্টটি পৃষ্ঠায় কী করার পরিকল্পনা করছে, এটি সবচেয়ে খারাপ পরিস্থিতি অনুমান করে এবং পার্সারকে ব্লক করে। ব্রাউজারকে একটি সংকেত যে স্ক্রিপ্টটি সঠিক বিন্দুতে কার্যকর করার প্রয়োজন নেই যেখানে এটি উল্লেখ করা হয়েছে ব্রাউজারটিকে DOM তৈরি করা চালিয়ে যেতে দেয় এবং স্ক্রিপ্ট প্রস্তুত হলে এটি কার্যকর করতে দেয়; উদাহরণস্বরূপ, ক্যাশে বা রিমোট সার্ভার থেকে ফাইল আনার পরে।
এটি অর্জন করতে, async
অ্যাট্রিবিউটটি <script>
উপাদানে যোগ করা হয়েছে:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link href="style.css" rel="stylesheet" />
<title>Critical Path: Script Async</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg" /></div>
<script src="app.js" async></script>
</body>
</html>
স্ক্রিপ্ট ট্যাগে অ্যাসিঙ্ক কীওয়ার্ড যুক্ত করা ব্রাউজারকে বলে যে স্ক্রিপ্টটি উপলব্ধ হওয়ার জন্য অপেক্ষা করার সময় DOM নির্মাণ ব্লক না করতে, যা উল্লেখযোগ্যভাবে কর্মক্ষমতা উন্নত করতে পারে।