IlmHamroh
JavaScript Full-stack/4-qism. HTML68/86-dars18 daqiqa
Mundarija (36)

HTML script tegi: defer, async va module bilan skriptlarni to'g'ri ulash

Qisqacha: Oddiy <script src="..."> tegida brauzer HTML o'qishni to'xtatadi va skript yuklanib bajarilishini kutadi. Atribut defer skriptni fonda yuklaydi va HTML to'liq o'qilgach, yozilgan tartibda bajaradi. Atribut async ham fonda yuklaydi, lekin yuklanishi bilanoq, tartibsiz bajaradi. Modul skript (type="module") o'zini defer kabi tutadi. Sahifaga bog'liq skriptlar uchun odatiy tanlov — head ichida defer.

Bu darsda

  • script tegi bilan tashqi va ichki skriptni ulay olasiz.
  • Oddiy skript, defer, async va type="module" qachon yuklanib, qachon bajarilishini diagrammada tushuntirasiz.
  • Har bir vaziyat uchun to'g'ri atributni tanlaysiz.
  • importmap, nomodule va noscript nima uchun kerakligini bilasiz.
  • Begona serverdagi skriptni integrity bilan himoya qilasiz.

Oldin bilishingiz kerak: head anatomiyasi va viewport, Renderni nima to'xtatadi, Brauzer HTML'ni qanday tahlil qiladi, Kam ma'lum, lekin foydali meta teglar.

1. Nega bu kerak?

«Bahor» saytiga birinchi skriptlar keladi. Choyxona egasi Jasur aka dasturchi tanishidan uchta fayl olib keldi:

  • menyu.js — menyuda "faqat issiq taomlar" tugmasi bosilganda ro'yxatni saralaydi.
  • analitika.js — saytga kunda nechta mehmon kirganini sanaydi.
  • Cloudflare Turnstile — bron formasini botlardan himoya qiladi. Uni Forma xavfsizligi darsida ulagan edik.

JavaScript'ni hali bilmaysiz — uni JavaScript nima darsidan boshlab o'rganamiz. Bu dars uchun bu muhim emas. Skript fayli ichida nima yozilgani biz uchun qora quti. Bizni faqat HTML tomoni qiziqtiradi: faylni qayerga va qaysi atribut bilan ulash.

Nega bu shunchalik muhim? Chunki noto'g'ri ulangan skript ikki xil zarar qiladi. Birinchisi — sahifa sekin ochiladi: mehmon oq ekranga qarab qoladi. Ikkinchisi — skript ishlamaydi: tugma bosiladi, hech narsa bo'lmaydi.

2. script tegi: asoslar

2.1 Tashqi skript

html
<script src="menyu.js"></script>
  • src — skript faylining manzili. Xuddi img dagi src kabi: nisbiy yoki to'liq yo'l.
  • Yopuvchi </script> majburiy. Ichi bo'sh bo'lsa ham.

type="text/javascript" yozish shart emas — brauzer standart bo'yicha shuni tushunadi. Eski kodlarda uchraydi. html-validate uni ortiqcha deb belgilaydi:

text
error  "type" attribute is unnecessary for javascript resources  script-type

Tarjimasi: "JavaScript resurslari uchun type atributi keraksiz".

2.2 Ichki (inline) skript

Kodni to'g'ridan-to'g'ri teg ichiga ham yozish mumkin:

html
<script>
  console.log("Salom, Bahor!");
</script>

Bu — ichki skript (inline script). Qisqa kod uchun qulay. Lekin katta kodni alohida faylga chiqargan ma'qul: brauzer faylni keshlaydi va keyingi sahifalarda qayta yuklamaydi (HTTP va kesh darsidagi g'oya).

Diqqat: src va ichki kod birga ishlamaydi. <script src="menyu.js">console.log(1);</script> da brauzer faqat menyu.js ni oladi, ichidagi console.log esa jimgina e'tiborsiz qoldiriladi.

3. Oddiy skript: HTML o'qish to'xtaydi

3.1 Nima bo'ladi

Renderni nima to'xtatadi darsida ko'rdik. Brauzer HTML'ni yuqoridan pastga o'qiydi va DOM daraxtini quradi. Oddiy script tegiga yetganda u to'xtaydi:

  1. Skript faylini yuklaydi.
  2. Uni bajaradi.
  3. Shundan keyingina HTML'ni o'qishda davom etadi.

