স্ক্রিপ্ট লোডিং এর ঘোলা জলের গভীরে ডুব দিন

ভূমিকা

এই নিবন্ধে আমি আপনাকে শেখাবো কিভাবে ব্রাউজারে কিছু জাভাস্ক্রিপ্ট লোড করতে হয় এবং এটি চালাতে হয়।

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

প্রারম্ভিকদের জন্য, এখানে স্ক্রিপ্ট ডাউনলোড এবং চালানোর বিভিন্ন উপায়ে স্পেকটি সংজ্ঞায়িত করে:

স্ক্রিপ্ট লোডিং এ WHATWG
স্ক্রিপ্ট লোডিং এ WHATWG

সমস্ত WHATWG স্পেসিক্সের মতো, এটি প্রাথমিকভাবে একটি স্ক্র্যাবল কারখানায় একটি ক্লাস্টার বোমার পরিণতির মতো দেখায়, কিন্তু একবার আপনি এটি 5ম বার পড়ে আপনার চোখ থেকে রক্ত ​​মুছে ফেললে, এটি আসলে বেশ আকর্ষণীয়:

আমার প্রথম স্ক্রিপ্ট অন্তর্ভুক্ত

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

আহ, আনন্দময় সরলতা। এখানে ব্রাউজার সমান্তরালভাবে উভয় স্ক্রিপ্ট ডাউনলোড করবে এবং তাদের ক্রম বজায় রেখে যত তাড়াতাড়ি সম্ভব তাদের কার্যকর করবে। "2.js" কার্যকর হবে না যতক্ষণ না "1.js" কার্যকর হয় (অথবা তা করতে ব্যর্থ হয়), "1.js" কার্যকর হবে না যতক্ষণ না আগের স্ক্রিপ্ট বা স্টাইলশীট কার্যকর না হয়, ইত্যাদি।

দুর্ভাগ্যবশত, ব্রাউজার পৃষ্ঠাটির আরও রেন্ডারিং ব্লক করে যখন এই সব ঘটছে। এটি "ওয়েবের প্রথম যুগ" থেকে DOM API-এর কারণে যা পার্সার যে বিষয়বস্তুর মাধ্যমে চিবিয়ে চলেছে তার সাথে স্ট্রিং যুক্ত করার অনুমতি দেয়, যেমন document.write । নতুন ব্রাউজারগুলি ব্যাকগ্রাউন্ডে ডকুমেন্টটি স্ক্যান বা পার্স করা চালিয়ে যাবে এবং এর প্রয়োজন হতে পারে এমন বাহ্যিক সামগ্রীর জন্য ডাউনলোডগুলি ট্রিগার করবে (js, চিত্র, CSS ইত্যাদি), কিন্তু রেন্ডারিং এখনও অবরুদ্ধ রয়েছে৷

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

ধন্যবাদ IE! (না, আমি ব্যঙ্গ করছি না)

<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>

মাইক্রোসফ্ট এই পারফরম্যান্সের সমস্যাগুলিকে স্বীকৃতি দিয়েছে এবং ইন্টারনেট এক্সপ্লোরার 4-এ "বিলম্বিত" চালু করেছে৷ এটি মূলত বলে "আমি প্রতিশ্রুতি দিচ্ছি যে document.write এর মতো জিনিসগুলি ব্যবহার করে পার্সারে স্টাফ ইনজেক্ট করব না৷ আমি যদি সেই প্রতিশ্রুতি ভঙ্গ করি, তাহলে আপনি যে কোনো উপায়ে আমাকে শাস্তি দিতে স্বাধীন”। এই বৈশিষ্ট্যটি এটিকে HTML4 তে তৈরি করেছে এবং অন্যান্য ব্রাউজারে উপস্থিত হয়েছে৷

