Script tegi — defer, async, type="module" — farqlari

~15 daq · HTML · Semantik HTML va Meta

Muammodan boshlaylik

JavaScript faylni ulaysiz:

<head>
  <script src="app.js"></script>
</head>
<body>
  <button id="saqlash">Saqlash</button>
</body>
// app.js
document.getElementById('saqlash').addEventListener('click', ...);

Konsolda xato: Cannot read properties of null. Tugma bor-ku! Yana bir muammo: katta skript yuklanayotganda sahifa bir necha soniya bo'sh oq turadi.

Ikkalasining sababi — brauzer <script> ni qanday o'qishida. Uni boshqarish uchun defer, async va type="module" atributlari bor.


Oddiy script — sahifani to'xtatadi

Brauzer HTML ni yuqoridan pastga o'qiydi. Oddiy <script> ga duch kelganda:

HTML o'qish ──────■ to'xtadi ──────────────────────────■ davom ─────▶
                  │                                    │
                  └─ skriptni yuklash ── bajarish ─────┘
  1. HTML o'qishni to'xtatadi
  2. Faylni yuklaydi (sekin internetda — soniyalar)
  3. Bajaradi
  4. Shundan keyingina HTML ni davom ettiradi

Natijalar:

  • Skript bajarilayotganda pastdagi HTML hali yo'q — getElementById('saqlash') → null (1-muammo)
  • Yuklash paytida sahifa chizilmaydi — bo'sh ekran (2-muammo)

Bu xatti-harakat "render-blocking" (chizishni bloklovchi) deb ataladi.

Eski yechim — body oxirida

<body>
  <button id="saqlash">Saqlash</button>
  <script src="app.js"></script>      <!-- eng oxirida -->
</body>

HTML allaqachon o'qilgan, tugma mavjud. Ishlaydi — lekin brauzer skriptni yuklashni faqat HTML oxiriga yetgandagina boshlaydi, vaqt yo'qotiladi. Zamonaviy yechim — defer.


defer — keyinga qoldirish

<head>
  <script src="app.js" defer></script>
</head>
HTML o'qish ──────────────────────────────────────■ tugadi ── bajarish
                  │
                  └─ skriptni yuklash (parallel) ─┘
  • Skript parallel yuklanadi — HTML o'qish to'xtamaydi, sahifa chiziladi
  • HTML to'liq o'qilgandan keyin bajariladi (DOMContentLoaded dan oldin) — barcha elementlar mavjud
  • Bir nechta defer skript — HTML dagi tartibda bajariladi
<script src="kutubxona.js" defer></script>
<script src="app.js" defer></script>      <!-- har doim kutubxona.js dan keyin -->

Ikkala muammo hal, va skript <head> da tursa ham, eng erta yuklanadi.

[!TIP] Sahifa elementlari bilan ishlaydigan skriptlar uchun — defer, <head> ichida. Bu bugungi standart yondashuv. DevDocs saytida ham kod rangini beruvchi (highlight.js) skriptlar shunday ulangan.


async — tayyor bo'lishi bilan

<script src="analytics.js" async></script>
HTML o'qish ──────────────■ to'xtadi ■ davom ─────────────────▶
                  │       │          │
                  └─ yuklash ─ bajarish (yuklanishi bilan)
  • Parallel yuklanadi
  • Yuklanishi bilan darhol bajariladi — HTML o'qishni qisqa to'xtatib
  • Tartib kafolatlanmaydi — qaysi biri oldin yuklansa, o'sha oldin bajariladi
  • Bajarilganda sahifa to'liq tayyor bo'lmasligi mumkin

Qachon: sahifaga va boshqa skriptlarga bog'liq bo'lmagan mustaqil skriptlar — analitika (Google Analytics, Yandex Metrika), reklama, chat vidjetlari.


Uchalasini taqqoslash

Oddiy defer async
HTML o'qishni to'xtatadimi ✅ Ha (yuklash + bajarish) ❌ Yo'q Faqat bajarish paytida
Qachon bajariladi Darhol HTML to'liq o'qilgandan keyin Yuklanishi bilan
Tartib HTML tartibida HTML tartibida Tasodifiy
DOM tayyormi Faqat yuqoridagi qismi ✅ To'liq Kafolat yo'q
Qachon Kamdan-kam Asosiy ilova kodi Mustaqil: analitika, reklama