Nega brauzer bunday qiladi? Chunki skript sahifaga yangi HTML yozishi mumkin. Brauzer skript nima qilishini oldindan bilmaydi. Shuning uchun xavfsiz yo'lni tanlaydi — kutadi.

Hayotdan o'xshatish: oshpaz osh damlayotganda ziravor tugadi. U qozonni tashlab, o'zi bozorga boradi. Qaytmaguncha oshxonada ish to'xtaydi.

3.2 Ikki muammo

menyu.js ni head ga oddiy qilib qo'ydik:

html
<head>
  <meta charset="utf-8">
  <title>Menyu — Choyxona «Bahor»</title>
  <script src="menyu.js"></script>
</head>
<body>
  <button id="issiq" type="button">Faqat issiq taomlar</button>
</body>

Birinchi muammo — sekinlik. Internet sekin bo'lsa, menyu.js 2 soniya yuklanadi. Shu 2 soniya davomida body hali o'qilmagan — mehmon oq ekranni ko'radi.

Ikkinchi muammo — skript elementni topmaydi. menyu.js "Faqat issiq taomlar" tugmasini qidiradi. Lekin u bajarilayotgan paytda brauzer hali body ga yetib bormagan — tugma DOM'da yo'q. Konsolda xato chiqadi:

text
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

Tarjimasi: "null ning addEventListener xususiyatini o'qib bo'lmaydi". null — "hech narsa". Skript tugmani qidirdi, hech narsa topmadi va o'sha "hech narsa"ga hodisa ulamoqchi bo'ldi. Xatoning sababi skript kodida emas — HTML'dagi joylashuvda.

3.3 Eski yechim: body oxiri

Uzoq yillar dasturchilar skriptni </body> dan oldinga qo'yishardi:

html
<body>
  <button id="issiq" type="button">Faqat issiq taomlar</button>

  <script src="menyu.js"></script>
</body>

Endi skript bajarilganda tugma allaqachon DOM'da. Sahifa ham skriptni kutmasdan ko'rinadi. Bu usul ishlaydi va eski saytlarda juda ko'p uchraydi.

Lekin zamonaviy yo'l qulayroq — defer.

Tekshirib ko'ring: Nega head dagi oddiy skript tugmani topa olmadi, body oxiridagisi esa topdi?

Javob

Oddiy skript o'z qatoriga yetilgan zahoti bajariladi. Bu paytda head dan pastdagi body hali o'qilmagan — tugma yo'q. body oxirida esa brauzer skriptgacha butun sahifani o'qib bo'lgan, tugma allaqachon DOM'da bor.

4. defer: "yuklab qo'y, keyin bajar"

html
<script src="menyu.js" defer></script>

defer (inglizcha "kechiktirmoq") — boolean atribut, qiymati yozilmaydi. U brauzerga aytadi:

  1. Skriptni fonda yuklay ber, HTML o'qishni to'xtatma.
  2. HTML to'liq o'qib bo'lingach, skriptni bajar.
  3. Bir nechta defer skript bo'lsa — ularni yozilgan tartibda bajar.

Oshxona o'xshatishida: oshpaz shogirdni bozorga yuboradi va o'zi ishda davom etadi. Shogird ziravorni olib keladi, oshpaz esa uni osh damlashga kelganda ishlatadi.

Natija: sahifa tez ko'rinadi, menyu.js esa bajarilganda tugma allaqachon joyida. Ikkala muammo hal.

Yana bir foydasi: defer skriptlar HTML to'liq o'qilganini bildiruvchi DOMContentLoaded hodisasidan oldin bajariladi. Bu hodisa nomini JavaScript qismida ko'p eshitasiz. Hozircha ma'nosi yetarli: "sahifa tuzilmasi tayyor" degan signal.

Maslahat: defer faqat src bor tashqi skriptda ishlaydi. Ichki skriptga defer yozsangiz, brauzer atributni e'tiborsiz qoldiradi va kod darhol bajariladi.

5. async: "yuklanishi bilan bajar"

html
<script src="https://example.com/analitika.js" async></script>

async (asynchronous — "bir vaqtda emas") ham skriptni fonda yuklaydi. Farqi — bajarish vaqtida:

  • Skript yuklanishi bilanoq bajariladi. HTML o'qish shu qisqa payt to'xtab turadi.
  • Bir nechta async skript tartibsiz bajariladi: qaysi biri oldin yuklansa, o'sha birinchi.
  • HTML to'liq o'qilganini kutmaydi.