উপরের উদাহরণে, ব্রাউজার উভয় স্ক্রিপ্ট সমান্তরালভাবে ডাউনলোড করবে এবং তাদের ক্রম বজায় রেখে DOMContentLoaded ফায়ারের ঠিক আগে সেগুলি চালাবে।

ভেড়ার কারখানায় ক্লাস্টার বোমার মতো, "বিলম্বিত করা" একটি পশম জগাখিচুড়ি হয়ে ওঠে। "src" এবং "defer" বৈশিষ্ট্য এবং স্ক্রিপ্ট ট্যাগ বনাম গতিশীলভাবে যোগ করা স্ক্রিপ্টগুলির মধ্যে, আমাদের কাছে একটি স্ক্রিপ্ট যুক্ত করার 6 টি প্যাটার্ন রয়েছে। অবশ্যই, ব্রাউজারগুলি তাদের কার্যকর করার আদেশে একমত হয়নি। মোজিলা 2009 সালে সমস্যাটির উপর একটি দুর্দান্ত রচনা লিখেছিল

WHATWG আচরণটিকে সুস্পষ্ট করে তুলেছে, "বিলম্বিত" ঘোষণা করে যে স্ক্রিপ্টগুলি গতিশীলভাবে যুক্ত করা হয়েছে বা "src" এর অভাব রয়েছে তার উপর কোন প্রভাব নেই৷ অন্যথায়, স্থগিত স্ক্রিপ্টগুলি দস্তাবেজটি পার্স করার পরে চালানো উচিত, যে ক্রমে সেগুলি যুক্ত করা হয়েছিল।

ধন্যবাদ IE! (ঠিক আছে, এখন আমি ব্যঙ্গ করছি)

এটা দেয়, এটা কেড়ে নেয়. দুর্ভাগ্যবশত IE4-9 এ একটি বাজে বাগ রয়েছে যা স্ক্রিপ্টগুলিকে একটি অপ্রত্যাশিত ক্রমে কার্যকর করতে পারে৷ এখানে যা ঘটে:

1.জেএস

console.log('1');
document.getElementsByTagName('p')[0].innerHTML = 'Changing some content';
console.log('2');

2.জেএস

console.log('3');

পৃষ্ঠায় একটি অনুচ্ছেদ আছে বলে ধরে নিলাম, লগের প্রত্যাশিত ক্রম হল [1, 2, 3], যদিও IE9 এবং নীচে আপনি [1, 3, 2] পাবেন। বিশেষ DOM ক্রিয়াকলাপগুলি IE কে বর্তমান স্ক্রিপ্ট এক্সিকিউশনকে বিরতি দেয় এবং চালিয়ে যাওয়ার আগে অন্যান্য মুলতুবি থাকা স্ক্রিপ্টগুলি কার্যকর করে।

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

উদ্ধারের জন্য HTML5

<script src="//other-domain.com/1.js" async></script>
<script src="2.js" async></script>

HTML5 আমাদের একটি নতুন অ্যাট্রিবিউট দিয়েছে, “async”, যা ধরে নেয় আপনি document.write ব্যবহার করতে যাচ্ছেন না, কিন্তু ডকুমেন্টটি এক্সিকিউট করার জন্য পার্স না হওয়া পর্যন্ত অপেক্ষা করবেন না। ব্রাউজার উভয় স্ক্রিপ্ট সমান্তরালভাবে ডাউনলোড করবে এবং যত তাড়াতাড়ি সম্ভব সেগুলি কার্যকর করবে।

দুর্ভাগ্যবশত, কারণ তারা যত তাড়াতাড়ি সম্ভব কার্যকর করতে যাচ্ছে, "2.js" "1.js" এর আগে কার্যকর হতে পারে। তারা স্বাধীন হলে এটি ঠিক আছে, সম্ভবত "1.js" একটি ট্র্যাকিং স্ক্রিপ্ট যার সাথে "2.js" এর কোনো সম্পর্ক নেই। কিন্তু যদি আপনার “1.js” jQuery-এর একটি CDN কপি হয় যার উপর “2.js” নির্ভর করে, তাহলে আপনার পৃষ্ঠায় ভুল হয়ে যাবে, যেমন একটি ক্লাস্টার-বোমার মতো… আমি জানি না… এর জন্য আমার কাছে কিছুই নেই এইটা.

