स्क्रिप्ट के आदेश को लोड और निष्पादित करें


265

HTML पेज में जावास्क्रिप्ट को शामिल करने के लिए बहुत सारे अलग-अलग तरीके हैं। मुझे निम्नलिखित विकल्पों के बारे में पता है:

  • इनलाइन कोड या बाहरी URI से लोड किया गया
  • <head> या <body> टैग [ 1 , 2 ] में शामिल
  • कोई नहीं, deferया asyncविशेषता (केवल बाहरी स्क्रिप्ट)
  • स्थिर लिपियों में शामिल है या अन्य लिपियों द्वारा गतिशील रूप से जोड़ा गया है (अलग-अलग विधियों के साथ, विभिन्न तरीकों से)

हार्डडिस्क, जावास्क्रिप्ट से गणना के onEventलिपियों की गणना नहीं: URIs और -attributes [ 3 ], जेएस निष्पादित होने के लिए पहले से ही 16 विकल्प हैं और मुझे यकीन है कि मैं कुछ भूल गया हूं।

मैं तेज़ (समानांतर) लोडिंग से चिंतित नहीं हूं, मैं निष्पादन आदेश (जो लोडिंग ऑर्डर और दस्तावेज़ ऑर्डर पर निर्भर हो सकता है) के बारे में अधिक उत्सुक हूं । क्या एक अच्छा (क्रॉस-ब्राउज़र) संदर्भ है जो वास्तव में सभी मामलों को कवर करता है? उदाहरण के लिए http://www.websiteoptimization.com/speed/tweak/defer/ केवल उनमें से 6 से संबंधित है, और ज्यादातर पुराने ब्राउज़रों का परीक्षण करता है।

जैसा कि मुझे डर है कि यहां नहीं है, मेरा विशिष्ट प्रश्न है: मुझे प्रारंभिक और स्क्रिप्ट लोड करने के लिए कुछ (बाहरी) हेड स्क्रिप्ट मिली हैं। फिर मुझे शरीर के अंत में दो स्थिर, इनलाइन स्क्रिप्ट मिली हैं। पहले एक स्क्रिप्ट लोडर को गतिशील रूप से दूसरे स्क्रिप्ट तत्व (बाह्य js को संदर्भित करने) को शरीर में जोड़ने की सुविधा देता है। स्थिर, इनलाइन स्क्रिप्ट का दूसरा जोड़ा, बाहरी स्क्रिप्ट से js का उपयोग करना चाहता है। क्या यह दूसरे पर भरोसा किया जा सकता है (और क्यों :-)?


क्या आपने स्टीव सॉडर्स द्वारा ब्लॉक किए बिना लोड हो रहे लिपियों को देखा है ? यह अब थोड़ा सा दिनांकित है, लेकिन फिर भी कुछ विशिष्ट स्क्रिप्ट लोड करने की तकनीक को देखते हुए ब्राउज़र व्यवहार में कुछ मूल्यवान अंतर्दृष्टि शामिल हैं।
जोश हबदास

जवाबों:


331

आप गतिशील रूप से स्क्रिप्ट लोड हो रहा है नहीं कर रहे हैं या उन्हें रूप में चिह्नित करना deferया async, तो स्क्रिप्ट पेज में आई क्रम में लोड किए गए हैं। इससे कोई फर्क नहीं पड़ता कि यह एक बाहरी स्क्रिप्ट या इनलाइन स्क्रिप्ट है - वे पृष्ठ में सामना किए गए क्रम में निष्पादित किए जाते हैं। बाह्य स्क्रिप्ट के बाद आने वाली स्क्रिप्ट्स को तब तक रखा जाता है जब तक कि सभी बाहरी स्क्रिप्ट जो उनके लोड होने और चलने से पहले आई थीं।

Async स्क्रिप्ट्स (इस बात की परवाह किए बिना कि वे Async के रूप में कैसे निर्दिष्ट की जाती हैं) एक अप्रत्याशित क्रम में लोड और चलती हैं। ब्राउज़र उन्हें समानांतर में लोड करता है और इसे जिस भी क्रम में चाहता है, उन्हें चलाने के लिए स्वतंत्र है।

