Blogg

Sluta bygga om varje WordPress-webbplats

En praktisk guide, invändning för invändning, för att standardisera WordPress-byggen med theme.json och blockmönster – utan att göra varje kundsajt till en kopia.

Sammanfattning

De flesta byråer bygger varje WordPress-webbplats från ett tomt tema, även när en gemensam grund skulle korta schemat med veckor. Den här artikeln argumenterar för att theme.json, blockmönster och dynamiska block låter dig standardisera strukturlagret samtidigt som varje kunds distinkta design bevaras. Den tar direkt upp de fem invändningar som hindrar team från att förändras: 'vi har olika kunder', 'anpassade block är dyra', 'redigeraren är förvirrande', 'vi förlorar våra hooks och filters' och 'FSE är inte produktionsredo'. Varje invändning får ett praktiskt motargument och ett konkret mönster som du kan anta stegvis. Utbytet är en repeterbar byggprocess som fortfarande hedrar skräddarsytt arbete där det hör hemma. Varning: inga enklickningsåterställningsknappar utlovas.

Hur många av dina kundwebbplatser delar ens en enda rad kod? Inte copyright-raden – faktisk kod. Om svaret är "knappt några", har du redan känt smärtan: samma hero-sektion byggd om för nionde gången, samma team-grid-markup kopierad från ett projekt till nästa, samma preprocess-justeringar korsrefererade över ett halvdussin teman. Du har också hört försvaret: "Varje kund har olika behov." Sant. Slutsatsen alla drar, dock – att varje webbplats behöver en skräddarsydd grund – är falsk. WordPress-ekosystemet ger dig nu ett sätt att standardisera de strukturella delarna utan att standardisera designen: theme.json för designtokens, blockmönster för upprepad layout och dynamiska block för de få funktioner som behöver riktig serverlogik. Den här artikeln handlar om invändningarna som hindrar byråer från att ta det steget, och vad som faktiskt fungerar när du står emot dem.

Invändningen "men varje kund är annorlunda"

Den underliggande principen: standardisera grunden, inte ytan. Anledningen till att hålla strukturen i ett delat bibliotek är just att lämna det visuella lagret fritt. En theme.json-fil är inte en design – den är en uppsättning designtokens. Färger, mellanrum och typografi är värden, inte markup. Det är den kritiska förändringen: du kan dela markup medan en theme.json per webbplats får webbplatsen att se helt annorlunda ut för ett annat varumärke.

Ta två kunder: en advokatbyrå och en friluftsåterförsäljare. Deras designspråk ligger långt ifrån varandra. Men båda behöver en hero-sektion, ett testimonial-grid, ett call-to-action-band. Istället för att bygga om markup för varje, underhåll tre blockmönster och låt varje kunds theme.json definiera färger, typsnitt och mellanrum. Strukturen förblir identisk; designtokenen förvandlar den från ett varumärke till det andra. När återförsäljaren ändrar sin färgpalett nästa vår, redigerar du en fil på deras webbplats – inte markup i sex mallar.

Praktiskt innebär detta att ditt team skapar mönster som kod, registrerar dem i ett delat plugin och låter theme.json på varje kundsajt hantera färgen. Mönstrets klassnamn blir din arkitektur; värdena blir variablerna. Du kan till och med gå längre och utöka theme.json till att inkludera anpassade inställningar för posttyper eller plugin-utdata, även om du vid någon punkt bygger ett konfigurationsgränssnitt istället för en webbplats – en fälla som diskuteras i vår titt på att utöka theme.json. Håll det delade lagret smalt: det ska bara innehålla det som återkommer hos kunder. I samma ögonblick som du lägger till en inställning "ifall någon någon dag vill ha det", har du skapat en abstraktion som kommer att kosta mer att underhålla än den sparar.

När du sätter upp en ny kund bör de första trettio minuterna vara: klona det delade mönsterpluginet, skapa en ny theme.json med kundens palett och teckenstorleksskala, och registrera deras logotyp och sidfot. Det är inte ett anpassat bygge; det är en konfigurationsuppgift. Det återstående kundspecifika arbetet går till innehåll, struktur och eventuella genuint skräddarsydda funktioner. Detta är skillnaden mellan att bygga varje hus från grunden och att ha en uppsättning prefabricerade planlösningar som du kan måla om och tapetsera om. Analogin är lös, men principen håller: ju mer du trycker in i theme.json-värden, desto mindre behöver du röra markup.

En av de enklaste vinsterna är att faktiskt titta på hur blockmönster fungerar. Ett mönster är bara en samling block med fördefinierat innehåll och stil. Du kan spara vilken blockkonfiguration som helst som ett mönster, och sedan kan en kund infoga det utan att behöva veta hur det är byggt. Det innebär att mönstret blir en 'ingångspunkt' för icke-tekniska användare. När ditt team underhåller det underliggande mönstret i kod, får kunden ett konsekvent bibliotek utan att röra en enda PHP-tagg.

