Script optimizatsiya — next/script, strategy

~10 daq · Next.js · Performance va Optimizatsiya

Muammodan boshlaylik

Marketing bo'limi so'radi: Google Analytics, Yandex Metrika, Facebook Pixel, onlayn chat vidjeti va reklama skripti. Hammasini <head> ga qo'shdingiz:

<script src="https://mc.yandex.ru/metrika/tag.js"></script>
<script src="https://chat-vidjet.uz/widget.js"></script>

Lighthouse: Performance 95 → 58. Sahifa ko'rinishidan oldin brauzer begona serverlardan yuzlab kilobayt JavaScript yuklab, bajarishi kerak. Chat serveri sekin javob bersa — butun sahifa kutadi.


Hayotiy o'xshatma

Do'kon ochilishi. Avval eshik ochiladi va mijozlar kiradi (sahifa kontenti). Musiqa, reklama ekranlari va kuzatuv kameralari (uchinchi tomon skriptlari) — keyin yoqiladi. Hammasi tayyor bo'lmaguncha eshikni yopiq tutish — mijozlarni yo'qotish.


next/script

import Script from 'next/script'

<Script src="https://example.com/vidjet.js" strategy="lazyOnload" />

Strategiyalar

strategy Qachon yuklanadi Misol
beforeInteractive Sahifa interaktiv bo'lishidan oldin, faqat root layout da Cookie roziligi menejeri, bot himoyasi
afterInteractive (standart) Sahifa interaktiv bo'lgandan keyin Analitika, teg menejerlari
lazyOnload Brauzer bo'sh paytda, hammasidan keyin Chat, ijtimoiy tarmoq tugmalari
worker (eksperimental) Web Worker da (Partytown) Og'ir uchinchi tomon skriptlari

[!TIP] Qoida: imkon qadar kechroq. Ko'p skriptlar uchun lazyOnload yetarli — foydalanuvchi chat tugmasini sahifa ochilgandan 2 soniya keyin ko'rsa, hech narsa yo'qotmaydi.


Analitika

// app/layout.tsx
import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const GA_ID = process.env.NEXT_PUBLIC_GA_ID

  return (
    <html lang="uz">
      <body>
        {children}

        {GA_ID && (
          <>
            <Script src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`} strategy="afterInteractive" />
            <Script id="ga-init" strategy="afterInteractive">
              {`
                window.dataLayer = window.dataLayer || [];
                function gtag(){dataLayer.push(arguments);}
                gtag('js', new Date());
                gtag('config', '${GA_ID}');
              `}
            </Script>
          </>
        )}
      </body>
    </html>
  )
}
  • Inline skriptga id majburiy — Next.js uni kuzatib, takror qo'shmaydi
  • Root layout da — bir marta yuklanadi va sahifalar almashganda qayta yuklanmaydi

@next/third-parties

Google xizmatlari uchun tayyor, optimallashtirilgan komponentlar:

npm install @next/third-parties
import { GoogleAnalytics, GoogleTagManager } from '@next/third-parties/google'

<GoogleAnalytics gaId="G-XXXXXXX" />
import { YouTubeEmbed } from '@next/third-parties/google'

<YouTubeEmbed videoid="dQw4w9WgXcQ" height={400} />

YouTubeEmbed — YouTube ning og'ir iframe i o'rniga yengil "fasad": video faqat bosilganda yuklanadi.


Hodisalar

'use client'

import Script from 'next/script'

export function Xarita() {
  return (
    <>
      <Script
        src="https://api-maps.yandex.ru/2.1/?lang=uz_UZ&apikey=..."
        strategy="lazyOnload"
        onLoad={() => {
          // skript yuklandi — xaritani yaratish
          window.ymaps.ready(() => { /* ... */ })
        }}
        onError={(e) => console.error('Xarita yuklanmadi', e)}
      />
      <div id="xarita" className="h-80" />
    </>
  )
}
Hodisa Qachon
onLoad Skript birinchi marta yuklanganda
onReady Yuklanganda va har safar komponent qayta mount bo'lganda
onError Yuklanmasa

onLoad, onReady, onError — faqat Client Component da (funksiya prop).


Faqat kerakli sahifada

// app/aloqa/page.tsx — xarita skripti faqat shu sahifada
import Script from 'next/script'

export default function Aloqa() {
  return (
    <>
      <Script src="https://xarita.example/sdk.js" strategy="lazyOnload" />
      {/* ... */}
    </>
  )
}

Skript faqat foydalanuvchi shu sahifaga kirganda yuklanadi.

[!WARNING] Har bir uchinchi tomon skripti — sizning saytingizda to'liq huquq bilan bajariladigan begona kod: u DOM ni, cookie larni (httpOnly dan tashqari), formalardagi ma'lumotlarni ko'ra oladi. Faqat ishonchli manbalardan qo'shing, kerak bo'lmaganlarini olib tashlang va iloji bo'lsa CSP (Content-Security-Policy) bilan ruxsat etilgan domenlarni cheklang (71-dars).


Rozilik (consent)

Ba'zi mamlakatlarda (Yevropa — GDPR) analitika va reklama skriptlarini foydalanuvchi rozilik bergandan keyin yuklash talab qilinadi:

'use client'

export function Analitika() {
  const [rozi, setRozi] = useState(false)
  useEffect(() => setRozi(localStorage.getItem('rozilik') === 'ha'), [])

  if (!rozi) return null
  return <GoogleAnalytics gaId="G-XXXXXXX" />
}

Tez-tez uchraydigan xatolar

1. Oddiy <script> tegi

<script src> JSX da — Next.js uni boshqarmaydi; sahifalar almashganda takrorlanishi yoki umuman ishlamasligi mumkin. next/script.

2. Inline skriptda id yo'q

Ogohlantirish va takroriy bajarilish ehtimoli.

3. Hammasiga beforeInteractive

Sahifa barcha skriptlarni kutadi — eng sekin variant. Faqat haqiqatan sahifadan oldin kerak bo'lganlar uchun.


Xulosa

next/script — uchinchi tomon skriptlarini boshqarish
beforeInteractive — juda kam, faqat root layout
afterInteractive — analitika (standart)
lazyOnload — chat, vidjetlar; imkon qadar kechroq
Inline skript — id majburiy
@next/third-parties — GoogleAnalytics, GTM, YouTubeEmbed (fasad)
onLoad / onReady / onError — Client Component da
Faqat kerakli sahifada; ishonchli manbalar, CSP, rozilik

Keyingi dars

59-dars: Caching — Request Memoization, Data Cache, Full Route Cache

Next.js ning to'rt qatlamli keshi — nima qachon keshlanadi va qanday yangilanadi.