कई async चीजों के बीच कोई अनुमान लगाने योग्य आदेश नहीं है। यदि किसी को पूर्वानुमेय आदेश की आवश्यकता होती है, तो उपयुक्त चीजों को लोड किए जाने पर यह एसिंक्स स्क्रिप्ट से लोड सूचनाओं के लिए रजिस्टर करके और मैन्युअल रूप से जावास्क्रिप्ट कॉल को मैन्युअल रूप से अनुक्रमित करके कोडित करना होगा।

जब एक स्क्रिप्ट टैग गतिशील रूप से डाला जाता है, तो निष्पादन आदेश कैसे व्यवहार करता है यह ब्राउज़र पर निर्भर करेगा। आप देख सकते हैं कि फ़ायरफ़ॉक्स इस संदर्भ लेख में कैसे व्यवहार करता है । संक्षेप में, फ़ायरफ़ॉक्स के नए संस्करणों ने डायनामिक रूप से जोड़े गए स्क्रिप्ट टैग को डिफॉल्ट रूप से डिफ़ॉल्ट किया जब तक कि स्क्रिप्ट टैग अन्यथा सेट नहीं किया गया हो।

asyncलोड होते ही एक स्क्रिप्ट टैग चलाया जा सकता है। वास्तव में, ब्राउज़र उस स्क्रिप्ट को जो कुछ भी कर रहा था, उससे पार्सर को रोक सकता है। तो, यह वास्तव में लगभग किसी भी समय चल सकता है। यदि स्क्रिप्ट को कैश किया गया था, तो यह लगभग तुरंत चल सकता है। यदि स्क्रिप्ट को लोड होने में कुछ समय लगता है, तो यह पार्सर के हो जाने के बाद चल सकता है। इसके साथ याद रखने वाली एक बात asyncयह है कि यह कभी भी चल सकता है और यह समय पूर्वानुमेय नहीं है।

एक स्क्रिप्ट टैग deferतब तक इंतजार करता है जब तक कि पूरा पार्सर नहीं हो जाता है और फिर उनके द्वारा अंकित deferकिए गए क्रम में चिह्नित सभी स्क्रिप्ट चलाता है । यह आपको कई लिपियों को चिह्नित करने की अनुमति देता है जो एक दूसरे पर निर्भर करते हैं defer। दस्तावेज़ पार्सर होने के बाद वे सभी स्थगित हो जाएंगे, लेकिन वे उस क्रम में निष्पादित करेंगे जो उनके आश्रितों को संरक्षित करते हुए सामना किया गया था। मुझे लगता है deferकि स्क्रिप्ट को एक कतार में गिरा दिया जाता है जो पार्सर के बाद संसाधित किया जाएगा। तकनीकी रूप से, ब्राउज़र किसी भी समय पृष्ठभूमि में स्क्रिप्ट डाउनलोड कर रहा हो सकता है, लेकिन जब तक कि पार्सर पृष्ठ को पार्स नहीं कर रहा है और पार्स कर रहा है और चिह्नित नहीं हैं deferया नहीं चला रहा है, तब तक वे पार्सर को निष्पादित या ब्लॉक नहीं करेंगे async

यहाँ उस लेख से एक उद्धरण है:

स्क्रिप्ट-सम्मिलित स्क्रिप्ट IE और WebKit में एसिंक्रोनस रूप से निष्पादित होती है, लेकिन ओपेरा और पूर्व 4.0 फ़ायरफ़ॉक्स में समान रूप से।

HTML5 कल्पना (नए अनुरूप ब्राउज़रों के लिए) का प्रासंगिक हिस्सा यहाँ है । वहाँ बहुत कुछ लिखा है async व्यवहार के बारे में। जाहिर है, यह कल्पना पुराने ब्राउज़रों (या दुर्भावनापूर्ण ब्राउज़रों) पर लागू नहीं होती है जिनके व्यवहार को निर्धारित करने के लिए आपको परीक्षण करना होगा।

HTML5 कल्पना से एक उद्धरण:

फिर, निम्नलिखित विकल्पों में से पहला जो स्थिति का वर्णन करता है उसका पालन किया जाना चाहिए:

यदि तत्व में एक src विशेषता है, और तत्व में एक defer विशेषता है, और तत्व को "पार्सर-सम्मिलित" के रूप में चिह्नित किया गया है, और तत्व में async विशेषता नहीं है । तत्व को सूची की समाप्ति पर जोड़ा जाना चाहिए स्क्रिप्ट जो तब निष्पादित होगी जब दस्तावेज़ ने तत्व बनाने वाले पार्सर के दस्तावेज़ से जुड़े पार्सिंग को समाप्त कर दिया है।