Nu, förbehållet jag återkommer till: övercentralisera inte. En theme.json med en inställning för varje tänkbar nyans är ett underhållsträsk. Delade mönster ska vara åsiktsfulla, inte allsmäktiga. Om en kund behöver en radikalt annorlunda layout – säg en tidningshemsida med ett stort utvalt grid – kanske de inte passar i ditt standardmönsterbibliotek. Det är okej. Standardisering innebär att du vinner på de 80 % av projekt som liknar varandra, inte att du tvingar varje webbplats i samma form.

Invändningen "custom blocks spräcker budgeten"

Här är en motprincip som låter tråkig men sparar pengar: de flesta saker du tror behöver ett custom block behöver det inte. Core-block plus ett mönster kan täcka den överväldigande majoriteten av layouter. Custom-blocket är sista utvägen, inte första avsikten.

Det klassiska exemplet är team-grid. Om det är en engångsföreteelse, använd core-blocken "columns" och "group" och låt kunden lägga till en avatar för hand. Om tre kunder ber om samma grid med samma "sociala länkar under namnet"-struktur, har du nu en kandidat för ett blockmönster. När det mönstret börjar samla nya alternativ – hover-effekter, sortering, betygsstjärnor – blir mönstret en ohanterlig blandpåse, och då är det dags att skriva ett custom block. Misstaget som skadar budgeten är att hoppa direkt till custom block vid första begäran.

Ett mer lömskt scenario: kunden ber om en "fallstudiekarusell." Den första instinkten är att tänka, "Jag behöver ett karusellblock." Men behöver de en karusell? Kanske behöver de en horisontellt rullbar grupp av inlägg, som core-blocken kan hantera med ett "group"-block och lite CSS. Eller så behöver de en dynamisk lista över senaste fallstudier, vilket är ett dynamiskt block som frågar CPT:en. Frågan är inte "vilken funktion vill kunden ha?" utan "vilken data är den beroende av?" Om datan är statisk och redigerbar av kunden, räcker ett mönster. Om datan kommer från en databasfråga, är ett dynamiskt block motiverat. Om datan behöver uppdateras i realtid från ett API, kanske du tittar på en REST API-integration istället – det går över i en annan typ av bygge.

När du väl bygger ett block är block.json din vän. Det är den enda källan till sanning för attribut, skript och stilar, vilket gör blocket portabelt mellan projekt. Det låter dig också deklarera beroenden och översättningar rent, vilket är viktigt när du distribuerar ett bibliotek över många kundsajter. För innehåll som är beroende av live-data renderas ett dynamiskt block på servern, så du behöver inte skicka ett JavaScript-paket vid varje sidvisning. Och om ditt block utvecklas kan du hantera utfasningar elegant så att befintligt innehåll inte går sönder – vår guide till block-utfasning går igenom det exakta mönstret.

Innan du bygger något, kör beslutet genom det här rutnätet:

MetodBäst förUndvik när
Core-blockEngångsinnehåll, enkla sidorLayouten upprepas hos många kunder och behöver rika alternativ
BlockmönsterRepeterbara layouter utan logikLayouten behöver villkor, dynamisk data eller komplexa interaktioner
Custom blockUpprepade, datadrivna eller mycket specifika beteendenDet enda skälet är en engångssektion som kan hanteras med en klass

Du vill också tänka på blocknamngivning från dag ett. Ett blocknamn är i huvudsak ett kontrakt med ditt innehåll. Om du kallar det wagent/team-grid och senare döper om det till wagent/team-carousel, kommer du att bryta befintligt innehåll om du inte tillhandahåller en utfasningsväg. Välj generiska, ändamålsbaserade namn som inte blir falsk marknadsföring när blocket utvecklas. Detta är en variant av namngivningsdisciplinen vi alla har lärt oss från plugin-prefix, och den gäller lika mycket för blocknamn.

Den konträra åsikten här är det mest användbara jag kan säga: det custom block du bygger för att en kund bad om "bara en enda pjäs" är nästan alltid ett misstag. Säg nej artigt, leverera ett core-block med en klass, och banka timmarna. Du kommer att få mer respekt från kunden – och en mindre rad i underhållsbudgeten.

Invändningen "kunder kommer att förstöra redigeraren"

Den här invändningen är till hälften rätt. Själva blockredigeraren är inte problemet; problemet är att ge kunderna för mycket rep. theme.json kan låsa ner vad som är redigerbart: inaktivera mallredigeraren, begränsa tillåtna block och ställ in standardstilar så att en felplacerad kolumn gör mindre skada. Vissa kunder kommer fortfarande att lyckas förstöra saker, men du kan återställa en sida till ett sparat mönster med ett klick – något den klassiska redigeraren inte kunde erbjuda.