Qachon kerak? Skript sahifaning boshqa qismlariga bog'liq bo'lmasa: analitika, reklama, chat vidjeti. analitika.js uchun farqi yo'q — tugmalar tayyormi yoki yo'q. Uning vazifasi — "yana bitta mehmon keldi" deb yozib qo'yish. Qanchalik erta bajarilsa, shuncha yaxshi.

Forma xavfsizligi darsida Turnstile'ni async defer bilan ulagan edik. Ikkalasi birga yozilsa, zamonaviy brauzer async ni tanlaydi. defer esa async ni bilmaydigan juda eski brauzerlar uchun zaxira edi. Bu odat katta xizmatlar kodida hali ham qolgan.

Tekshirib ko'ring: jadval.js va jadval-bezak.js bor. Ikkinchisi birinchisining ichidagi kodni ishlatadi. Ikkalasiga async qo'ysak nima bo'lishi mumkin?

Javob

jadval-bezak.js kichikroq bo'lsa, u birinchi yuklanib, birinchi bajarilishi mumkin. Unda u hali mavjud bo'lmagan kodni ishlatmoqchi bo'ladi — xato chiqadi. Bir-biriga bog'liq skriptlarga defer kerak: u yozilgan tartibni kafolatlaydi.

6. Diagramma: to'rt usul yonma-yon

Quyidagi diagrammada vaqt chapdan o'ngga oqadi. Raqamlar — shartli vaqt birliklari. Har bir holatda brauzer HTML'ni o'qiydi va 3-birlikda skript tegiga duch keladi. Skript 3 birlik yuklanadi va 1 birlik bajariladi.

gantt
  title Vaqt chapdan o'ngga oqadi
  dateFormat ss
  axisFormat %S
  section Oddiy
    HTML o'qish      :done, o1, 00, 3s
    Yuklash          :active, o2, 03, 3s
    Bajarish         :crit, o3, 06, 1s
    HTML davomi      :done, o4, 07, 4s
  section async
    HTML o'qish      :done, a1, 00, 6s
    Yuklash          :active, a2, 03, 3s
    Bajarish         :crit, a3, 06, 1s
    HTML davomi      :done, a4, 07, 1s
  section defer
    HTML o'qish      :done, d1, 00, 7s
    Yuklash          :active, d2, 03, 3s
    Bajarish         :crit, d3, 07, 1s

Diagrammani o'qiymiz:

  • Oddiy. 3-birlikda HTML o'qish to'xtaydi. Brauzer yuklashni kutadi (3–6), bajaradi (6–7) va shundan keyingina davom etadi. Sahifa 11-birlikda tayyor — eng sekin.
  • async. Yuklash HTML o'qish bilan parallel ketadi. Yuklanishi bilan (6) HTML to'xtab, skript bajariladi. Keyin HTML davom etadi. Sahifa 8-birlikda tayyor.
  • defer. Yuklash ham parallel, bajarish esa HTML to'liq o'qilgandan keyin (7–8). HTML bir marta ham to'xtamadi.
  • type="module" — diagrammada alohida ko'rsatilmadi, chunki u defer qatori bilan bir xil ishlaydi — pastda ko'ramiz.

Bitta jadvalda:

Usul Yuklash Bajarish Tartib
Oddiy HTML'ni to'xtatib Darhol Yozilgan tartibda
async Fonda Yuklanishi bilan Kafolatsiz
defer Fonda HTML o'qib bo'lingach Yozilgan tartibda
module Fonda HTML o'qib bo'lingach Yozilgan tartibda

Bo'sh joyni to'ldiring: bir-biriga bog'liq ikki skriptni tartib bilan, HTML'ni to'xtatmasdan ulash uchun qaysi atribut kerak?

7. type="module": zamonaviy JavaScript fayllari

7.1 Modul nima

Katta loyihada JavaScript kodi o'nlab fayllarga bo'linadi. Bir fayl boshqasidan kerakli qismni "olib keladi". Bunday fayllar modul (module) deyiladi. Qanday yozilishini modullar darsida o'rganamiz. HTML tomonida esa bitta atribut kifoya:

html
<script type="module" src="app.js"></script>