कार्य जो कि कार्य प्रणाली स्रोत पर काम करता है, एक बार जब एल्गोरिथ्म पूरा हो जाता है, तो तत्व को "पार्सर-निष्पादित होने के लिए तैयार" ध्वज को सेट करना होगा। पार्सर स्क्रिप्ट को निष्पादित करने का काम करेगा।

यदि तत्व में एक src विशेषता है, और तत्व को "पार्सर-सम्मिलित" के रूप में चिह्नित किया गया है, और तत्व में एक async विशेषता नहीं है । तत्व तत्व को बनाने वाले पार्सर के दस्तावेज़ की लंबित पार्सिंग-अवरुद्ध स्क्रिप्ट है। (एक बार में प्रति दस्तावेज केवल एक ही स्क्रिप्ट हो सकती है।)

कार्य जो कि कार्य प्रणाली स्रोत पर काम करता है, एक बार जब एल्गोरिथ्म पूरा हो जाता है, तो तत्व को "पार्सर-निष्पादित होने के लिए तैयार" ध्वज को सेट करना होगा। पार्सर स्क्रिप्ट को निष्पादित करने का काम करेगा।

यदि तत्व में src विशेषता नहीं है, और तत्व को "पार्सर-सम्मिलित" के रूप में चिह्नित किया गया है, और स्क्रिप्ट तत्व को बनाने वाले HTML पार्सर या XML पार्सर के दस्तावेज़ में एक स्टाइल शीट है जो स्क्रिप्ट्स को अवरुद्ध कर रहा है जो तत्व है। तत्व को बनाने वाले पार्सर के दस्तावेज़ की लंबित पार्सिंग-अवरुद्ध स्क्रिप्ट। (एक बार में प्रति दस्तावेज केवल एक ही स्क्रिप्ट हो सकती है।)

तत्व के "तैयार होने के लिए पार्सर-निष्पादित" ध्वज सेट करें। पार्सर स्क्रिप्ट को निष्पादित करने का काम करेगा।

यदि तत्व में एक src विशेषता है, एक async विशेषता नहीं है, और "बल-async" ध्वज सेट नहीं है तत्व को स्क्रिप्ट की सूची के अंत में जोड़ा जाना चाहिए जो जितनी जल्दी हो सके निष्पादित होगा स्क्रिप्ट तत्व तैयार करने के समय स्क्रिप्ट लिपि के दस्तावेज के साथ शुरू हुआ।

कार्य जो कि एल्गोरिथ्म पूरा हो जाने पर नेटवर्किंग कार्य स्रोत कार्य पंक्ति पर रखता है, को निम्न चरण चलाने होंगे:

यदि तत्व अब स्क्रिप्ट की सूची में पहला तत्व नहीं है, जो जितनी जल्दी हो सके इसे निष्पादित करेगा, जो ऊपर जोड़ा गया था, तो तत्व को तैयार के रूप में चिह्नित करें लेकिन स्क्रिप्ट को निष्पादित किए बिना इन चरणों को निरस्त करें।

निष्पादन: स्क्रिप्ट की इस सूची में पहले स्क्रिप्ट तत्व के अनुरूप स्क्रिप्ट ब्लॉक निष्पादित करें जो जितनी जल्दी हो सके निष्पादित करेगा।

स्क्रिप्ट की इस सूची से पहला तत्व निकालें, जो जितनी जल्दी हो सके निष्पादित करेगा।

यदि स्क्रिप्ट की यह सूची जो जल्द से जल्द निष्पादित होगी, अभी भी खाली नहीं है और पहली प्रविष्टि पहले से ही तैयार के रूप में चिह्नित की गई है, तो चरण लेबल निष्पादन पर वापस जाएं।

यदि तत्व में एक src विशेषता है , तो तत्व को स्क्रिप्ट के सेट में जोड़ा जाना चाहिए जो स्क्रिप्ट तत्व तैयार करने के समय जितनी जल्दी हो सके स्क्रिप्ट तत्व के दस्तावेज़ को निष्पादित करेगा।

कार्य जो कि नेटवर्किंग कार्य स्रोत कार्य कतार पर एक बार होता है जब एक बार एल्गोरिथ्म पूरा हो जाता है तो स्क्रिप्ट ब्लॉक को निष्पादित करना चाहिए और फिर स्क्रिप्ट के सेट से तत्व को निकालना चाहिए जो जितनी जल्दी हो सके निष्पादित करेगा।

