jQuery løste reelle nettleserkompatibilitetsproblemer i over et tiår. I 2008, da denne artikkelen først ble publisert, var det virkelig smertefullt å skrive JavaScript på tvers av nettlesere uten jQuery. Internet Explorer 6 håndterte hendelser annerledes, CSS-velgere var inkonsekvente, og AJAX krevde nettleserspesifikke XMLHttpRequest-implementeringer.
Lær mer om WordPress hastighetsoptimalisering hos WPPoland.
I 2026 håndteres hvert problem jQuery løste nativt av nettlesere. Spørsmålet er ikke lenger om man skal migrere, men hvordan man gjør det trygt uten å ødelegge eksisterende funksjonalitet.
Hvorfor jQuery er teknisk gjeld i 2026
jQuery 3.7 veier 87KB ukomprimert (30KB gzipped). Det kan høres lite ut, men vurder hva det koster:
- Total Blocking Time (TBT): jQuery må parses og kjøres før avhengig kode kan kjøre. På mellomklasse mobilenheter legger dette til 150-300ms til TBT.
- Interaction to Next Paint (INP): jQuerys hendelsesdelegeringssystem legger overhead til hver brukerinteraksjon og forverrer INP-scorer målbart.
- Avhengighetskjede: Lasting av jQuery betyr at hvert skript som avhenger av det må vente, noe som skaper en kaskade av blokkerende ressurser.
- Redundant kode: Hver jQuery-metode du kaller har en nativ ekvivalent som nettleseren allerede leverer. Du betaler dobbelt for den samme funksjonaliteten.
Ytelsesmålinger: jQuery vs vanilla JS
Virkelige målinger på et WordPress-tema med typiske interaksjoner (menytogling, fanebytte, skjemavalidering, AJAX last-mer):
| Metrikk | Med jQuery | Uten jQuery | Forbedring |
|---|---|---|---|
| Total JS-størrelse | 142KB | 55KB | -61% |
| TBT (mobil) | 480ms | 180ms | -62% |
| INP (p75) | 220ms | 95ms | -57% |
| LCP | 2.1s | 1.7s | -19% |
| Lighthouse ytelse | 72 | 94 | +22 poeng |
Disse tallene kommer fra et WordPress-nettsted i produksjon som kjører GeneratePress med WooCommerce, testet på en Moto G Power (en representativ mellomklasseenhet).
Moderne JavaScript (ES2024+) erstatter hvert jQuery-mønster
ES2024-spesifikasjonen, fullt støttet i Chrome 124+, Firefox 126+, Safari 17.4+ og Edge 124+, gir native alternativer for hvert vanlig jQuery-mønster.
DOM-seleksjon
// jQuery
const $buttons = $('.btn');
const $container = $('#main-container');
const $firstItem = $('.menu-item:first');
// Vanilla JS (ES2024+)
const buttons = document.querySelectorAll('.btn');
const container = document.getElementById('main-container');
const firstItem = document.querySelector('.menu-item');
// Avgrenset seleksjon (som jQuery .find())
const navLinks = container.querySelectorAll('a.nav-link');
Viktig forskjell: querySelectorAll returnerer en statisk NodeList, ikke en levende samling. Dette er faktisk tryggere fordi listen ikke endres uventet når DOM-en muterer.
Hendelseshåndtering
// jQuery
$('.btn').click(function () {
$(this).toggleClass('active');
});
$('.menu').on('click', '.menu-item', function () {
// delegert hendelse
});
// Vanilla JS
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener('click', () => {
btn.classList.toggle('active');
});
});
// Hendelsesdelegering (erstatter .on() med velger)
document.querySelector('.menu').addEventListener('click', (e) => {
const item = e.target.closest('.menu-item');
if (item) {
// håndter menyelement-klikk
}
});
Metoden closest() er den moderne ekvivalenten til jQuerys delegerte hendelsesmatching. Den traverserer DOM-treet oppover for å finne den nærmeste forfaderen som matcher en velger.
Klassemanipulering
// jQuery
$el.addClass('active');
$el.removeClass('hidden');
$el.toggleClass('open');
$el.hasClass('visible');
// Vanilla JS
el.classList.add('active');
el.classList.remove('hidden');
el.classList.toggle('open');
el.classList.contains('visible');
// Flere klasser samtidig
el.classList.add('active', 'highlighted', 'animate-in');
el.classList.remove('hidden', 'collapsed');
AJAX med fetch API og async/await
// jQuery
$.ajax({
url: '/wp-json/wp/v2/posts',
method: 'GET',
data: { per_page: 5 },
success: function (posts) { renderPosts(posts); },
error: function (xhr) { console.error(xhr); }
});
// Vanilla JS (moderne async/await)
async function loadPosts() {
try {
const response = await fetch('/wp-json/wp/v2/posts?per_page=5');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const posts = await response.json();
renderPosts(posts);
} catch (error) {
console.error('Kunne ikke laste innlegg:', error);
}
}
// POST med nonce (WordPress-mønster)
async function submitForm(data) {
const response = await fetch('/wp-json/custom/v1/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce,
},
body: JSON.stringify(data),
});
return response.json();
}
Animasjoner uten jQuery
jQuerys .fadeIn(), .slideDown() og .animate() kan alle erstattes med CSS-overganger, CSS-animasjoner eller Web Animations API.
// jQuery
$('.panel').slideDown(300);
$('.modal').fadeIn(200);
// CSS-tilnærming (foretrukket for ytelse)
// I CSS:
// .panel { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; }
// .panel.open { max-height: 500px; }
// I JS:
panel.classList.add('open');
// Web Animations API (for komplekse, programmatiske animasjoner)
modal.animate(
[
{ opacity: 0, transform: 'scale(0.95)' },
{ opacity: 1, transform: 'scale(1)' },
],
{ duration: 200, easing: 'ease-out', fill: 'forwards' }
);
Web Animations API kjører på kompositor-tråden, noe som betyr at animasjoner ikke blokkerer hovedtråden. jQuery-animasjoner kjører på hovedtråden og forårsaker jank på tregere enheter.
DOM-manipulering
// jQuery
$('<div class="notice">Hei</div>').appendTo('#container');
$('.old-element').replaceWith('<span>Ny</span>');
$('.item').remove();
$('.list').empty();
// Vanilla JS
const notice = document.createElement('div');
notice.className = 'notice';
notice.textContent = 'Hei';
container.append(notice);
// Eller bruk insertAdjacentHTML for HTML-strenger
container.insertAdjacentHTML('beforeend', '<div class="notice">Hei</div>');
// Erstatt
oldElement.replaceWith(Object.assign(document.createElement('span'), { textContent: 'Ny' }));
// Fjern
item.remove();
// Tøm
list.replaceChildren();
Document ready
// jQuery
$(document).ready(function () { /* ... */ });
$(function () { /* snarvei */ });
// Vanilla JS
document.addEventListener('DOMContentLoaded', () => {
// DOM er klar
});
// Eller plasser <script>-taggen din med type="module" på slutten av <body>
// Moduler er utsatt som standard, så DOM-en er allerede klar
Web Components: den moderne erstatningen for jQuery-plugins
jQuery-plugins ga gjenbrukbare UI-komponenter (slidere, modaler, faner, trekkspill). I 2026 tilbyr Web Components et standardbasert alternativ med bedre innkapsling.
Eksempel: en toggle-panel-komponent
class TogglePanel extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
const title = this.getAttribute('title') || 'Bytt';
this.shadowRoot.innerHTML = `
<style>
:host { display: block; margin: 1rem 0; }
button {
width: 100%; padding: 0.75rem 1rem;
background: #f5f5f5; border: 1px solid #ddd;
cursor: pointer; text-align: left;
font-size: 1rem; font-weight: 600;
}
.content {
display: none; padding: 1rem;
border: 1px solid #ddd; border-top: none;
}
:host([open]) .content { display: block; }
</style>
<button part="trigger">${title}</button>
<div class="content"><slot></slot></div>
`;
this.shadowRoot.querySelector('button').addEventListener('click', () => {
this.toggleAttribute('open');
});
}
}
customElements.define('toggle-panel', TogglePanel);
Bruk i HTML:
<toggle-panel title="Fraktinformasjon">
<p>Gratis frakt på bestillinger over 50 EUR.</p>
</toggle-panel>
Web Components gir Shadow DOM-innkapsling (stiler lekker ikke ut), slotter for innholdsprojeksjon og livssyklus-callbacks. De fungerer i alle moderne nettlesere uten polyfills.
Når bruke Web Components vs. et rammeverk
| Scenario | Anbefaling |
|---|---|
| Enkel interaktiv widget (trekkspill, faner, modal) | Web Component |
| Full SPA (enkeltsideapplikasjon) | React / Vue / Svelte |
| WordPress-blokk (Gutenberg) | React (WordPress-standard) |
| Delt komponent på tvers av flere nettsteder | Web Component |
| Kompleks tilstandshåndtering | Rammeverk med tilstandsbibliotek |
Migreringsstrategi for WordPress-prosjekter
Trinn 1: Undersøk jQuery-bruken din
Kjør denne kommandoen i temamappen din for å finne alle jQuery-referanser:
grep -rn '\$(\|jQuery\.\|jQuery(' --include='*.js' --include='*.php' .
Kategoriser hver bruk:
- Din kode (tema/egendefinert plugin): migrer dette
- Tredjeparts plugin: la det være, pluginet håndterer sine egne avhengigheter
- WordPress admin: ikke rør, WordPress-kjernen håndterer dette
Trinn 2: Lag en migreringsplan
Prioriter etter påvirkning:
- Frontend-temakode (påvirker hver besøkende) - migrer først
- Egendefinert plugin-frontend - migrer som nummer to
- Admin-tilpasninger - migrer sist (lavere trafikk)
Trinn 3: Erstatt mønstre trinnvis
Ikke skriv om alt på en gang. Erstatt en fil om gangen:
- Fjern
array('jquery')fra filenswp_enqueue_script-avhengighetsarray - Erstatt alle jQuery-mønstre med vanilla JS-ekvivalenter
- Test i Chrome, Firefox, Safari og Edge
- Test med alle aktive plugins aktivert
- Kjør Lighthouse før og etter for å måle forbedringen
Trinn 4: Håndter WordPress AJAX-mønsteret
WordPress legacy AJAX bruker admin-ajax.php med jQuery:
// Gammelt mønster (jQuery + admin-ajax)
jQuery.post(ajaxurl, {
action: 'my_custom_action',
nonce: myData.nonce,
post_id: 123,
}, function (response) {
console.log(response);
});
// Moderne mønster (fetch + REST API)
async function myCustomAction(postId) {
const response = await fetch('/wp-json/myplugin/v1/action', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': myData.nonce,
},
body: JSON.stringify({ post_id: postId }),
});
return response.json();
}
REST API-tilnærmingen er raskere (ingen admin-ajax.php-overhead), mer cachebar og følger moderne WordPress-utviklingsstandarder.
Trinn 5: Registrer skript riktig
// Før (med jQuery-avhengighet)
wp_enqueue_script(
'my-theme-scripts',
get_template_directory_uri() . '/js/main.js',
array('jquery'),
'1.0.0',
true
);
// Etter (uten jQuery, med modulstøtte)
wp_enqueue_script_module(
'my-theme-scripts',
get_template_directory_uri() . '/js/main.js',
array(),
'2.0.0'
);
WordPress 6.5+ støtter wp_enqueue_script_module() som laster skript som ES-moduler med type="module", noe som muliggjør nativ import/export-syntaks.
Når det fortsatt gir mening å beholde jQuery
jQuery kan fortsatt være berettiget hvis:
- Legacy-kodebase med over 50 jQuery-plugin-avhengigheter: Migreringskostnaden overstiger ytelsesgevinsten. Planlegg en gradvis utfasing over 6-12 måneder.
- WordPress admin-tilpasninger: Admin-området laster allerede jQuery. Å legge til egne admin-skript med jQuery-avhengighet koster ingenting ekstra.
- Krav fra tredjepartsplugins: Noen populære plugins (visse skjemabyggere, sidebyggere) krever jQuery. Ikke kjemp mot avhengigheten hvis du ikke kan kontrollere den.
- Kompetansegap i teamet: Hvis utviklingsteamet ditt ikke er komfortable med moderne JS, invester i opplæring før du tvinger en migrering. Forståelse av hva en WordPress-utvikler gjør hjelper med å sette realistiske forventninger til ferdighetene som trengs under migrering.
Målet er pragmatisk forbedring, ikke ideologisk renhet. Fjern jQuery der det koster deg ytelse og ikke tilfører verdi. Behold det der fjerning ville ødelegge ting eller koste mer enn det sparer.
ES2024+-funksjoner som erstatter vanlige jQuery-verktøy
Strukturert klon (dyp kopi)
// jQuery
const copy = $.extend(true, {}, original);
// ES2024+
const copy = structuredClone(original);
Array-lignende iterasjon
// jQuery
$.each(items, function (index, item) { /* ... */ });
// ES2024+
items.forEach((item, index) => { /* ... */ });
// Eller med Array.from for NodeLists
Array.from(document.querySelectorAll('.item')).map(item => item.textContent);
// Eller spread-operator
[...document.querySelectorAll('.item')].filter(item => item.dataset.active);
Deferred/Promise-mønstre
// jQuery
const deferred = $.Deferred();
deferred.resolve('ferdig');
deferred.promise().then(val => console.log(val));
// ES2024+
const promise = new Promise((resolve) => resolve('ferdig'));
promise.then(val => console.log(val));
// Promise.withResolvers() - ES2024-funksjon
const { promise, resolve, reject } = Promise.withResolvers();
IntersectionObserver (erstatter jQuery scroll-behandlere)
// jQuery (kostbar scroll-behandler)
$(window).scroll(function () {
$('.lazy-image').each(function () {
if ($(this).offset().top < $(window).scrollTop() + $(window).height()) {
$(this).attr('src', $(this).data('src'));
}
});
});
// Vanilla JS (ytelseseffektiv, utenfor hovedtråden)
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('.lazy-image').forEach(img => observer.observe(img));
Alternativer i form av verktøybiblioteker (hvis du trenger en hjelper)
Hvis du finner deg selv i å skrive de samme vanilla JS-mønstrene gjentatte ganger, vurder et mikrobibliotek i stedet for jQuery:
| Bibliotek | Størrelse | Formål |
|---|---|---|
| Alpine.js | 15KB | Deklarativ reaktivitet (x-data, x-on) |
| htmx | 14KB | AJAX, WebSocket, SSE via HTML-attributter |
| Petite-Vue | 6KB | Vue-kompatibel mal-syntaks |
| Ingen (vanilla) | 0KB | Best ytelse, full kontroll |
For WordPress-temaer i 2026 er anbefalingen vanilla JS for enkle interaksjoner og Alpine.js eller htmx hvis du trenger deklarativ oppførsel uten et fullt rammeverk.
jQuery best practices i 2026
Hvis du fortsatt vedlikeholder jQuery-kode - enten av eget valg eller fordi en eldre kodebase krever det - minimerer disse praksisene skaden:
- Last jQuery fra WordPress-kjernen, aldri fra et CDN. WordPress bunder en kompatibel versjon. Å laste en ekstra kopi fra
cdnjsellercode.jquery.combetyr dobbel vekt og potensielle versjonskonflikter. - Bruk
jQueryi stedet for$i WordPress. WordPress kjører jQuery i no-conflict-modus. Å pakke kode ijQuery(function($) { ... })forhindrer kollisjoner med andre biblioteker. - Unngå nesting av
.ready(). En enkeltjQuery(function($) { ... })er nok. Nestede.ready()-kall skaper callback-pyramider og forvirrer kjøringsrekkefølgen. - Cache velgere. Hvert
$('.my-class')-kall traverserer DOM-en. Lagre resultater i en variabel når du bruker samme velger mer enn en gang. - Deleger hendelser i stedet for å binde til individuelle elementer. Bruk
$(parent).on('click', '.child', handler)i stedet for$('.child').click(handler). Dette håndterer dynamisk tillagte elementer og bruker færre hendelseslyttere. - Ikke bruk jQuery for CSS-animasjoner. Bruk CSS-overganger eller Web Animations API. jQuerys
.animate()kjører på hovedtråden og forårsaker jank. - Sett
jquerysom avhengighet kun når det er nødvendig. Hvis en skriptfil ikke bruker jQuery, fjern det frawp_enqueue_script-avhengighetsarrayet for å unngå unødvendig lasting av jQuery.
Nyeste jQuery-versjon og hva som endret seg
Per 2026 er jQuery 3.7.1 den nyeste stabile utgivelsen (utgitt august 2023). jQuery 4.0.0-beta.2 har vært i beta siden februar 2024, uten annonsert dato for stabil utgivelse.
jQuery 4.0-endringer som er viktige for WordPress:
| Endring | Påvirkning |
|---|---|
| Dropper IE 11-støtte | Ingen effekt - WordPress 6.6+ droppet allerede IE 11 |
Fjerner utdaterte API-er (.click(), .bind(), .delegate()) | Plugins som bruker disse vil slutte å fungere |
| Mindre bundle (~68KB vs 87KB) | Beskjeden forbedring, fortsatt tyngre enn ingen jQuery |
FormData-basert $.ajax() for filopplasting | Finere API, men fetch() gjør dette nativt |
WordPress-kjernen leverer for tiden jQuery 3.7.1 og har ikke forpliktet seg til å bunde 4.0. Den praktiske konklusjonen: ikke vent på jQuery 4 for å forbedre ytelsen. Migrer til vanilla JS der det er mulig, og bruk jQuery 3.7.1 best practices der migrering ennå ikke er gjennomførbar.
Hvem bruker fortsatt jQuery i 2026
jQuery lastes fortsatt på anslagsvis 77% av alle nettsteder (ifølge W3Techs), hovedsakelig fordi WordPress, Shopify og eldre bedriftssystemer inkluderer det som standard. Men “lastet” betyr ikke “nødvendig.”
Oversikten:
- WordPress-nettsteder: jQuery lastes på praktisk talt hver WordPress-side fordi admin-baren og mange populære plugins er avhengige av det. På frontend er den faktiske avhengigheten ofte bare ett eller to skript.
- Shopify-temaer: De fleste Shopify-temaer bunder jQuery for handlekurvinteraksjoner. Shopify har ikke beveget seg mot å avvikle det.
- Eldre bedriftssystemer: Banker, offentlige portaler og store e-handelsplattformer har ofte jQuery innebygd i kodebaser som stammer fra 2010-2015. Migrering er kostbar og lavt prioritert.
- Nye prosjekter: Nesten ingen. React, Vue, Svelte og vanilla JS dominerer nyutvikling. Ingen moderne rammeverk eller startmal inkluderer jQuery.
Hvis du starter et nytt WordPress-tema eller -plugin i 2026, er det ingen grunn til å legge til jQuery som avhengighet. Nettleser-API-ene er tilstrekkelige for hvert vanlig mønster. For mer om å bygge plugins på riktig måte, se seksjonen om WordPress-plugin best practices i vår plugin-stack-guide.
Konklusjon: sjekklisten for migrering
- Undersøk all jQuery-bruk i temaet og egendefinerte plugins
- Mål nåværende Core Web Vitals som referanseverdi
- Erstatt frontend-temakode først (størst besøkspåvirkning)
- Bruk
querySelector,addEventListener,fetch,classListog Web Animations API - Vurder Web Components for gjenbrukbare UI-elementer
- Bruk
wp_enqueue_script_module()for ES-modulstøtte - Test i alle store nettlesere etter hver filmigrering
- Mål Core Web Vitals igjen og dokumenter forbedringen
- Behold jQuery kun for admin-skript og tredjeparts plugin-avhengigheter
- Lær opp teamet ditt i moderne JavaScript-mønstre
Webplattformen i 2026 gir alt jQuery tilbød, og mer. Hvert kilobyte med unødvendig JavaScript du fjerner gjør WordPress-nettstedet ditt raskere, mer tilgjengelig og enklere å vedlikeholde.