7.2 Modul skriptning xususiyatlari

  • O'zi defer kabi. Fonda yuklanadi, HTML o'qib bo'lingach bajariladi. defer qo'shish shart emas — ta'siri yo'q.
  • async qo'shsa bo'ladi. Unda yuklanishi bilan bajariladi, xuddi oddiy async kabi.
  • Bir marta bajariladi. Bitta modul sahifaga ikki marta ulansa ham, faqat bir marta ishlaydi. Oddiy skript esa ikki marta bajarilardi.
  • Ichki modul ham kechiktiriladi. Oddiy ichki skriptdan farqli: <script type="module">...</script> ichidagi kod ham HTML o'qib bo'lingach bajariladi.
  • Server talab qiladi. Modullar file:// da ishlamaydi.

Oxirgi band Birinchi sahifa darsida bergan va'damiz edi: "JavaScript qismida ba'zi imkoniyatlar file:// da ishlamaydi". Mana o'sha imkoniyat. Faylni ikki marta bosib ochsangiz, konsolda qizil xato chiqadi:

text
Access to script at 'file:///C:/Users/Aziz/Documents/choyxona/app.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: chrome, chrome-extension, chrome-untrusted, data, http, https, isolated-app.

Tarjimasi: "app.js ga kirish bloklandi: boshqa manbadan so'rovlar faqat http, https va boshqa bir nechta sxemalarda ruxsat etiladi". Sxemalar ro'yxati Chrome versiyasiga qarab biroz farq qiladi. Muhimi: ro'yxatda file yo'q. Same-Origin Policy darsida ko'rgan xavfsizlik qoidasi ishladi. Tuzatish: sahifani Live Server orqali oching (http://127.0.0.1:5500).

7.3 nomodule — eski brauzerlar uchun

html
<script type="module" src="app.js"></script>
<script nomodule src="app-eski.js"></script>

Modulni tushunadigan brauzer nomodule li skriptni o'tkazib yuboradi. Tushunmaydigan eski brauzer esa type="module" ni tanimaydi va faqat nomodule ni bajaradi. Shunday qilib, har brauzer o'ziga mosini oladi.

Bugun barcha zamonaviy brauzerlar modullarni 2018-yildan beri tushunadi. Shuning uchun yangi loyihada nomodule deyarli kerak emas. Uni eski loyihalarda va ba'zi build vositalarining "eski brauzerlar uchun" sozlamasida uchratasiz.

8. importmap: modul nomlari xaritasi

Modul ichida boshqa kutubxonani nomi bilan chaqirish mumkin, masalan sanalar bilan ishlaydigan dayjs:

html
<script type="module">
  import dayjs from "dayjs";
</script>

Brauzer "dayjs" so'zini ko'rib hayron qoladi: bu qaysi fayl? Qaysi serverda? Xato beradi:

text
Uncaught TypeError: Failed to resolve module specifier "dayjs". Relative references must start with either "/", "./", or "../".

Tarjimasi: "dayjs modul nomini manzilga aylantirib bo'lmadi. Nisbiy manzillar /, ./ yoki ../ bilan boshlanishi kerak". Ya'ni brauzer faqat manzilni tushunadi, nomni emas.

Import map (import xaritasi) — nomni manzilga bog'laydigan "telefon kitobcha":

html
<script type="importmap">
  {
    "imports": {
      "dayjs": "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/+esm"
    }
  }
</script>
<script type="module" src="app.js"></script>
  • Ichida JSON: "imports" ichida "nom": "manzil" juftliklari.
  • Birinchi modul skriptidan oldin turishi kerak.
  • 2023-yildan barcha asosiy brauzerlarda bor, bugun Baseline widely available.

Katta loyihalarda bu ishni Vite kabi vositalar qiladi. Ikkalasini Brauzerda ESM va import maps darsida solishtiramiz.

Maslahat: Atribut type ga brauzer tanimaydigan qiymat yozilsa, script ichidagi matn bajarilmaydi — u oddiy ma'lumot bo'lib qoladi. Import map ham shu qoidadan foydalanadi. JSON-LD darsida type="application/ld+json" ni ko'ramiz — u ham skript emas, qidiruv tizimlari uchun ma'lumot.

9. noscript: JavaScript o'chirilgan bo'lsa

Ba'zi foydalanuvchilar JavaScript'ni o'chirib qo'yadi. Ba'zi korporativ tarmoqlarda u taqiqlangan. Skript yuklanmay qolishi ham mumkin. noscript ichidagi kontent faqat shunday holatda ko'rinadi:

html
<noscript>
  <p>Menyuni saralash uchun JavaScript kerak.
     Taomlar ro'yxati quyida to'liq ko'rsatilgan.</p>
</noscript>

Qoidalar:

  • body ichida noscript ga oddiy kontent yozsa bo'ladi: paragraf, havola, rasm.
  • head ichida esa faqat link, style va meta mumkin.

head dagi noscript ichiga paragraf qo'ysangiz, html-validate xato beradi:

text
error  <p> element is not permitted as content under <head>  element-permitted-content

Tarjimasi: "p elementi head ichida bo'lishi mumkin emas". Brauzer ham uni head dan chiqarib, body ga ko'chiradi — HTML tahlili darsida ko'rgan "tuzatish".

Eng muhimi: yaxshi sayt JavaScript'siz ham asosiy vazifasini bajaradi. «Bahor» menyusi to'liq ko'rinadi — faqat saralash tugmasi ishlamaydi. Bu progressive enhancement: Zamonaviy forma imkoniyatlari darsidagi "zinapoya va lift" g'oyasi.

10. integrity: begona skriptga ishonch

10.1 Muammo

Ba'zan skriptni o'z saytingizdan emas, CDN dan olasiz. CDN (Content Delivery Network) — fayllarni dunyo bo'ylab ko'p serverlardan tez tarqatadigan xizmat, masalan cdn.jsdelivr.net. Qulay: yuklash tez, o'zingiz saqlashingiz shart emas.

Lekin bu fayl endi boshqa birovning serverida. Agar CDN buzilsa yoki fayl almashtirilsa, sizning saytingizda begona kod ishlaydi. U mehmonlaringizning ma'lumotini o'g'irlashi mumkin.

10.2 Yechim: SRI

SRI (Subresource Integrity — resurs butunligi) — faylning "barmoq izi"ni HTML'ga yozib qo'yish:

html
<script
        src="https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js"
        integrity="sha384-DpVxUeeBWjUvUV1czyIHJAjh+jYUZFu2lLakbdua5vbwOrBGi1UgaKCHjTC+x3Ky"
        crossorigin="anonymous" defer></script>
  • integrity — faylning xeshi (hash). Bu faylning har bir baytidan hisoblangan qisqa "barmoq izi". Faylda bitta harf o'zgarsa ham, xesh butunlay boshqacha bo'ladi. sha384 — hisoblash usulining nomi.
  • crossorigin="anonymous" — boshqa serverdagi fayl uchun SRI ishlashi shart. U so'rovni cookie'larsiz yuboradi.

Brauzer faylni yuklab, xeshini o'zi hisoblaydi va integrity bilan solishtiradi. Mos kelmasa — skriptni bajarmaydi va konsolda xato chiqaradi:

text
Failed to find a valid digest in the 'integrity' attribute for resource 'https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js' with computed SHA-384 integrity '...'. The resource has been blocked.

Tarjimasi: "integrity atributida bu resurs uchun to'g'ri xesh topilmadi. Hisoblangan SHA-384 xesh: '...'. Resurs bloklandi".

Xeshni qayerdan olasiz? jsDelivr va cdnjs sahifalarida "Copy SRI" tugmasi bor. Yoki o'zingiz terminalda hisoblaysiz (openssl dasturi Git Bash'da tayyor bor):