type="module" — zamonaviy JavaScript

<script type="module" src="main.js"></script>

Fayl ES modul sifatida yuklanadi:

// main.js
import { hisobla } from './utils.js';
import { marked } from 'https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js';

hisobla();

Modul skriptlari:

  • Avtomatik defer xatti-harakatida — defer yozish shart emas
  • import / export ishlatish mumkin
  • O'z qamrovida — modul ichidagi o'zgaruvchilar global emas (window ga tushmaydi)
  • Har doim strict mode da
  • Faqat server orqali ishlaydi (file:// dan to'g'ridan-to'g'ri ochilganda — CORS xatosi; npx vite yoki VS Code Live Server ishlating)

Vite, Next.js kabi zamonaviy vositalar aynan type="module" ga asoslangan — DevDocs ham: <script type="module" src="/src/main.js">.

Modulni async ham qilish mumkin: <script type="module" async> — yuklanishi bilan bajariladi.

nomodule — eski brauzerlar uchun

<script type="module" src="app.modern.js"></script>
<script nomodule src="app.legacy.js"></script>

Modullarni tushunmaydigan juda eski brauzerlar faqat nomodule ni yuklaydi, zamonaviylari — uni e'tiborsiz qoldiradi. Bugun kamdan-kam kerak.


Ichki (inline) skript

<script>
  document.documentElement.dataset.theme = localStorage.getItem('theme') || 'light';
</script>
  • defer va async ichki skriptlarda ishlamaydi (faqat src bilan)
  • Kichik, sahifa chizilishidan oldin bajarilishi kerak bo'lgan kod uchun: masalan, qorong'i rejimni sahifa "miltillamasdan" o'rnatish

Katta kodni ichki skriptga yozmang — u keshlanmaydi va HTML ni og'irlashtiradi.


Tavsiyalar

<head>
  <meta charset="UTF-8">
  <title>...</title>
  <link rel="stylesheet" href="style.css">

  <!-- Ilova kodi -->
  <script type="module" src="main.js"></script>

  <!-- Yoki oddiy skript -->
  <script src="app.js" defer></script>

  <!-- Mustaqil uchinchi tomon skriptlari -->
  <script src="https://analytics.example.com/script.js" async></script>
</head>

Nima uchun shunday?

Nima uchun oddiy <script> standart holatda HTML o'qishni to'xtatadi — bu sahifani sekinlashtirishi aniq-ku?

Chunki skript HTML ni o'zgartirishi mumkin. Eski document.write() funksiyasi skript turgan joyga to'g'ridan-to'g'ri yangi HTML yozardi — va brauzer skriptni bajarmasdan turib keyingi HTML qanday bo'lishini bila olmasdi. Shuning uchun xavfsiz yo'l — to'xtab kutish edi. Zamonaviy kodda document.write() deyarli ishlatilmaydi, lekin orqaga moslik uchun standart xatti-harakat o'zgartirilmadi — buzilib qoladigan millionlab eski saytlar bor. Buning o'rniga defer va async qo'shildi: siz brauzerga "bu skript HTML ni yozmaydi, kutish shart emas" deb aytasiz va sahifa tezlashadi.


Xulosa

Eslab qoling:

  • Oddiy <script> — HTML o'qishni to'xtatadi; pastdagi elementlar hali yo'q, sahifa bo'sh turadi
  • defer — parallel yuklash, HTML to'liq o'qilgandan keyin, tartibda bajarish — asosiy kod uchun
  • async — parallel yuklash, yuklanishi bilan bajarish, tartibsiz — analitika, reklama
  • type="module" — avtomatik defer, import/export, o'z qamrovi; server orqali ishlaydi
  • Ichki skriptda defer/async ishlamaydi
  • Tavsiya: skriptlar <head> da, defer yoki type="module" bilan

Keyingi dars

13-dars: Semantik HTML va SEO — qanday bog'liq