আমি জানি আমাদের কী দরকার, একটি জাভাস্ক্রিপ্ট লাইব্রেরি!

হোলি গ্রেইলে রেন্ডারিং ব্লক না করেই স্ক্রিপ্টের একটি সেট অবিলম্বে ডাউনলোড করা হচ্ছে এবং যত তাড়াতাড়ি সম্ভব সেগুলি যোগ করা হয়েছে সেই ক্রমে কার্যকর করুন৷ দুর্ভাগ্যবশত HTML আপনাকে ঘৃণা করে এবং আপনাকে তা করতে দেবে না।

সমস্যাটি জাভাস্ক্রিপ্ট দ্বারা কয়েকটি স্বাদে মোকাবেলা করা হয়েছিল। কিছু আপনাকে আপনার জাভাস্ক্রিপ্টে পরিবর্তন করতে হবে, এটিকে একটি কলব্যাকে মোড়ানো যা লাইব্রেরি সঠিক ক্রমে কল করে (যেমন RequireJS )। অন্যরা সমান্তরালে ডাউনলোড করতে XHR ব্যবহার করবে তারপর eval() সঠিক ক্রমে, যা অন্য ডোমেনে স্ক্রিপ্টের জন্য কাজ করে না যদি না তাদের একটি CORS হেডার থাকে এবং ব্রাউজার এটি সমর্থন করে। কেউ কেউ এমনকি ল্যাবজেএস- এর মতো সুপার-ম্যাজিক হ্যাক ব্যবহার করে।

হ্যাকগুলি ব্রাউজারকে এমনভাবে রিসোর্স ডাউনলোড করার জন্য প্রতারণার সাথে জড়িত যা সম্পূর্ণ হওয়ার পরে একটি ইভেন্টকে ট্রিগার করবে, কিন্তু এটি কার্যকর করা এড়িয়ে যাবে। ল্যাবজেএস-এ, স্ক্রিপ্টটি একটি ভুল মাইম টাইপের সাথে যোগ করা হবে, যেমন <script type="script/cache" src="..."> । একবার সমস্ত স্ক্রিপ্ট ডাউনলোড হয়ে গেলে, সেগুলিকে আবার সঠিক টাইপের সাথে যুক্ত করা হবে, আশা করছি ব্রাউজারটি সরাসরি ক্যাশে থেকে সেগুলি নিয়ে আসবে এবং অবিলম্বে সেগুলি কার্যকর করবে। এটি সুবিধাজনক কিন্তু অনির্দিষ্ট আচরণের উপর নির্ভর করে এবং যখন HTML5 ঘোষণা করে যে ব্রাউজারগুলিকে একটি অচেনা ধরনের স্ক্রিপ্ট ডাউনলোড করা উচিত নয় তখন তা ভেঙে যায়। লক্ষণীয় যে ল্যাবজেএস এই পরিবর্তনগুলির সাথে খাপ খাইয়ে নিয়েছে এবং এখন এই নিবন্ধে পদ্ধতিগুলির সংমিশ্রণ ব্যবহার করে৷

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

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

উদ্ধারের জন্য DOM

উত্তরটি আসলে HTML5 স্পেকের মধ্যে রয়েছে, যদিও এটি স্ক্রিপ্ট-লোডিং বিভাগের নীচে লুকানো আছে।

আসুন এটিকে "আর্থলিং"-এ অনুবাদ করি:

[
  '//other-domain.com/1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  document.head.appendChild(script);
});

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