bash
openssl dgst -sha384 -binary dayjs.min.js | openssl base64 -A

Muhim: SRI faqat versiyasi qotirilgan fayl bilan ishlaydi (dayjs@1.11.13). dayjs@1 kabi "eng yangisini ber" manzilida fayl yangilanganda xesh mos kelmay qoladi va skript bloklanadi.

11. Hujumchi nigohi

2024-yil, polyfill.io voqeasi. Yuz mingdan ortiq sayt eski brauzerlar uchun yordamchi skriptni cdn.polyfill.io dan ulagan edi. 2024-yil boshida domen yangi egaga sotildi. Iyun oyida bu CDN ba'zi telefon foydalanuvchilariga zararli kod bera boshladi: mehmonlarni firibgar saytlarga yo'naltirardi. Saytlar egalari o'z kodiga tegmagan edi — lekin ularning sahifalarida begona kod ishladi.

Bu yerdan uchta dars:

  1. Begona skript — sizning saytingizdagi begona odam. U sahifadagi hamma narsani ko'radi va o'zgartira oladi: formalar, parollar, havolalar.
  2. SRI yordam beradi, lekin har doim emas. polyfill.io har brauzerga har xil fayl berardi, shuning uchun unga SRI qo'yib bo'lmasdi. Bunday xizmatdan umuman voz kechish kerak edi.
  3. Imkon bo'lsa — faylni o'zingizda saqlang. dayjs.min.js ni yuklab olib, /assets/js/ papkangizga qo'ying. Endi faqat o'z serveringizga ishonasiz.