Låt mig måla upp ett scenario. En kund ringer och säger: "Jag flyttade en sektion och nu ser hela sidan fel ut." Med ett klassiskt tema skulle du logga in, inspektera CSS:en och förmodligen spendera en timme på att fixa layouten. Med en blockuppsättning kan du öppna sidan, välja innehållsområdet och återställa det till det sparade mönstret. Mönstret är baslinjen; kundens ändringar är överlagringen. När överlagringen går fel tar du bort den. Det är inte bara ett trevligare arbetsflöde; det är en fundamentalt mer förlåtande redigerare.

Nu till nyansen: de flesta kunder vill inte redigera särskilt mycket alls. De vill ändra text, byta foton och kanske omordna en sektion. Blockmönstret ger dig exakt det utan att exponera hela webbplatsstrukturen. I den meningen är redigeraren inte en leksak; det är en sökare. Ditt jobb är att kalibrera vad kunder kan se. Det innebär att du kanske inaktiverar "Mallar"-inställningarna, begränsar blockinsättaren till en kurerad lista och till och med förfyller tomma mönster med platshållararbete. Redigeraren blir ett inmatningsformulär för innehåll snarare än en webbdesigncanvas.

På tillgänglighetssidan är blockredigerarens fokushantering och tangentbordsstöd generellt bättre än en klassisk redigerares mallfält. Men du måste fortfarande säkerställa att mönster har korrekt rubrikhierarki och tillgängliga namn. Eftersom mönstret delas mellan kunder, åtgärdar du dessa problem bara en gång, vilket är ytterligare en dold vinst med standardisering.

Den genuint svåra delen är intern. För ditt team kräver inlärningen att prototypa med block att man lär bort "gör det i PHP"-vanan. Det är en verklig kostnad, men det är en engångskostnad per person. Det är inte en anledning att undvika metoden; det är en anledning att börja med ett mönsterbibliotek och en förlåtande kund innan du rullar ut överallt. Låt inte refrängen "mina kunder kan inte hantera block" dölja det faktum att du inte ännu har konfigurerat en blockuppsättning för att möta dem halvvägs.

Invändningen "vi har redan hooks och filters"

Principen här är: du kastar inte bort hooks; du lägger till ett lager ovanpå. Block är presentationsgränsen; hooks är fortfarande hur du injicerar logik. Ett dynamiskt blocks render callback körs i PHP, vilket innebär att du kan anropa samma funktioner och använda samma filter som du redan litar på.

Föreställ dig ett plugin som låter dig lägga till ett fält för "utvald produkt" till vilket inlägg som helst med hjälp av ett filter. Med ett dynamiskt block kan du inkludera ett serverrenderat block som kör det filtret och skriver ut utdata inuti blockets omslag. Kunden infogar blocket; den befintliga PHP-logiken gör det tunga arbetet. Ingenting kastas bort. För ett ännu mer konkret exempel, överväg ett custom block som listar senaste projektinlägg. I dess render callback anropar du get_posts(), loopar och använder the_title() och the_permalink() – samma malltaggar du har använt i åratal.

Detta är också platsen att vara ärlig om vad som inte översätts. Vissa smarta gamla teman använder template-parts med invecklade villkor som tar argument baserat på sidkontexten. Att återskapa det som ett block kan vara rörigt. Men du behöver inte återskapa allt på en gång. Den inkrementella vägen är att behålla PHP-logiken, slå in den i ett dynamiskt block och flytta markupen till blockmallen. Du kommer ofta att upptäcka att dina befintliga filtermönster kan hantera den nya utdatan. Och om logiken är tätt kopplad till en mallhierarki (t.ex. "på sökresultat, visa detta annorlunda"), kan du fortfarande använda den klassiska mallen för de specifika vyerna medan du använder block för vanliga sidor.

REST API:et öppnar också en annan dörr: du kan bygga block som hämtar data från andra WordPress-webbplatser eller tredjepartstjänster. Ett dynamiskt block kan anropa wp_remote_get() för att hämta JSON och rendera det på frontend. Det är ett kraftfullt mönster för byråbyggen där kunder vill visa sociala flöden, produktlistor eller intern data utan att hantera en separat integration. Avvägningen är cachning och felhantering – om det fjärranslutna API:et är långsamt, är din sida långsam. Håll API-baserade block borta från kritiskt ovanför-vik-innehåll, eller använd klientsidans rendering med ett korrekt laddningstillstånd.

Actions och filters körs fortfarande runt sparande och rendering; hook-arkitekturen försvinner inte när du antar block, den flyttar bara till en ny kontext. Om du behöver fräscha upp din förståelse av var actions och filters möter denna nya blockvärld, är vår hooks-djupdykning en användbar uppfräschning.