[
  '//other-domain.com/1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

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

উপরের স্ক্রিপ্টটি পৃষ্ঠার মাথায় ইনলাইনে অন্তর্ভুক্ত করা উচিত, প্রগতিশীল রেন্ডারিংকে ব্যাহত না করে যত তাড়াতাড়ি সম্ভব স্ক্রিপ্ট ডাউনলোডগুলি সারিবদ্ধ করা উচিত এবং আপনার নির্দিষ্ট করা ক্রম অনুসারে যত তাড়াতাড়ি সম্ভব কার্যকর করা উচিত। "1.js" এর আগে "2.js" বিনামূল্যে ডাউনলোড করা যায়, কিন্তু "1.js" সফলভাবে ডাউনলোড এবং কার্যকর না হওয়া পর্যন্ত এটি কার্যকর করা হবে না, অথবা করতে ব্যর্থ হয়। হুররাহ! async-ডাউনলোড কিন্তু আদেশ-সম্পাদনা!

Safari 5.0 (5.1 ঠিক আছে) ব্যতীত, এইভাবে স্ক্রিপ্টগুলি লোড করা সমস্ত কিছু দ্বারা সমর্থিত যা async বৈশিষ্ট্য সমর্থন করে । অতিরিক্তভাবে, Firefox এবং Opera-এর সমস্ত সংস্করণগুলি এমন সংস্করণ হিসাবে সমর্থিত যেগুলি async বৈশিষ্ট্য সমর্থন করে না যেগুলি যেভাবেই হোক নথিতে যুক্ত করা হয় সেই ক্রমে গতিশীলভাবে-যুক্ত স্ক্রিপ্টগুলি সহজে কার্যকর করে৷

এটি স্ক্রিপ্ট লোড করার দ্রুততম উপায়? ঠিক?

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

আমরা এটিকে নথির মাথায় রেখে আবিষ্কারযোগ্যতা যোগ করতে পারি:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

এটি ব্রাউজারকে বলে যে পৃষ্ঠাটির প্রয়োজন 1.js এবং 2.js৷ link[rel=subresource] link[rel=prefetch] এর মত, কিন্তু বিভিন্ন শব্দার্থ সহ। দুর্ভাগ্যবশত এটি বর্তমানে শুধুমাত্র Chrome-এ সমর্থিত, এবং আপনাকে ঘোষণা করতে হবে কোন স্ক্রিপ্টগুলি দুবার লোড করতে হবে, একবার লিঙ্ক উপাদানের মাধ্যমে এবং আবার আপনার স্ক্রিপ্টে।

সংশোধন: আমি মূলত বলেছিলাম যে এগুলি প্রিলোড স্ক্যানার দ্বারা বাছাই করা হয়েছিল, সেগুলি নয়, সেগুলি নিয়মিত পার্সার দ্বারা তোলা হয়েছে৷ যাইহোক, প্রিলোড স্ক্যানার এগুলি নিতে পারে , এটি এখনও হয় না, যেখানে এক্সিকিউটেবল কোড দ্বারা অন্তর্ভুক্ত স্ক্রিপ্টগুলি কখনই প্রিলোড করা যায় না। Yoav Weiss কে ধন্যবাদ যিনি আমাকে মন্তব্যে সংশোধন করেছেন।

আমি এই নিবন্ধটি হতাশাজনক খুঁজে

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

<script src="dependencies.js"></script>
<script src="enhancement-1.js"></script>
<script src="enhancement-2.js"></script>
<script src="enhancement-3.js"></script>
…
<script src="enhancement-10.js"></script>

প্রতিটি বর্ধিতকরণ স্ক্রিপ্ট একটি নির্দিষ্ট পৃষ্ঠা উপাদানের সাথে কাজ করে, কিন্তু নির্ভরশীলতা.js-এ ইউটিলিটি ফাংশন প্রয়োজন। আদর্শভাবে আমরা সমস্ত অ্যাসিঙ্ক্রোনাসভাবে ডাউনলোড করতে চাই, তারপর যত তাড়াতাড়ি সম্ভব বর্ধিতকরণ স্ক্রিপ্টগুলি চালাতে চাই, যে কোনও ক্রমে, কিন্তু dependent.js এর পরে। এটা প্রগতিশীল প্রগতিশীল বর্ধন! দুর্ভাগ্যবশত এটি অর্জনের কোনো ঘোষণামূলক উপায় নেই যদি না স্ক্রিপ্টগুলিকে নির্ভরশীলতা.js-এর লোডিং অবস্থা ট্র্যাক করার জন্য পরিবর্তন করা হয়। এমনকি async=false এই সমস্যার সমাধান করে না, কারণ enhancement-10.js কার্যকর করা 1-9 তারিখে ব্লক করবে। আসলে, শুধুমাত্র একটি ব্রাউজার আছে যা হ্যাক ছাড়াই এটি সম্ভব করে তোলে...

IE একটি ধারণা আছে!

IE অন্যান্য ব্রাউজার থেকে ভিন্নভাবে স্ক্রিপ্ট লোড করে।

var script = document.createElement('script');
script.src = 'whatever.js';

IE এখন "whatever.js" ডাউনলোড করা শুরু করে, নথিতে স্ক্রিপ্ট যোগ না করা পর্যন্ত অন্যান্য ব্রাউজার ডাউনলোড করা শুরু করে না। IE এর একটি ইভেন্টও রয়েছে, "readystatechange", এবং সম্পত্তি, "readystate", যা আমাদের লোডিং অগ্রগতি জানায়। এটি আসলে সত্যিই দরকারী, কারণ এটি আমাদের স্বাধীনভাবে স্ক্রিপ্টগুলির লোডিং এবং নির্বাহকে নিয়ন্ত্রণ করতে দেয়।

var script = document.createElement('script');

script.onreadystatechange = function() {
  if (script.readyState == 'loaded') {
    // Our script has download, but hasn't executed.
    // It won't execute until we do:
    document.body.appendChild(script);
  }
};

script.src = 'whatever.js';

নথিতে কখন স্ক্রিপ্ট যোগ করতে হবে তা বেছে নিয়ে আমরা জটিল নির্ভরতা মডেল তৈরি করতে পারি। IE সংস্করণ 6 থেকে এই মডেলটিকে সমর্থন করেছে। বেশ আকর্ষণীয়, কিন্তু এটি এখনও async=false হিসাবে একই প্রিলোডার আবিষ্কারযোগ্যতার সমস্যায় ভুগছে।

যথেষ্ট! আমি কিভাবে স্ক্রিপ্ট লোড করা উচিত?

ঠিক আছে ঠিক আছে. আপনি যদি এমনভাবে স্ক্রিপ্টগুলি লোড করতে চান যাতে রেন্ডারিং ব্লক না হয়, পুনরাবৃত্তি জড়িত না হয় এবং দুর্দান্ত ব্রাউজার সমর্থন থাকে, আমি যা প্রস্তাব করছি তা এখানে:

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

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

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

Eww, আমরা এখন ব্যবহার করতে পারেন ভাল কিছু থাকতে হবে?

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

প্রথমত, আমরা প্রিলোডারদের জন্য সাবরিসোর্স ঘোষণা যোগ করি:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

তারপর, ডকুমেন্টের মাথায় ইনলাইনে, আমরা জাভাস্ক্রিপ্টের সাথে আমাদের স্ক্রিপ্টগুলি লোড করি, async=false ব্যবহার করে, IE-এর রেডিস্টেট-ভিত্তিক স্ক্রিপ্ট লোডিং-এ ফিরে যাই, পিছিয়ে পড়ি।

var scripts = [
  '1.js',
  '2.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we'll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}

কিছু কৌশল এবং পরে ছোট করা, এটি 362 বাইট + আপনার স্ক্রিপ্ট URL:

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])

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