अन्यथा : उपयोगकर्ता एजेंट को स्क्रिप्ट ब्लॉक को तुरंत निष्पादित करना होगा, भले ही अन्य स्क्रिप्ट पहले से ही निष्पादित हो रही हो।


जावास्क्रिप्ट मॉड्यूल स्क्रिप्ट के बारे में क्या type="module"?

जावास्क्रिप्ट में अब इस तरह से सिंटैक्स के साथ लोडिंग मॉड्यूल के लिए समर्थन है:

<script type="module">
  import {addTextToBody} from './utils.mjs';

  addTextToBody('Modules are pretty cool.');
</script>

या, srcविशेषता के साथ :

<script type="module" src="http://somedomain.com/somescript.mjs">
</script>

सभी स्क्रिप्ट के साथ type="module"स्वचालित रूप से deferविशेषता दी जाती है । यह उन्हें पृष्ठ के अन्य लोडिंग के साथ समानांतर (यदि इनलाइन नहीं) में डाउनलोड करता है और फिर उन्हें क्रम में चलाता है, लेकिन पार्सर के बाद किया जाता है।

मॉड्यूल स्क्रिप्ट को वह asyncविशेषता भी दी जा सकती है जो जितनी जल्दी हो सके इनलाइन मॉड्यूल स्क्रिप्ट को चलाएगी, पार्सर के होने तक इंतजार नहीं करेगी और asyncअन्य स्क्रिप्ट के सापेक्ष किसी विशेष क्रम में स्क्रिप्ट को चलाने का इंतजार नहीं करेगी ।

इस लेख में मॉड्यूल स्क्रिप्ट सहित, स्क्रिप्ट के विभिन्न संयोजनों को लाने और निष्पादित करने के लिए एक बहुत ही उपयोगी समयरेखा चार्ट है: जावास्क्रिप्ट मॉड्यूल लोड हो रहा है


उत्तर के लिए धन्यवाद, लेकिन समस्या यह है कि स्क्रिप्ट को गतिशील रूप से पृष्ठ पर जोड़ा जाता है, जिसका अर्थ है कि यह async माना जाता है । या कि केवल <head> में काम करता है? और मेरा अनुभव यह भी है कि वे दस्तावेज़ क्रम में निष्पादित होते हैं?
बरगी २५'१२

@Bergi - यदि यह गतिशील रूप से जोड़ा गया है, तो यह async है और निष्पादन आदेश अनिश्चित है जब तक कि आप इसे नियंत्रित करने के लिए कोड नहीं लिखते हैं।
jfriend00

बस, कोलिंक इसके विपरीत बताता है ...
बरगी

@Bergi - ठीक है, मैंने यह कहने के लिए अपने उत्तर को संशोधित किया है कि async स्क्रिप्ट अनिश्चित क्रम में लोड होती हैं। उन्हें किसी भी क्रम में लोड किया जा सकता है। अगर मैं तुम होते तो मैं कोलिंक के अवलोकन पर भरोसा नहीं करता, जिस तरह से यह हमेशा से है। मैं बिना किसी मानक के जानता हूं जो कहता है कि एक गतिशील रूप से जोड़ी गई स्क्रिप्ट को तुरंत चलाना होगा और अन्य स्क्रिप्ट को लोड होने तक चलने से रोकना होगा। मुझे उम्मीद है कि ब्राउज़र पर निर्भर रहना होगा और शायद पर्यावरणीय कारकों पर भी निर्भर होगा (क्या स्क्रिप्ट कैश की गई है, आदि ...)।
२०

1
@RuudLenders - यह ब्राउज़र कार्यान्वयन पर निर्भर है। दस्तावेज़ में पहले स्क्रिप्ट टैग को एनकाउंटर करना, लेकिन चिह्नित deferकरने से पार्सर को अपना निष्पादन स्थगित करते हुए जल्द ही अपना डाउनलोड शुरू करने का अवसर मिलता है। ध्यान दें कि यदि आपके पास एक ही होस्ट से बहुत सी स्क्रिप्ट हैं, तो जल्द ही डाउनलोड शुरू करना वास्तव में उसी होस्ट से दूसरों के डाउनलोड को धीमा कर सकता है (जैसा कि वे बैंडविड्थ के लिए प्रतिस्पर्धा करते हैं) कि आपका पेज इंतजार कर रहा है (ऐसा नहीं है defer) यह एक दोधारी तलवार हो सकती है।
१६