Analitika va Turnstile kabi doim yangilanadigan xizmatlarga SRI qo'yib bo'lmaydi — ularni faqat ishonchli kompaniyalardan oling. HTML darajasidagi xavfsizlik darsida CSP bilan birga to'liq himoya quramiz.

12. «Bahor» sayti: yakuniy head

head anatomiyasi darsidan beri qurib kelgan head ning to'liq ko'rinishi:

html
<!DOCTYPE html>
<html lang="uz">
  <head>
    <!-- 1. Birinchi 1024 bayt ichida bo'lishi shart -->
    <meta charset="utf-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1">
    <title>Choyxona «Bahor» — Chilonzor, Toshkent</title>

    <!-- 2. CSS va skriptlar: brauzer ularni erta ko'rsin -->
    <link rel="stylesheet" href="/assets/css/asosiy.css">
    <script src="https://example.com/analitika.js" async></script>
    <script src="/assets/js/menyu.js" defer></script>

    <!-- 3. Qidiruv tizimlari -->
    <meta name="description"
          content="Chilonzordagi choyxona: Toshkent oshi 35 000 so'm,
                   lag'mon va kabob. Har kuni 7:00–23:00.">
    <link rel="canonical" href="https://example.com/">

    <!-- 4. Ijtimoiy tarmoq kartasi -->
    <meta property="og:site_name" content="Choyxona «Bahor»">
    <meta property="og:type" content="website">
    <meta property="og:locale" content="uz_UZ">
    <meta property="og:url" content="https://example.com/">
    <meta property="og:title"
          content="Choyxona «Bahor» — Chilonzor, Toshkent">
    <meta property="og:description"
          content="Chilonzordagi choyxona: Toshkent oshi 35 000 so'm,
                   lag'mon va kabob. Har kuni 7:00–23:00.">
    <meta property="og:image"
          content="https://example.com/assets/images/og-bahor.jpg">
    <meta property="og:image:width" content="1200">
    <meta property="og:image:height" content="630">
    <meta name="twitter:card" content="summary_large_image">

    <!-- 5. Ikonkalar va ilova -->
    <link rel="icon" href="/favicon.ico" sizes="32x32">
    <link rel="icon" href="/favicon.svg" type="image/svg+xml">
    <link rel="apple-touch-icon" href="/apple-touch-icon.png">
    <link rel="manifest" href="/manifest.webmanifest">
    <meta name="theme-color" content="#2f6b3a"
          media="(prefers-color-scheme: light)">
    <meta name="theme-color" content="#16301b"
          media="(prefers-color-scheme: dark)">
    <meta name="color-scheme" content="light dark">

    <!-- 6. Boshqa meta teglar -->
    <meta name="format-detection" content="telephone=no">
    <meta name="google-site-verification"
          content="Google-bergan-kod-shu-yerga">
  </head>
  <body>
    <main>
      <h1>Choyxona «Bahor»</h1>
      <button id="issiq" type="button">Faqat issiq taomlar</button>
      <noscript>
        <p>Saralash uchun JavaScript kerak. Menyu quyida to'liq.</p>
      </noscript>
    </main>
  </body>
</html>

Tartib head anatomiyasi darsidagi qoidaga mos: majburiy uchlik, keyin CSS va skriptlar, oxirida qolgan meta teglar. Nega skriptlar meta teglardan oldin? Brauzer ularni qanchalik erta ko'rsa, yuklashni shunchalik erta boshlaydi. Meta teglar hech narsa yuklamaydi — pastda tursa ham farqi yo'q. CSS'ni esa keyingi qismda yozamiz, hozircha asosiy.css — bo'sh fayl.

menyu.js ni /assets/js/ papkasiga ko'chirdik — Ko'p sahifali sayt darsidagi assets tartibi. Turnstile esa faqat bron sahifasida ulanadi — bosh sahifaga keraksiz yuk tashlamaymiz.

Maslahat: Brauzerga "bu fayl juda muhim, uni birinchi yukla" yoki "keyingi sahifani oldindan tayyorlab qo'y" deyish ham mumkin. Bu — resurs maslahatlari, keyingi dars mavzusi.