Invändningen "FSE är inte produktionsredo"

Rättvis invändning, men fråga vad "riskfyllt" faktiskt innebär. Full Site Editing har gått igenom flera versioner, och theme.json har stabiliserats i ett stabilt schema. Risken är inte att redigeraren "plötsligt går sönder" – risken är att ditt teams anpassade kod kan förlita sig på gamla PHP-mallar som samexisterar besvärligt med blockmallar. Dessutom antar vissa tredjepartsplugin fortfarande den klassiska redigeraren eller anpassaren. Det är ett kompatibilitetsbeslut, inte en anledning att kasta ut hela modellen.

Ett användbart sätt att tänka på det: enkla, repeterbara webbplatser med innehåll skrivet i block är minst riskfyllda. Högrisk-kunder är de med djupt anpassade klassiska teman eller proprietära plugin som renderar sin egen frontend. Det är en legitim anledning att hålla sig till klassiska teman för den lilla nischen. Felet är att låtsas att "produktionsredo" är en enda strömbrytare som antingen är på eller av.

Innan du föreslår ett blocktema för en kund, gå igenom en snabb checklista:

  • Har kunden ett djupt anpassat tema som skulle kräva migrering?
  • Stödjer de nödvändiga plugin-programmen Site Editor och REST API?
  • Tillåter värdmiljön den filåtkomst som blocktemat förväntar sig?
  • Har du avsatt tid för mönsterdesign, inte bara blockregistrering?
  • Kommer kundens team att tolerera redigeringsändringarna, eller behöver de en låst mall?

Om något svar är nej, justera omfattningen eller använd en hybridmetod. Det är inte en kompromiss; det är ingenjörsmässigt omdöme. Och om du bygger en hybrid, kom ihåg hooks- och filterhistorien ovan – du kan fortfarande slå in gammal logik i dynamiska block medan theme.json hanterar det globala utseendet.

Versionshantering av din theme.json är inte bara en teoretisk fråga. Jag har sett en byrås anpassade blockbibliotek gå sönder när kunden uppdaterade WordPress och blockets style-fil registrerades med wp_register_style() under ett ändrat handle. Fixen var enkel, men paniken var verklig. En enkel testprocess – kör uppdateringen på en staging-kopia av webbplatsen, klicka igenom de viktigaste sidorna, släpp sedan – löser de flesta sådana överraskningar.

Invändningen du inte har gjort mot dig själv

Här är meta-invändningen som hindrar byråer från att standardisera: "Det är en stor förändring, och det finns ingen tid att göra det under kundarbete." Det är sant – så gör det inte under kundarbete. Välj ett internt projekt eller en liten kund och bygg ett mönsterbibliotek. Använd theme.json som design-token-system. Lägg till ett custom block bara när det är motiverat. Slå in de gamla hooks där de hjälper. Iterera.

Här är en grov första 30 dagar:

  1. Granska dina senaste fem kundbyggen och lista de tio mest upprepade layoutdelarna.
  2. Förvandla dessa tio delar till blockmönster, med en liten uppsättning CSS-klasser.
  3. Bygg ett delat plugin (eller mu-plugin) som registrerar dessa mönster. Om du inte har tänkt på plugin-organisation för detta, skumma den här guiden om att bygga robusta WordPress-plugin först.
  4. Skapa en theme.json som matchar din baslinjedesign; lägg till kundspecifika värden när du startar projekt.
  5. Välj ett litet internt projekt eller en vänlig kund och migrera det till stacken.
  6. Dokumentera en hjältehistoria om en kund som redigerade sin hemsida utan att ringa dig.

I slutet av det experimentet kommer du inte att ha ett "block-first"-märke att hänga på väggen. Du kommer att ha ett team som kan starta en ny kundsajt från en delad baslinje utan att be om ursäkt för tidslinjen. Du kommer också att vara i en bättre position att säga nej till kundens begäran om ett 42:a custom block – för att du vet exakt vad core-blocken kan göra, eller för att du kan visa varför ett dynamiskt block verkligen skulle vara snabbare.

Kommer du fortfarande att bygga vissa skräddarsydda webbplatser? Ja. Vissa kunder kommer alltid att behöva en anpassad mall, en skräddarsydd sida eller en proprietär integration som inte är värd att tvinga in i den delade modellen. Målet är inte att eliminera skräddarsytt arbete – det är att göra det till undantaget snarare än standarden.

Repeterbarheten kommer från de tråkiga delarna: ett gediget theme.json-schema, ett tydligt mönsterbibliotek och disciplinen att hålla det delade lagret smalt. Det är inte den glansiga versionen du hör i webinarier. Det är den som slår måndagsmorgonens tomma-tema-blues.

Sources (5)