ওফ, এখন আমি জানি কেন WHATWG স্ক্রিপ্ট লোডিং বিভাগটি এত বিশাল। আমি একটি পানীয় প্রয়োজন.

দ্রুত রেফারেন্স

প্লেইন স্ক্রিপ্ট উপাদান

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

স্পেক বলে: একসাথে ডাউনলোড করুন, যেকোনো মুলতুবি থাকা CSS পরে ক্রমানুসারে চালান, সম্পূর্ণ না হওয়া পর্যন্ত রেন্ডারিং ব্লক করুন। ব্রাউজার বলেছেন: হ্যাঁ স্যার!

বিলম্বিত করুন

<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>

স্পেক বলেছেন: একসাথে ডাউনলোড করুন, DOMContentLoaded এর ঠিক আগে ক্রমানুসারে চালান। "src" ছাড়া স্ক্রিপ্টে "defer" উপেক্ষা করুন। IE < 10 বলেছেন: আমি 1.js কার্যকর করার অর্ধেক 2.js কার্যকর করতে পারি। মজা তাই না? লাল রঙের ব্রাউজারগুলি বলে: আমি এই "বিলম্বিত" জিনিসটি কী তা জানি না, আমি স্ক্রিপ্টগুলি এমনভাবে লোড করতে যাচ্ছি যেন এটি সেখানে ছিল না। অন্যান্য ব্রাউজার বলে: ঠিক আছে, কিন্তু আমি "src" ছাড়া স্ক্রিপ্টে "defer" উপেক্ষা করতে পারি না।

