
⚡ Kuinka lisätä defer ja async WordPress-skripteille function.php-tiedostossa
Sivut latautuvat hitaasti, Google PageSpeed Insights näyttää oransseja varoituksia ja asiakas kysyy: "miksi sivusto on hidas?" Yhdeksässä tapauksessa kymmenestä perimmäinen syy on JavaScript, joka estää renderöinnin. Selain kohtaa <script>-elementin, pysäyttää DOM-puun rakentamisen, lataa ja suorittaa skriptin ja vasta sitten jatkaa. Nykyaikaisella sivustolla, jossa on tusina lisäosaa, tämä viive venyy sekunneiksi.
WordPress ei pitkään aikaan tarjonnut standardoitua tapaa hallita skriptien latausta. Kehittäjät kiersivät ongelmaa: suodattamalla script_loader_tag-koukkua, paikkaamalla tulostetta clean_url-funktion kautta tai jopa kirjoittamalla omia walkereita WP_Scripts-luokalle. Mutta WordPressin version 6.3 myötä tilanne muuttui radikaalisti, ja nyt meillä on siisti, tuettu tapa lisätä defer tai async mihin tahansa skriptiin ilman ainuttakaan purkkaviritystä.
Alla on kaksi toimivaa menetelmää: moderni natiiviapproach (WP 6.3+) ja testattu script_loader_tag-suodatin (WP 4.1+). Molemmat on testattu oikeissa projekteissa, ja molemmat säilyttävät riippuvuusjonon eheyden.
💡 Pikaopas:
- Ymmärrä ero
defer- jaasync-attribuuttien välillä ja milloin kumpaakin kannattaa käyttää, sillä tämä ratkaisee, hajoaako toiminnallisuus optimoinnin jälkeen - Käytä natiivia WordPress 6.3+ -menetelmää
wp_enqueue_script()-funktionstrategy-parametrin kautta, siistein tapa, joka säilyttää suoritusjärjestyksen - Jos sivusto käyttää versiota, joka on alle 6.3, käytä
script_loader_tag-suodatinta kahvojen taulukon kanssa, tämä toimii WordPress 4.1:stä alkaen - Kun skriptejä on useita, kerää kahvat taulukkoon ja kierrä se läpi silmukassa, yksi suodatin kaikille skripteille kopioi-liimaa -ratkaisun sijaan
Mitä defer ja async ovat ja milloin niitä käytetään
Kun selain kohtaa tavallisen <script>-elementin, se tekee kolme asiaa peräkkäin: pysäyttää HTML:n jäsentämisen, lataa skriptin, suorittaa sen. Vasta sitten se palaa HTML:n pariin. Sivulla, jossa on viisi skriptiä <head>-osiossa, tämä tarkoittaa, että käyttäjä näkee valkoisen ruudun sillä aikaa, kun viimeinen kommenttilaajennus latautuu, vaikka itse artikkeli olisi voitu renderöidä jo aikoja sitten.
defer- ja async-attribuutit ratkaisevat tämän ongelman, mutta toimivat eri tavoin:
Attribuutti | Milloin latautuu | Milloin suoritetaan | Suoritusjärjestys |
|---|---|---|---|
(ei mitään) | Estää jäsentämisen heti | Välittömästi latauksen jälkeen | DOM-järjestyksessä |
| Rinnakkain jäsentämisen kanssa | Kun DOM on täysin ladattu | DOM-järjestyksessä |
| Rinnakkain jäsentämisen kanssa | Välittömästi latauksen jälkeen | Se, joka latautuu ensin |
Defer on työjuhta useimpiin tilanteisiin. Skripti latautuu rinnakkain HTML:n kanssa ja suoritetaan vasta, kun DOM on täysin rakennettu. Järjestys säilyy: skripti A suoritetaan ennen skriptiä B, vaikka B latautuisi nopeammin. Tämä on kriittistä jQueryn ja kaiken siitä riippuvaisen kannalta.
Async on työkalu itsenäisille skripteille. Analytiikka, mainokset, some-widgetit: ne eivät tarvitse DOMia, ne eivät välitä järjestyksestä, niiden on vain saatava suorittaa itsensä mahdollisimman pian. Mutta jos laitat async-attribuutin skriptille, joka riippuu jQuerysta, saat todennäköisesti virheen $ is not defined.
Yksinkertainen sääntö: skripti riippuu muista skripteistä tai DOMista → defer. Skripti on täysin autonominen → async. Epävarmana aloita aina defer-attribuutilla.
Menetelmä 1: Natiivi WordPress 6.3+ -tapa
Heinäkuusta 2023 lähtien WordPressin ytimessä on toiminut uusi mekanismi. wp_register_script()- ja wp_enqueue_script()-funktiot saivat kuormitetun viidennen parametrin $args, taulukon, jossa voit määrittää latausstrategian. Ei suodattimia, ei merkkijonotaikuutta, ei riskiä riippuvuusjärjestyksen rikkomisesta.
Perussyntaksi defer-attribuutille:
1 wp_enqueue_script( 2 'my-js-handle', 3 get_template_directory_uri() . '/js/my-script.js', 4 array('jquery'), 5 '1.0.0', 6 array( 7 'strategy' => 'defer', 8 'in_footer' => true, 9 ) 10 );
async-attribuutille sama mekaniikka:
1 wp_enqueue_script( 2 'google-analytics', 3 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX', 4 array(), 5 '1.0.0', 6 array( 7 'strategy' => 'async', 8 'in_footer' => false, 9 ) 10 );
in_footer-avain taulukon sisällä toimii samoin kuin vanha boolean-parametri: true sijoittaa skriptin footeriin, false <head>-osioon. defer-attribuutille asetat tyypillisesti true (skripti odottaa DOMia joka tapauksessa, ei ole syytä ladata sitä aikaisin), async-attribuutille sen mukaan, mikä toimii.
Natiivimenetelmän suurin etu on, että ydin itse tarkistaa riippuvuuspuun. Jos skripti A, jossa on defer, riippuu skriptistä B, ja B on rekisteröity ilman strategiaa (blokkaava), WordPress ei riko sivustoasi: se automaattisesti alentaa skriptin A strategian blokkaavaksi. script_loader_tag-suodatinta käytettäessä sinulta puuttuu tämä suoja, suodatin yksinkertaisesti lisää attribuutin katsomatta riippuvuuksiin.
Tärkeää: $args-taulukko ilmestyi WordPress 6.3:ssa. Jos teeman tai lisäosan on toimittava vanhemmissa versioissa, käytä menetelmää 2 tai lisää tarkistus:
1 if ( version_compare( $GLOBALS['wp_version'], '6.3', '>=' ) ) { 2 // native method 3 } else { 4 // script_loader_tag filter 5 }
Menetelmä 2: script_loader_tag-suodatin (WordPress 4.1+)
Jos sivusto käyttää versiota, joka on alle 6.3, tai sinun on säilytettävä taaksepäin yhteensopivuus, käytä testattua script_loader_tag-suodatinta. Se on ollut olemassa WordPress 4.1:stä lähtien ja toimii edelleen moitteettomasti.
Suodatin laukeaa juuri ennen kuin <script>-elementti tulostetaan HTML:ään, saat valmiin elementin merkkijonon, skriptin kahvan ja tiedostopolun, ja voit korvata src-kohdan muodossa defer="defer" src tai async="async" src.
Yksittäinen skripti defer-attribuutilla:
1 function add_defer_to_my_script($tag, $handle) { 2 if ( 'my-js-handle' !== $handle ) { 3 return $tag; 4 } 5 return str_replace( ' src', ' defer="defer" src', $tag ); 6 } 7 add_filter('script_loader_tag', 'add_defer_to_my_script', 10, 2);
Koodi sijoitetaan aktiivisen teeman functions.php-tiedostoon tai, oikeaoppisemmin, erilliseen koodinpätkälaajennukseen, kuten Code Snippets tai WPCode. Jos laitat sen lapsiteeman functions.php-tiedostoon, teemaa vaihtaessasi skripteistä tulee taas blokkaavia, etkä huomaa sitä heti.
Skriptin kahva on ensimmäinen parametri, jonka annoit wp_register_script()- tai wp_enqueue_script()-funktiolle. Tämä näkyy if-ehdossa. Älä arvaa kahvaa, avaa lisäosan tai teeman lähdekoodi ja etsi wp_enqueue_script-kutsu.
Defer ja async useille skripteille
Yhden suodattimen lisääminen per skripti on tie paisuneeseen functions.php-tiedostoon ja kopioi-liimaa -virheisiin. Oikea ratkaisu: taulukko kahvoja ja yksi suodatin silmukalla.
1 function add_defer_to_scripts($tag, $handle) { 2 $scripts_to_defer = array( 3 'my-js-handle', 4 'another-handle', 5 'third-party-lib', 6 ); 7 8 foreach ( $scripts_to_defer as $defer_script ) { 9 if ( $defer_script === $handle ) { 10 return str_replace( ' src', ' defer="defer" src', $tag ); 11 } 12 } 13 return $tag; 14 } 15 add_filter('script_loader_tag', 'add_defer_to_scripts', 10, 2);
async-attribuutille vain attribuutti ja taulukon nimi vaihtuvat:
1 function add_async_to_scripts($tag, $handle) { 2 $scripts_to_async = array( 3 'google-tag-manager', 4 'facebook-pixel', 5 'hotjar', 6 ); 7 8 foreach ( $scripts_to_async as $async_script ) { 9 if ( $async_script === $handle ) { 10 return str_replace( ' src', ' async="async" src', $tag ); 11 } 12 } 13 return $tag; 14 } 15 add_filter('script_loader_tag', 'add_async_to_scripts', 10, 2);
Molemmat suodattimet voidaan kytkeä samanaikaisesti, defer omille skripteillesi, async kolmannen osapuolen seurannoille. Ne toimivat itsenäisesti eivätkä ole ristiriidassa keskenään.
Käytännön esimerkki: Google Maps API
Google Maps on klassinen ehdokas defer-attribuutille. Kartta on tyypillisesti yhteystietosivun footerissa, skripti vetää yli 100 kt, eikä käyttäjä tarvitse karttaa heti. Lisäksi itse API ei riipu muista sivun skripteistä, ihanteellinen tapaus.
Yhdistä ja defer:
1 // theme's functions.php 2 function enqueue_google_maps() { 3 if ( ! is_page('contacts') ) { 4 return; 5 } 6 7 wp_enqueue_script( 8 'google-maps-api', 9 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY', 10 array(), 11 null, 12 array( 13 'strategy' => 'defer', 14 'in_footer' => true, 15 ) 16 ); 17 } 18 add_action('wp_enqueue_scripts', 'enqueue_google_maps');
Sama lopputulos script_loader_tag-suodattimella:
1 function add_defer_to_google_maps($tag, $handle) { 2 if ( 'google-maps-api' !== $handle ) { 3 return $tag; 4 } 5 return str_replace( ' src', ' defer="defer" src', $tag ); 6 } 7 add_filter('script_loader_tag', 'add_defer_to_google_maps', 10, 2);
Kummankin vaihtoehdon asentamisen jälkeen tarkista ehdottomasti kartta yhteystietosivulla. Avaa selaimen konsoli (F12), varmista, ettei JavaScript-virheitä ole ja että kartta renderöityi oikein. Jos saat virheen, kuten initMap is not a function, se tarkoittaa, että myös alustusskriptisi on merkittävä defer-attribuutilla ja sijoitettava tiukasti API-yhteyden jälkeen.
Kuinka varmistaa, että defer ja async toimivat
Toteutuksen jälkeen tulee varmennus. Ilman sitä et tiedä, toimiko optimointi vai jäikö se vain kuolleeksi koodiksi.
Avaa sivun lähdekoodi (Ctrl+U) ja etsi skriptisi. <script>-elementissä pitäisi olla attribuutit:
1 <script defer="defer" src="/wp-content/themes/my-theme/js/my-script.js"></script>
Jos attribuutteja ei ole, tarkista, vastaako suodattimen kahva todellista skriptin kahvaa. Yleinen virhe: wp_enqueue_script-kutsussa kahva on my-plugin-frontend, mutta suodattimessa se on my_plugin_frontend. Väliviiva vastaan alaviiva, ja suodatin ohittaa skriptin hiljaisesti.
Viimeinen silaus, Google PageSpeed Insights tai Lighthouse Kehittäjätyökalujen Audits-välilehdellä. "Poista renderöinnin estävät resurssit" -osion pitäisi näyttää parannusta. Tarkka hyöty riippuu skriptien määrästä ja koosta, mutta tyypillisellä WordPress-sivustolla, jossa on 5-7 lisäosaa, 40-60% vähennys blokkaavassa JavaScriptissä on saavutettavissa oleva tulos.
⁉️🤔 Usein kysytyt kysymykset
Voinko käyttää sekä defer- että async-attribuuttia yhdessä skriptissä?
Et. Jos määrität molemmat attribuutit samanaikaisesti, selain jättää
defer-attribuutin huomiotta ja suorittaa skriptinasync-tyyliin. Tämä käytös on leivottu sisään HTML-spesifikaatioon,asyncmenee aina edelle. Valitse yksi sen perusteella, onko suoritusjärjestyksellä väliä.
Mitä tehdä, jos defer-attribuutin lisäämisen jälkeen skripti lakkasi toimimasta?
Todennäköisesti skripti odottaa, ettei DOMia ole vielä rakennettu, ja yrittää manipuloida elementtejä, joita ei ole olemassa suoritushetkellä. Korvaa
defertavallisella blokkaavalla latauksella kyseiselle skriptille. Tai kääri skriptin koodiDOMContentLoaded-tapahtuman sisään, jolloin se voi toimiadefer-attribuutin kanssa ilman virheitä. Jälkimmäinen vaihtoehto on suositeltavampi: säilytät optimoinnin ja korjaat yhteensopivuuden.
Mitä eroa on defer-attribuutilla ja skriptin siirtämisellä footeriin wp_enqueue_script-funktion $in_footer = true -parametrilla?
$in_footer = trueainoastaan siirtää<script>-elementin<head>-osiosta<body>-osion loppuun. Skripti blokkaa edelleen renderöinnin, vain myöhemmin.deferlatautuu rinnakkain HTML:n jäsentämisen kanssa ja suoritetaan tiukasti vasta, kun DOM on rakennettu. Yhdistetty käyttö (in_footer => true+strategy => 'defer') antaa maksimaalisen vaikutuksen: footerissa oleva skripti ei viivästytä ensimmäistä renderöintiä, ja defer takaa, ettei se blokkaa myöskään lopullista renderöintiä.
Pitäisikö WordPress päivittää versioon 6.3 pelkästään natiivimenetelmän vuoksi?
Jos sivusto on versiossa 6.2 tai vanhemmassa, päivittäminen on vaivan arvoista muustakin syystä kuin
strategy-parametrin. WordPress 6.3 paikkasi kymmeniä haavoittuvuuksia ja toi ytimen suorituskykyparannuksia. Mutta jos päivitys on jostain syystä mahdoton,script_loader_tag-suodatin toimii täysin luotettavasti versiosta 4.1, joka julkaistiin vuonna 2014. Et menetä mitään käyttämällä sitä.
Entä jQuery, defer vai jätetäänkö ennalleen?
jQueryn pitäisi latautua
defer-attribuutilla, jos kaikki siitä riippuvat skriptit on myös merkittydefer-attribuutilla. Ongelma on, että WordPress-lisäosat hallitsevat skriptiensä attribuutteja erittäin harvoin. Jos laitatdefer-attribuutin jQuerylle, kun taas yhteydenottolomakelisäosa yhdistää skriptinsä ilman attribuutteja, selain suorittaa lisäosan ennen jQuerya ja lomake hajoaa. Käytännön neuvo: aloitadefer-attribuutilla omille teemasi skripteille. Älä koske jQueryyn ennen kuin olet testannut jokaisen lisäosan sivustolla.
Mitä laittaa tuotantosivustolle vuonna 2026
Jos palvelimella on WordPress 6.3 tai uudempi, vain natiivimenetelmä. Puhdasta koodia, suoja riippuvuuskonflikteilta, ytimen tuki. Aloita defer-attribuutilla kaikille teeman skripteille ja kriittisen tärkeille lisäosille; varaa async analytiikalle ja kolmannen osapuolen widgeteille.
Jos versio on alle 6.3, script_loader_tag-suodatin kahvojen taulukon kanssa. Se on toiminut vuosikymmenen, ei mitään hajoavaa. Ainoa asia, mitä se ei osaa, on tarkistaa riippuvuuspuuta automaattisesti, joten lisää skriptejä taulukkoon yksi kerrallaan ja tarkista sivusto jokaisen jälkeen.
Ja mikä tärkeintä: mikään menetelmä ei korvaa itse skriptien auditointia. Jos gallerialisäosa yhdistää 15 tiedostoa vain näyttääkseen kolme kuvaa, defer tai async eivät radikaalisti auta. Latauksen optimointi alkaa kysymyksestä "tarvitaanko tätä skriptiä ylipäätään", ja vasta sitten "miten se ladataan".
🔗 Virallinen WordPress 6.3 -dokumentaatio, Script Loading Strategies