13

ब्राउज़र स्क्रिप्ट को उसी क्रम में निष्पादित करेगा जिस क्रम में यह उन्हें मिलता है। यदि आप किसी बाहरी स्क्रिप्ट को कॉल करते हैं, तो यह पेज को तब तक ब्लॉक करेगा जब तक स्क्रिप्ट लोड और निष्पादित नहीं हो जाती।

इस तथ्य का परीक्षण करने के लिए:

// file: test.php
sleep(10);
die("alert('Done!');");

// HTML file:
<script type="text/javascript" src="test.php"></script>

दस्तावेज़ में संलग्न होते ही डायनामिक रूप से जोड़े गए स्क्रिप्ट निष्पादित होते हैं।

इस तथ्य का परीक्षण करने के लिए:

<!DOCTYPE HTML>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <script type="text/javascript">
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.src = "link.js"; // file contains alert("hello!");
        document.body.appendChild(s);
        alert("appended");
    </script>
    <script type="text/javascript">
        alert("final");
    </script>
</body>
</html>

अलर्ट का आदेश "संलग्न" है -> "हैलो!" -> "अंतिम"

यदि एक स्क्रिप्ट में आप किसी ऐसे तत्व तक पहुंचने का प्रयास करते हैं जो अभी तक नहीं पहुंचा है (उदाहरण:) <script>do something with #blah</script><div id="blah"></div>तो आपको एक त्रुटि मिलेगी।

कुल मिलाकर, हां आप बाहरी स्क्रिप्ट शामिल कर सकते हैं और फिर उनके कार्यों और चर तक पहुंच सकते हैं, लेकिन केवल तभी जब आप वर्तमान <script>टैग से बाहर निकलते हैं और एक नई शुरुआत करते हैं।


मैं उस व्यवहार की पुष्टि कर सकता हूं। लेकिन हमारे फ़ीडबैक पेजों पर संकेत हैं, कि यह केवल तभी काम कर सकता है जब test.php कैश हो। क्या आप इसके बारे में कोई युक्ति / संदर्भ लिंक जानते हैं?
बेर्गी

4
link.js अवरुद्ध नहीं है। एक लंबे डाउनलोड समय का अनुकरण करने के लिए अपने php के समान एक स्क्रिप्ट का उपयोग करें।
1983

14
यह उत्तर गलत है। यह हमेशा ऐसा नहीं होता है कि "दस्तावेज़ में संलग्न होते ही गतिशील रूप से जोड़ी गई स्क्रिप्ट निष्पादित होती है"। कभी-कभी यह सच होता है (जैसे फ़ायरफ़ॉक्स के पुराने संस्करणों के लिए), लेकिन आमतौर पर ऐसा नहीं है। निष्पादन आदेश, जैसा कि jfriend00 के उत्तर में वर्णित है, निर्धारित नहीं है।
फैबियो बेल्ट्रामिनी

1
यह समझ में नहीं आता कि स्क्रिप्ट पृष्ठ पर दिखाई देने वाले क्रम में बहिष्कृत हैं, भले ही वे इनलाइन हों या न हों। फिर Google टैग प्रबंधक स्निपेट और कई अन्य लोगों को क्यों दिखाई देगा, जिनके पास पृष्ठ में अन्य सभी स्क्रिप्ट टैग के ऊपर एक नई स्क्रिप्ट सम्मिलित करने के लिए कोड है? यह करने के लिए कोई मतलब नहीं होगा, अगर उपरोक्त लिपियों को पहले से ही लोड किया गया है ?? या क्या मैं कुछ न कुछ भूल रहा हूं।
user3094826


2

कई विकल्पों का परीक्षण करने के बाद मैंने पाया है कि निम्नलिखित सरल समाधान उस क्रम में गतिशील रूप से भरी हुई स्क्रिप्ट को लोड कर रहे हैं जिसमें वे सभी आधुनिक ब्राउज़रों में जोड़े गए हैं

loadScripts(sources) {
    sources.forEach(src => {
        var script = document.createElement('script');
        script.src = src;
        script.async = false; //<-- the important part
        document.body.appendChild( script ); //<-- make sure to append to body instead of head 
    });
}

loadScripts(['/scr/script1.js','src/script2.js'])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.