অ্যাসিঙ্ক

<script src="//other-domain.com/1.js" async></script>
<script src="2.js" async></script>

স্পেক বলেছেন: একসাথে ডাউনলোড করুন, তারা যে ক্রমে ডাউনলোড করুক না কেন তা চালান। লাল রঙের ব্রাউজারগুলি বলে: 'অ্যাসিঙ্ক' কী? আমি স্ক্রিপ্টগুলি লোড করতে যাচ্ছি যেন এটি সেখানে ছিল না। অন্যান্য ব্রাউজার বলে: হ্যাঁ, ঠিক আছে।

অ্যাসিঙ্ক মিথ্যা

[
  '1.js',
  '2.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

স্পেক বলেছেন: একসাথে ডাউনলোড করুন, সব ডাউনলোডের সাথে সাথেই ক্রমানুসারে চালান। ফায়ারফক্স < 3.6, অপেরা বলেছেন: এই "অ্যাসিঙ্ক" জিনিসটি কী তা আমার কোন ধারণা নেই, তবে এটি ঠিক তাই ঘটে আমি JS-এর মাধ্যমে যোগ করা স্ক্রিপ্টগুলি যে ক্রমানুসারে যুক্ত করা হয় সেভাবে চালাই৷ Safari 5.0 বলেছেন: আমি "async" বুঝি, কিন্তু JS এর ​​সাথে "false" এ সেট করা বুঝতে পারছি না। আমি আপনার স্ক্রিপ্টগুলি যত তাড়াতাড়ি অবতরণ করব, তা যে কোনও ক্রমে কার্যকর করব। IE < 10 বলেছেন: "অ্যাসিঙ্ক" সম্পর্কে কোন ধারণা নেই, তবে "অনরিডিস্টেটচেঞ্জ" ব্যবহার করে একটি সমাধান আছে। লাল রঙের অন্যান্য ব্রাউজার বলে: আমি এই "অ্যাসিঙ্ক" জিনিসটি বুঝতে পারছি না, আমি আপনার স্ক্রিপ্টগুলি যত তাড়াতাড়ি অবতরণ করব, তা যেভাবেই হোক না কেন কার্যকর করব। বাকি সব বলে: আমি আপনার বন্ধু, আমরা বই দ্বারা এটি করতে যাচ্ছি.