En eldre WordPress-kodebase er en kodebase der ingen kan forutsi hva en endring vil ødelegge. Alderen er ikke problemet, det er mangelen på målinger. Denne guiden handler om å skaffe de målingene først, og deretter bytte ut koden i en rekkefølge der hvert steg kan rulles tilbake.
Sidene vi snakker om, kjenner du igjen med en gang: bygget mellom 2015 og 2020, et klassisk tema med en functions.php som har passert to tusen linjer, flere spesiallagde utvidelser uten upstream-repositorium og en wp_options-tabell ingen har sett på siden lanseringen. Som regel virker de fortsatt. Det som har sluttet å virke, er muligheten til å endre dem uten overraskelser.
WordPress 7.1.1 kom 17. september 2026. Avstanden mellom den versjonen og en stack fra 2018 ligger sjelden i kjernen. Den ligger i PHP-versjonen under, i skriptene temaet legger i kø, og i en database som i årevis har samlet rader fra utvidelser som ikke finnes lenger. Å bygge alt på nytt fra bunnen av er ofte for dyrt eller for risikabelt, og det er her en kontrollert modernisering kommer inn.
Les mer om profesjonell WordPress-utvikling hos WPPoland.
1. Hvordan revidere et eldre WordPress-nettsted
Start med tallene du kan lese av et nettsted i produksjon, ikke med en mening om koden.
Minste og anbefalte PHP-versjon for WordPress
Gulvet og anbefalingen er to forskjellige ting. WordPress trunk setter fortsatt $required_php_version = '7.4' i src/wp-includes/version.php, mens kravsiden anbefaler PHP 8.3 eller nyere og MariaDB 10.11 eller MySQL 8.0. Kjernen starter altså på 7.4, og å starte på 7.4 betyr å kjøre uten sikkerhetsoppdateringer.
Det som avgjør migreringen, er datoene på php.net, ikke en lovet prosentvis forbedring:
| PHP-gren | Status per 20. september 2026 |
|---|---|
| 7.4 | Slutt på levetid 28. november 2022 |
| 8.0 | Slutt på levetid 26. november 2023 |
| 8.1 | Slutt på sikkerhetsstøtte 31. desember 2025 |
| 8.2 | Sikkerhetsstøtte til 31. desember 2026 |
| 8.3 og nyere | Aktiv støtte |
En plan som sikter mot 8.2, har omtrent tre måneders margin. Sikt mot 8.3 eller 8.4.
Et nettsted på 7.4, 8.0 eller 8.1 fikk ingen ny versjon da de kritiske PHP-sårbarhetene ble rettet 21. oktober 2026. Stegene for et slikt nettsted står i hva du gjør med PHP2Shell på et WordPress-nettsted.
Slik logger du utdaterte funksjoner i produksjon uten WP_DEBUG
Det er her de fleste revisjoner bommer. Kjernen kjører do_action( 'deprecated_function_run', ... ) inne i _deprecated_function() før den sjekker WP_DEBUG; det eneste som er betinget, er kallet til trigger_error(). Det samme gjelder deprecated_hook_run, deprecated_argument_run, deprecated_file_included, deprecated_class_run og deprecated_constructor_run. En liten mu-plugin gir deg en reell oversikt fra live trafikk uten å vise noe på skjermen:
<?php
// mu-plugins/deprecation-log.php
$hooks = array(
'deprecated_function_run',
'deprecated_hook_run',
'deprecated_argument_run',
'deprecated_file_included',
'deprecated_class_run',
'deprecated_constructor_run',
);
foreach ( $hooks as $hook ) {
add_action(
$hook,
static function () use ( $hook ) {
error_log( $hook . ' ' . wp_json_encode( func_get_args() ) );
},
10,
4
);
}La den gå gjennom en hel forretningssyklus. En ukentlig import eller en kvartalsvis rapportside treffer utdatert kode som ingen gjennomsøking av frontenden når.
Slik verifiserer du WordPress-sjekksummer med WP-CLI
wp core verify-checksums og wp plugin verify-checksums sammenligner det som er installert, med hashene fra WordPress.org. På et nettsted med ti års historikk finner dette nesten alltid en utvidelse som er lappet for hånd av noen som ikke lenger er i teamet. Det er de filene som rulles tilbake ved neste oppdatering, og det er de som først skal inn i versjonskontroll.
Hvor mange jQuery-versjoner laster et gammelt WordPress-nettsted
Før du gir jQuery skylden, tell hvor mange kopier som finnes. Kjernen registrerer nøyaktig én: script-loader.php deklarerer jquery-core i versjon 3.7.1 og jquery-migrate i 3.4.1, med jquery som alias som avhenger av begge. Dukker det opp flere versjoner på en side, kommer de fra utvidelser og temaer som legger sin egen kopi i kø under et annet handle, eller som skriver en <script src>-tagg rett i footeren. wp_scripts()->queue viser deg hvilken som er hvilken på et minutt. Å avregistrere kjernens jQuery for å tvinge fram en CDN-kopi er nettopp endringen som ødelegger adminpanelet: la kjernens handle være i fred og fjern duplikatene. Mer om veien videre finner du i guiden om overgang fra jQuery til vanilla JS.
jquery-migrate fortjener en egen beslutning. Å fjerne den fra køen er én linje, og fylles konsollen da med feil, er de feilene den reelle listen over jQuery 1.x-mønstre som fortsatt finnes i temaet.
PHP-kompatibilitetsskanning med PHPCompatibilityWP
PHPCompatibilityWP finnes for at sniffene ikke skal flagge polyfillene kjernen allerede har med:
vendor/bin/phpcs -p wp-content/themes wp-content/plugins \
--standard=PHPCompatibilityWP \
--extensions=php \
--runtime-set testVersion 8.3-Uten testVersion sier resultatet svært lite. Med den får du en filliste sortert etter hva som skiller deg fra versjonen du vil nå.
Oversikten du bør ha etter første uke, har fire kolonner: nåværende PHP-versjon, deprecations per endepunkt, filer som feiler sjekksummen, og PHPCS-feil per utvidelse. Alt som kommer etterpå, prioriteres ut fra den tabellen.
Oppdatering . PHPCompatibilityWP viser hva som slutter å virke på en nyere PHP-versjon. Mye av rettingen kan automatiseres med Rector. Ifølge utgivelsesnotatene er versjon 2.8 fra 26. oktober 2026 omtrent 26 % raskere enn 2.7, og omtrent tre ganger raskere på PHP 8.3 eller nyere med utvidelsen PHPStan Turbo. Reglene kommer nå frem til resultatet i én kjøring og testes for idempotens, så en ny kjøring på samme fil endrer ingenting. På et eldre prosjekt anbefaler Rector-dokumentasjonen ->withPhpLevel() og å heve nivået ett steg av gangen i stedet for hele ->withPhpSets() på én gang. Kjør hver runde i en egen gren og gå gjennom diffen før den går i produksjon.
2. Hvordan refaktorere WordPress med strangler fig-mønsteret
Ikke prøv å endre alt på én gang. Strangler fig fra Martin Fowler, skrevet i 2004 og revidert i august 2024, er den eneste omskrivingsstrategien som holder et nettsted som tjener penger i drift: sett det nye systemet ved siden av det gamle, send en del av trafikken til det nye og la det gamle krympe til det ikke er noe igjen å kutte.
WordPress har to naturlige sømmer for dette, og begge ligger i kjernen.
Fase 1: oppdater kjernen og infrastrukturen
Før du flytter maler, må infrastrukturen være i orden: PHP på en gren med støtte, WordPress på siste stabile versjon, MySQL 8.0 eller MariaDB 10.11 i tråd med kravsiden, HTTPS på hele nettstedet og sikkerhetskopier som noen faktisk har gjenopprettet minst én gang.
Fase 2: migrer maler rute for rute
Den første sømmen er template_include. Det er et filter, så én enkelt rute kan gå over til ny kode mens alle de andre fortsatt går gjennom de gamle malene. Det holder for å flytte kontaktsiden, karrieresiden eller en innholdstype til en omskrevet mal med egne ressurser, og for å flytte den tilbake med én linje hvis konverteringen faller.
Den andre er hybridstøtten for blokkmaler. locate_block_template(), i src/wp-includes/block-template.php, avslutter tidlig med mindre current_theme_supports( 'block-templates' ) er sann, og når den støtten er deklarert, vurderer den bare blokkmaler med lik eller høyere spesifisitet enn PHP-malen hierarkiet allerede har funnet. I praksis:
add_action(
'after_setup_theme',
static function () {
add_theme_support( 'block-templates' );
}
);Fra da av overtar en fil templates/page-contact.html i det klassiske temaet nøyaktig den ruten. single.php, archive.php og resten forblir som før. Dette er mekanismen som gjør “migrer til blokker” om til en serie små leveranser i stedet for en helg med en tilbakerullingsplan ingen har testet.
Sorter delene etter risiko, ikke etter entusiasme. En god første del er en mal med reell trafikk, et målbart resultat og ingen kasse inni. En dårlig første del er forsiden, fordi den gir størst mulig skadeomfang den dagen du kjenner den nye koden minst.
Fase 3: fas ut de gamle PHP-malene
Kvel de gamle PHP-malene til hele nettstedet kjører på den moderne stacken. To regler får dette til å holde. Hver del tar med seg egne ressurser, slik at den nye malen ikke arver det gamle globale stilarket ved et uhell. Og den gamle koden slettes i samme leveranse som pensjonerer den, fordi en død mal som blir liggende i repositoriet, vil bli redigert av noen innen seks måneder.
3. Hvordan rydde i databasen på et gammelt WordPress-nettsted
Nesten alle meldinger om at “databasen er treg” på et gammelt WordPress koker ned til tre ting, og bare én av dem har med størrelse å gjøre.
Slik reduserer du autoload i wp_options
Autoload er den du betaler for i hver forespørsel. Siden WordPress 6.6 lagrer kolonnen autoload ikke bare yes og no. Utviklernotatet om Options API innførte on, off, auto-on, auto-off og auto, og wp_filter_default_autoload_value_via_option_size(), i src/wp-includes/option.php, nekter å autolaste en serialisert verdi som overstiger filteret wp_max_autoloaded_option_size, med 150000 byte som standard. Den beskyttelsen slår inn når opsjonen skrives. Den gjør ingenting med blob-en en avinstallert utvidelse la igjen i 2019.
Les den faktiske listen med SQL, ikke med panelet til en utvidelse:
SELECT option_name, LENGTH(option_value) AS bytes, autoload
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 25;Disse fire verdiene er de wp_load_alloptions() behandler som autolastet. Det betyr noe, fordi wp option list --autoload=on --format=total_bytes i WP-CLI bare treffer autoload='on' OR autoload='yes'. På et nettsted med 6.6 eller nyere, der nye opsjoner legges inn som auto, rapporterer den kommandoen et mindre autoload-avtrykk enn det du betaler for ved hver sidelasting. Bruk spørringen, eller les WP-CLI-tallet med vissheten om hva det utelater.
Slik rydder du foreldreløs postmeta
Foreldreløs postmeta er en opptelling, ikke et mysterium. Tell den før du bestemmer at den betyr noe:
SELECT COUNT(*)
FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;Rader uten et gjenværende innlegg kan slettes, og du tar uansett en dump av databasen først. Meta som tilhører en utvidelse du allerede har fjernet, er en egen og mer forsiktig runde: grupper etter meta_key, sammenlign prefiksene med utvidelsene du fortsatt bruker, og slett per nøkkel.
Gamle revisjoner er den tredje blokken, og verdien i post_type står på engelsk også på et norsk nettsted:
DELETE FROM wp_posts
WHERE post_type = 'revision'
AND post_date < DATE_SUB(NOW(), INTERVAL 6 MONTH);Indekser i wp_postmeta, InnoDB og utf8mb4
Indeksene er delen ingen leser. src/wp-admin/includes/schema.php gir wp_postmeta en primærnøkkel på meta_id, en nøkkel post_id og en nøkkel meta_key avkortet til 191 tegn, fordi utf8mb4 bruker fire byte per tegn og den historiske indeksgrensen var 767 byte. Det finnes ingen sammensatt indeks på (post_id, meta_key). En spørring som filtrerer på begge kolonnene, som er det en arkivmal tung på meta gjør for hver rad, kan ikke bruke én indeks for begge. På et stort nettsted er løsningen en sammensatt indeks lagt til via en migrering, ikke enda et cachelag oppå. Mer om moderne indeksering i WordPress-databasen finner du i databaseguiden.
To kontroller til hører hjemme i samme runde. Bekreft at alle tabellene er InnoDB, fordi en MyISAM-tabell arvet fra en import fra MySQL 5.1-tiden låser ved skriving og ignorerer transaksjoner. Og bekreft at tegnsettet er utf8mb4: kjernen velger utf8mb4_unicode_520_ci i determine_charset() når serveren støtter det, men en database opprettet før WordPress 4.2 og migrert med mysqldump vil fortsatt stå på utf8 og fortsatt i stillhet miste tegn utenfor det grunnleggende planet.
4. Hvordan modernisere CSS og JavaScript i et eldre tema
Frontenden på et eldre WordPress er sjelden treg på grunn av rammeverket den bruker. Den er treg fordi ingenting i temaet vet hva resten legger i kø.
Slik deler du en monolittisk style.css i moduler
Et eldre tema med én håndredigert style.css og ingen bundler har ingen måte å levere en avgrenset endring på. Om resultatet blir Tailwind, CSS modules eller egendefinerte egenskaper, betyr mye mindre enn om du kan svare på “hvilke selektorer trenger denne malen”. En struktur som lar deg svare på det, ser omtrent slik ut:
styles/
├── critical.css (inline i <head>)
├── components/
│ ├── header.css (på alle sider)
│ ├── blog.css (bare på bloggsider)
│ └── product.css (bare på produktsider)
└── utilities.css (delte hjelpeklasser)Når et bygg først finnes, blir ressurslasting per mal mulig, og det er lastingen per mal som flytter renderingsstien, ikke valget av rammeverk.
Slik laster du skript med defer og async i WordPress
Bruk lastestrategien kjernen allerede har. Siden WordPress 6.3 godtar wp_enqueue_script() en array i den siste parameteren:
wp_enqueue_script(
'site-main',
get_theme_file_uri( 'build/main.js' ),
array(),
filemtime( get_theme_file_path( 'build/main.js' ) ),
array(
'strategy' => 'defer',
'in_footer' => true,
)
);Fellen er dokumentert i utviklernotatet for 6.3 og implementert i WP_Scripts::filter_eligible_strategies(): kjernen går gjennom avhengighetstreet, og hvis et skript i køen som avhenger av ditt, ikke også er utsatt, skrives ditt ut som blokkerende. Du kan sette defer på et handle, ikke se noe defer-attributt i HTML-en og ikke ha noe i loggen. Kjernen skriver data-wp-strategy på taggen hver gang en utsatt strategi ble registrert, enten den ble nedgradert eller ikke, så et søk etter bare det attributtet returnerer alle utsatte skript. Tegnet på nedgradering er en tagg med data-wp-strategy og uten tilsvarende defer eller async. Én gammel utvidelse som legger i kø et blokkerende skript som avhenger av bundelen din, er nok til å velte hele endringen.
Den samme filen avviser også en strategi på et alias-handle, og det er derfor wp_script_add_data( 'jquery', 'strategy', 'defer' ) ikke gjør noe nyttig: jquery har ingen src.
Slik fjerner du jQuery fra et eldre tema
Prosessen er gradvis og bygger på oversikten fra seksjon 1:
- List opp handlene i køen med
wp_scripts()->queueog skill kjernens jQuery fra duplikatkopiene. - Finn ut hvilke utvidelser som avhenger av handlet
jquery. - Fjern
jquery-migratefra køen og behandle konsollfeilene som arbeidslisten. - Erstatt enkle funksjoner med ren JavaScript.
- Fjern avhengigheten når ingenting lenger ber om den.
5. Hvordan sikre et gammelt WordPress-nettsted
Eldre kode er ikke usikker fordi den er gammel. Den er usikker fordi flatene den eksponerer, ble konfigurert da standardverdiene var andre.
Verktøy for sikkerhetsskanning av WordPress
En planlagt sjekksumverifisering, en deprecation-logg og varsler om filintegritet er mer verdt enn en skanner som returnerer en alvorlighetsscore. De vanlige verktøyene for resten av runden er PHPStan for statisk analyse av PHP, npm audit for JavaScript-avhengigheter og WPScan for allerede publiserte sårbarheter.
Slik begrenser du WordPress REST API
REST API kan ikke slås av, og snuttene som påstår å gjøre det, er verre enn å la være: kjernen bruker det til blokkredigereren, Site Health og applikasjonspassord. Det du kan gjøre, er å kreve autentisering for alt som ikke er eksplisitt offentlig:
add_filter(
'rest_authentication_errors',
static function ( $result ) {
if ( ! empty( $result ) || is_user_logged_in() ) {
return $result;
}
return new WP_Error(
'rest_not_logged_in',
__( 'Tilgang til REST API krever autentisering.' ),
array( 'status' => 401 )
);
}
);Test deretter, uten å være innlogget, de delene av nettstedet som er avhengige av det: kommentarskjemaer, søkeblokker, kontaktskjemaer bygget på REST-endepunkter og enhver headless-klient. På et markedsføringsnettsted for en bedrift er dette filteret som regel ufarlig. På et nettsted med en interaktiv funksjon for anonyme besøkende vil det ødelegge den, og det er bedre å oppdage i staging.
Vit hva som allerede er begrenset før du legger til regler. Brukerendepunktet er en tilbakevendende skrekk, men WP_REST_Users_Controller bruker has_published_posts på samlingsforespørsler hver gang kalleren ikke består current_user_can( 'list_users' ), noe som dekker både besøkende uten økt og kontoer med få rettigheter. Innholdstypene den godtar, er get_post_types( array( 'show_in_rest' => true ) ), ikke de offentlige, og de to listene er ikke like. Endepunktet returnerer altså forfattere som har publisert i en type som er eksponert i REST, ikke alle kontoer. Forfatteropplisting på et bedriftsnettsted lekker som regel gjennom omdirigeringene fra /?author=1 og forfatterarkivene, ikke gjennom REST.
Applikasjonspassord fungerer dessuten bare over HTTPS: wp_is_application_passwords_supported() returnerer is_ssl() || 'local' === wp_get_environment_type(). Et gammelt nettsted som fortsatt leverer adminpanelet med blandet innhold over ren HTTP, tilbyr dem ikke, og derfor ender integrasjoner på slike nettsteder med å dele det ekte passordet til en administrator. Å fikse sertifikatet er sikkerhetsrettingen; applikasjonspassordet er konsekvensen.
Slik oppdaterer du avhengighetene i et gammelt WordPress
Hvert tredjepartsbibliotek oppdateres eller erstattes:
- PHP-biblioteker med publiserte sårbarheter
- JavaScript-komponenter med aktive CVE-er
- Fonter og ressurser lastet fra tredjeparts-CDN
- Integrasjoner mot API-er som er pensjonert
Gjør samtidig en gjennomgang av utvidelsene, fordi hver utvidelse du fjerner, er en flate du slipper å vedlikeholde. Hvorfor for mange utvidelser også koster ytelse, står i en egen guide.
6. Hvordan migrere til Gutenberg fra et klassisk tema
Kompatibilitet mellom eldre tema og Gutenberg
For temaer bygget mellom 2015 og 2018 slås støtten på bit for bit. add_theme_support( 'block-templates' ) er bryteren som åpner for migreringen mal for mal fra seksjon 2; resten er innstillinger for redigereren:
add_action('after_setup_theme', function() {
// Grunnleggende blokkstøtte
add_theme_support('wp-block-styles');
add_theme_support('align-wide');
add_theme_support('responsive-embeds');
// Fargepalett fra det eldre temaet
add_theme_support('editor-color-palette', [
['name' => 'Primary', 'slug' => 'primary', 'color' => '#1a1a2e'],
['name' => 'Secondary', 'slug' => 'secondary', 'color' => '#16213e'],
]);
});Skjemaet for theme.json er på versjon 3. Det finnes ingen versjon 4, så et eksempel som deklarerer den, får kjernen til å ignorere filen.
Slik migrerer du fra Elementor eller Divi til Gutenberg
Migrering fra Elementor, Divi eller Visual Composer til Gutenberg følger en strukturert prosess:
- Kartlegging: dokumenter hver side og hvilken sidebygger den bruker i dag
- Prioritering: begynn med sidene som har mest trafikk
- Konvertering: gjenskap layoutene med blokkmønstre
- Verifisering: sammenlign visuelt og funksjonelt
- Aktivering: bytt side for side med testomdirigeringer
- Opprydding: deaktiver den gamle sidebyggeren når alle sidene er migrert
Sjekk sidebyggerens versjon mot utvidelses-API-et på wordpress.org (api.wordpress.org/plugins/info/1.0/elementor.json for Elementor, som per 12. oktober 2026 oppgir 4.3.4 som stabil) og ikke mot readme.txt i repositoriet, som henger etter.
7. Hvordan måle om en WordPress-modernisering lykkes
Ikke lov prosenter før du har målt. Det du kan fastsette før du starter, er instrumentet hver ting skal kontrolleres med, og utgangsverdien for nettstedet slik det er i dag.
| Hva som måles | Instrument | Når det tas |
|---|---|---|
| LCP og INP fra feltdata | CrUX-rapport eller egen RUM | Før første del og 28 dager etter |
| TTFB | WebPageTest eller serverloggene | Per mal, ikke som snitt for nettstedet |
| SQL-spørringer per side | Query Monitor | På malene med trafikk, med objektcache aktiv |
| Autolastede byte | SQL-spørringen fra seksjon 3 | Før og etter oppryddingen i wp_options |
| PHP-feil per dag | Serverens feillogg | Gjennom en hel forretningssyklus |
| Deprecations per endepunkt | Mu-pluginen fra seksjon 1 | Gjennom en hel forretningssyklus |
På forretningssiden er det eneste ærlige tallet før du starter, det du allerede har: nåværende organisk trafikk, konvertering og vedlikeholdskostnad. Sammenligningen gjøres etterpå, mot den samme utgangsverdien og med måleperioden bestemt på forhånd.
8. Revisjon og modernisering av WordPress med WPPoland
Hos WPPoland jobber vi med å redde WordPress-nettsteder, og alltid i denne rekkefølgen.
Due diligence og revisjoner: vi leverer den tekniske oversikten fra seksjon 1, med prioriteringer og anslått kostnad for hvert tiltak.
Trinnvise utrullinger: vi moderniserer i etapper, hver med sitt akseptkriterium og sin vei tilbake.
Mål som måles, ikke loves: vi blir enige om hvilken måleverdi som skal flytte seg, hvilket instrument som måler den og i hvilken periode, før vi rører koden. Det som ikke kan måles, kommer ikke med i omfanget.
Kunnskapsoverføring: vi dokumenterer prosessen og lærer opp teamet ditt, slik at dere kan vedlikeholde den moderniserte koden selv.
9. Hvor du begynner når du moderniserer et eldre WordPress
Et eldre WordPress-nettsted er ikke automatisk en bør. Det er den tekniske gjelden ingen styrer, og forskjellen mellom de to ligger i om noen kan si hva en endring koster før den gjøres.
Rekkefølgen i denne guiden er bevisst. Mål PHP-gapet mot datoene på php.net, samle deprecations fra ekte trafikk med hookene kjernen allerede kjører, verifiser filene mot sjekksummene, og kvel deretter malene rute for rute med template_include eller block-templates. Fiks autoload og postmeta-indeksene, fordi de er med i hver forespørsel. Fiks skriptlastingen, fordi kjernen gir deg mekanismen og gamle utvidelser tar den fra deg i stillhet. Alt annet er en preferanse så lenge dette ikke er gjort.
Kjører nettstedet fortsatt på en stack fra 2018, er den første leveransen ikke kode. Det er et dokument: PHP-versjon, deprecation-logg, sjekksumfeil, liste over utvidelser med ansvarlig person og malene som bærer trafikken. Vi leser gjerne gjennom den gamle koden først, se WordPress-utvikling og kodegjennomgang.
Sitter bedriftsnettstedet ditt fast i 2018? Skriv til WPPoland for en revisjon, og begynn med oversikten, ikke med omskrivingen.
Relaterte ressurser
- Profesjonell WordPress-utvikling - Modernisering for bedrifter
- Hastighetsoptimalisering av WordPress - Ytelse etter moderniseringen
- Sikkerhetsrevisjon av WordPress - Sikkerhet for eldre kode
- Redesign av nettsted - Fullstendig visuell modernisering
- Migrering til Astro og Next.js - Moderne arkitekturer etter refaktoreringen