13. Ko'p uchraydigan xatolar

13.1 script ni o'zi yopish

html
<!-- ❌ -->
<script src="menyu.js" />

Boshqa ba'zi tillarda /> tegni "o'zi yopadi". HTML'da script uchun bu ishlamaydi. Brauzer /> ni oddiy > deb tushunadi va </script> ni qidiradi. Undan keyingi hamma narsa — </head>, body, sarlavhalar — skript ichidagi matn bo'lib qoladi. src bor bo'lgani uchun bu matn e'tiborsiz qoldiriladi. Natija: bo'sh oq sahifa.

html-validate ikkita xato beradi:

text
error  <script> must not be self-closed          no-self-closing
error  End tag for <script> must not be omitted  script-element

Tarjimasi: "script ni o'zi yopib bo'lmaydi" va "script ning yopuvchi tegini tashlab ketish mumkin emas". Tuzatish: har doim <script src="..."></script>.

13.2 Ichki skriptga defer

<script defer>...</script> — src yo'q, shuning uchun defer ishlamaydi. Kod darhol bajariladi va elementlarni topmay qolishi mumkin. Validator buni ushlamaydi. Tuzatish: kodni alohida faylga chiqarib, src va defer bilan ulang. Yoki type="module" ishlating — ichki modul ham kechiktiriladi.

13.3 Bog'liq skriptlarga async

Ba'zan ishlaydi, ba'zan yo'q — internet tezligiga qarab. Bunday "suzib yuruvchi" xato eng og'ir topiladi. Tuzatish: tartib muhim bo'lsa — defer.

13.4 Modulni file:// da ochish

Modullar bo'limidagi CORS xatosi chiqadi. Tuzatish: Live Server.

13.5 importmap moduldan keyin

html
<!-- ❌ tartib noto'g'ri -->
<script type="module" src="app.js"></script>
<script type="importmap">
  { "imports": { "dayjs": "/assets/js/dayjs.js" } }
</script>

app.js yuklanayotganda brauzer hali xaritani ko'rmagan. Tuzatish: importmap — har doim birinchi modul skriptidan oldin.

14. Mashqlar

1-mashq (oson): Atributni tanlang

Har bir skript uchun atribut tanlang: yo'q (oddiy), async, defer yoki type="module".

  1. menyu.js — menyudagi tugmalarni ishlatadi.
  2. hisoblagich.js — tashrif sonini sanaydi, sahifaga tegmaydi.
  3. app.js — boshqa fayllardan import bilan kod oladi.
  4. kutubxona.js va undan keyin uni ishlatadigan galereya.js.
Yechim
  1. defer — tugmalar DOM'da tayyor bo'lishi kerak.
  2. async — mustaqil, qanchalik erta ishlasa, shuncha yaxshi.
  3. type="module" — import faqat modulda ishlaydi; u o'zi defer kabi.
  4. Ikkalasiga defer — yozilgan tartib saqlanadi: avval kutubxona.js, keyin galereya.js.

Oddiy (atributsiz) skript faqat skript sahifa chizilishidan oldin albatta ishlashi shart bo'lganda kerak. Masalan, qorong'i rejim tanlovini eng boshida qo'llash — buni Qorong'i rejim va temalash darsida ko'ramiz.

2-mashq (o'rta): Oq sahifani tuzating

Aziz yangi "Aloqa" sahifasini yasadi, lekin brauzerda bo'sh oq sahifa chiqyapti. Sababini toping va tuzating. Keyin skriptni tezlik uchun to'g'ri ulang.

html
<!-- ❌ sahifa bo'sh chiqyapti -->
<head>
  <meta charset="utf-8">
  <title>Aloqa — Choyxona «Bahor»</title>
  <script type="text/javascript" src="/assets/js/xarita.js" />
</head>
<body>
  <h1>Aloqa</h1>
</body>
Yechim
html
<head>
  <meta charset="utf-8">
  <title>Aloqa — Choyxona «Bahor»</title>
  <script src="/assets/js/xarita.js" defer></script>
</head>
<body>
  <h1>Aloqa</h1>
</body>
  1. Asosiy sabab — />. script o'zini yopmaydi, shuning uchun body va h1 skript matni ichida "yutilib" ketdi.
  2. type="text/javascript" — ortiqcha, olib tashladik.
  3. defer — xarita skripti sahifaga bog'liq, HTML'ni to'xtatmasin.

3-mashq (qiyin): CDN'dan xavfsiz ulash

«Bahor» blogida sanalarni chiroyli ko'rsatish uchun dayjs kutubxonasi kerak. Fayl: https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js, xeshi darsdagi SRI bo'limida. Undan keyin uni ishlatadigan o'z faylimiz /assets/js/blog.js ulanadi.

  1. Ikkala skriptni to'g'ri tartibda va to'g'ri atributlar bilan yozing.
  2. CDN faylni o'zgartirib yuborsa, sahifada nima bo'ladi?
  3. Nega dayjs@1 kabi qisqa manzilni ishlatmadingiz?
Yechim
html
<script
        src="https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js"
        integrity="sha384-DpVxUeeBWjUvUV1czyIHJAjh+jYUZFu2lLakbdua5vbwOrBGi1UgaKCHjTC+x3Ky"
        crossorigin="anonymous" defer></script>
<script src="/assets/js/blog.js" defer></script>
  1. Ikkalasiga defer: blog.js dayjs ga bog'liq, defer esa yozilgan tartibni kafolatlaydi. integrity va crossorigin="anonymous" — begona serverdagi fayl uchun.
  2. Brauzer yangi faylning xeshini hisoblaydi, u integrity bilan mos kelmaydi — skript bloklanadi. Konsolda Failed to find a valid digest... xatosi chiqadi. Sanalar chiroyli ko'rinmaydi, lekin begona kod ham ishlamaydi. Bu to'g'ri tanlov: sal xunuk sahifa o'g'irlangan ma'lumotdan yaxshiroq.
  3. dayjs@1 — "1-versiyaning eng yangisi". Yangi versiya chiqqanda fayl o'zgaradi, xesh mos kelmay qoladi va sayt o'z-o'zidan buziladi. SRI uchun versiya to'liq qotirilishi kerak.

15. Real ishda

  • Deyarli har bir saytda. Google Analytics, Yandex Metrika, chat vidjetlari async bilan ulanadi — ularning rasmiy kodini ko'rsangiz, shu atributni topasiz.
  • Vite va React. Vite HTML'ga type="module" li skriptni o'zi yozadi — nega aynan modul ekanini endi bilasiz.
  • Tezlik auditi. Lighthouse "Eliminate render-blocking resources" deb ogohlantirsa, birinchi qadam — oddiy skriptlarga defer qo'shish.
  • Uchinchi tomon vidjetlari sahifani sekinlashtiradi va xavf qo'shadi — Uchinchi tomon skriptlar darsida chuqur ko'ramiz.
  • Intervyuda deyarli har doim so'raladi: "defer va async farqi nima?". Javob: ikkalasi fonda yuklaydi; defer HTML o'qilgach tartib bilan bajaradi, async — yuklanishi bilan, tartibsiz.

Xulosa

  • Oddiy script HTML o'qishni to'xtatadi: sahifa sekinlashadi, skript pastdagi elementlarni topmaydi.
  • defer — fonda yuklash, HTML o'qilgach tartib bilan bajarish; sahifaga bog'liq skriptlar uchun odatiy tanlov.
  • async — fonda yuklash, yuklanishi bilan tartibsiz bajarish; analitika kabi mustaqil skriptlar uchun.
  • type="module" o'zi defer kabi ishlaydi va server talab qiladi; importmap modul nomlarini manzilga bog'laydi, nomodule — eski brauzerlar uchun.
  • script hech qachon /> bilan yopilmaydi; noscript — JavaScript yo'q bo'lganda ko'rinadigan matn.
  • Begona CDN skriptiga integrity + crossorigin="anonymous", imkon bo'lsa — faylni o'zingizda saqlang.

Keyingi dars: Resurs maslahatlari: preload, preconnect, prefetch — brauzerga "bu fayl kerak bo'ladi" deb oldindan aytib, sahifani yanada tezlashtiramiz.

Manbalar

  • MDN: "<script>: The Script element", "JavaScript modules", "<script type="importmap">", "Subresource Integrity" — developer.mozilla.org
  • HTML Living Standard: "Scripting" bo'limi — html.spec.whatwg.org
  • web.dev: "Efficiently load third-party JavaScript" — web.dev
  • Sansec: "Polyfill supply chain attack hits 100K+ sites" (2024) — sansec.io
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
HTML script tegi: defer, async va module bilan skriptlarni to'g'ri ulash — IlmHamroh