Migrering av Hubnet Cloud frå WordPress til Azure Static Web Apps

| 11 min lesing

Innleiing

Etter å ha drive bloggen min på WordPress i Azure i nesten seks år, tvinga flyttinga frå Storbritannia til Noreg meg uventa til å tenkje nytt om heile hostingstrategien. I staden for berre å byggje opp den eksisterande plattforma på nytt, nytta eg høvet til å migrere til Hugo og Azure Static Web Apps. Det reduserte driftskostnaden frå rundt £55 i månaden til nesten ingenting, samstundes som yting, tryggleik og vedlikehaldsevne blei betre.

Ei praktisk side ved flyttinga som eg ikkje hadde tenkt på, var at det av design ikkje er mogleg å endre korkje Billing Country eller Billing Currency i ein Microsoft Customer Agreement. Det var ikkje eit stort problem, sidan Azure/M365-forbruket mitt er relativt lågt, men eg trong likevel ei løysing fordi dette ikkje berre påverkar bloggen, men òg andre ressursar eg har distribuert.

Kort fortalt måtte eg opprette ein ny tenant med faktureringsprofil i Noreg, slik at eg kan bli fakturert i NOK i staden for GBP. Eg skal skrive om M365-migreringa i eit seinare innlegg, men først hadde eg ein meir presserande prioritet: Kva skulle eg gjere med hostingplattforma til bloggen?

Sjølv om eg ikkje har jobba direkte med webutvikling på lenge, brukte eg ChatGPT og Codex som engineering assistants gjennom heile prosjektet for å gjere research, implementering og feilsøking raskare.

Opphavlege komponentar

  • Azure App Service running WordPress
  • Azure Database for MySQL Flexible Server
  • Azure App Service Managed Certificate
  • Azure Key Vault
  • Virtual Network
  • Private DNS Zone for database
  • User-Assigned Managed Identity
Skjermbilete av Azure-portalen som viser ressursgruppa med ressursane som trengst for den opphavlege WordPress-nettstaden
Ressursgruppe for den opphavlege WordPress-nettstaden

Sjølv om dette fungerte fint for meg dei siste seks åra, har det ikkje vore billeg i drift. Komponentane kosta samla rundt £55 i månaden, med unntak av Azure App Service Managed Certificate, som kosta rundt £50 i året. Eg veit at eg kunne ha ordna sertifikatet gratis sjølv med til dømes LetsEncrypt eller Cloudflare, men eg ville ha noko som var enkelt å halde ved like. Eg kunne ha valt ein managed WordPress-instans på WordPress.com, men då får ein avgrensa kontroll, så PaaS-løysinga verka som eit godt kompromiss. Ulempa var 18 støttekomponentar i ressursgruppa.

Då høvet til å migrere til ein ny tenant oppstod, byrja eg å tenkje på kva eg likte og ikkje likte med WordPress-oppsettet.

Den gamle WordPress-hostede versjonen av Hubnet Cloud

Det eg likte

  • Svært enkelt å opprette nye innlegg og utkast
  • Enkel mediehåndtering; media organiseres automatisk etter dato
  • En populær og moden plattform med mye støtte

Det eg ikkje likte

  • Å måtte bruke en plugin for halvavansert funksjonalitet i stedet for at funksjonen er innebygd i plattformen
  • Å måtte oppdatere plugins og kjernemotoren regelmessig
  • På grunn av populariteten blir WordPress ofte mål for ondsinnede aktører og spammere
  • Det er veldig lett å ødelegge hele nettstedet når en temaoppdatering går galt
  • Å måtte være på nett for å arbeide med nettstedet
  • Driftskostnaden var høy for en personlig blogg
  • Å måtte kjøpe plugins og temaer; mange ligger bak betalingsmurer

Val av rett hostingløysing

Det var tydeleg at ein lift-and-shift av nettstaden mellom tenantar og abonnement ikkje var aktuelt. No måtte eg tenkje gjennom kva eg ville prioritere i eit nytt hostingrammeverk eller på ei ny plattform:

PrioritetKravBegrunnelse
Må haEnkel migrering av innhold fra det eksisterende WordPress-nettstedetMigreringen bør kreve minst mulig manuelt arbeid og bevare eksisterende innhold og metadata der det er mulig.
Må haRimeleg eller gratis i driftLøsningen bør minimere løpende kostnader til hosting, lisenser og vedlikehold.
Må haBruke eige domeneHostingplattformen bør støtte bruk av egne domener.
Bør haCI/CD for deploymentEndringer bør bygges, valideres og distribueres automatisk fra source control gjennom en CI/CD-pipeline.
Bør haStøtte for fleire språkNå som jeg bor i Norge, vil jeg særlig sikre at innholdet er tilgjengelig på norsk bokmål og nynorsk, i tillegg til engelsk.
Bør haIkke være avhengig av tredjeparter for kjernefunksjonalitetNettstedets kjernefunksjonalitet bør være selvstendig og ikke avhenge av eksterne SaaS-plattformer eller proprietære tjenester utover hostingplattformen.
Bør haBruke open-source-komponentar der det er moglegModne open-source-teknologier bør foretrekkes for å redusere vendor lock-in og dra nytte av støtte fra fellesskapet.
Bør haMeir kontroll over innhaldet og strukturen på nettstadenLøsningen bør støtte lagring og levering av ressurser direkte fra prosjektets repository, slik at avhengigheten av eksterne lagringstjenester blir mindre og nettstedet mer selvstendig.
Bør haAdministrerte TLS-sertifikatHostingplattformen bør ha innebygde managed TLS certificates, helst uten ekstra kostnad.
Kan haMoglegheit til å arbeide med nettstaden offlineUtviklingsflyten bør støtte oppretting og redigering av innhold uten internettforbindelse.
Kan haEnkel lokal utviklingsopplevingJeg bør kunne kjøre, forhåndsvise og teste nettstedet lokalt med minimalt oppsett.
Kan haHoste i Microsoft AzureDer det er praktisk, bør løsningen kunne distribueres i Azure for å passe med eksisterende kompetanse og infrastruktur.
Vil ikke ha (foreløpig)Dynamisk CMS-redigering, brukerautentisering, kommentarer eller annen server-side-funksjonalitetDisse funksjonene er utenfor omfanget av den første migreringen og kan vurderes senere ved behov.

Val av rammeverk

Eg dokumenterte desse prioriteringane og vurderte fleire rammeverk opp mot dei. ChatGPT hjelpte til med å lage ei første samanlikningsmatrise, som eg deretter forbetra ut frå eigne krav og erfaringar. Kvart kriterium fekk ein score frå 1 til 5, der 1 er dårleg og 5 er framifrå.

KravPrioritetHugoEleventyAstroJekyllNext.jsBlazor WASMGhostWordPress
Enkel migrering av innhald frå WordPressMust44343255
Rimeleg eller gratis i driftMust55554522
Bruke eige domeneMustN/AN/AN/AN/AN/AN/AN/AN/A
CI/CD for deploymentShould55545533
Støtte for fleire språkShould53434424
Ikkje avhengig av tredjepartar for kjernefunksjonalitetShould55554544
Bruke open-source-komponentar der det er moglegShould55555555
Meir kontroll over innhaldet og strukturen på nettstadenShould55554532
Administrerte TLS-sertifikatShouldN/AN/AN/AN/AN/AN/AN/AN/A
Moglegheit til å arbeide med nettstaden offlineCould55544532
Enkel lokal utviklingsopplevingCould44434534
Hoste i Microsoft AzureCould55555545

Det var mykje å velje i, men Ghost og WordPress blei straks utelatne fordi driftskostnadene ikkje oppfylte krava mine. Blazor WASM blei òg raskt utelukka, sidan den største veikskapen i denne samanhengen er innhaldshandtering.

Hugo var den klare vinnaren i samanlikninga, men får ikkje full score fordi han ikkje har den same komplette IDE- og debugging-støtta som Blazor WASM i Visual Studio, og fordi overføring av WordPress-innhald krev noko manuelt arbeid.

Valt rammeverk: Hugo

Val av plattform

Eg gjorde den same vurderinga for hostingplattforma, men med eit tilleggskrav om innebygd støtte for statiske Hugo-nettstader.

KravPrioritetAzure Static Web AppsAzure App ServiceGitHub PagesCloudflare PagesNetlifyVercel
Rimeleg eller gratis i driftMust525555
Eigne domeneMust554555
Innebygd støtte for Hugo-deploymentMust534555
CI/CD for deploymentShould454555
Støtte for fleire språkShould555555
Ikkje avhengig av tredjepartar for kjernefunksjonalitetShould554333
Bruke open-source-komponentar der det er moglegShould555555
Meir kontroll over innhaldet og strukturen på nettstadenShould555555
Administrerte TLS-sertifikatShould554555
Moglegheit til å arbeide med nettstaden offlineCould555555
Enkel lokal utviklingsopplevingCould554555
Hoste i Microsoft AzureCould551111

Med Azure-bakgrunnen min og scoren opp mot krava, var Azure Static Web Apps det klare valet.

Valt plattform: Azure Static Web Apps

Kome i gang

Dette var truleg den vanskelegaste delen, sidan eg aldri hadde jobba med Hugo før og ikkje visste heilt kva eg kunne vente. Først oppretta eg eit nytt repo på GitHub-kontoen min. Deretter måtte eg tenkje mykje på utsjånaden til den nye nettstaden. Hugo er ei langt nyare plattform enn WordPress, og det finst derfor færre tema. Eg brukte ein kveld på å sjå gjennom tema på GoHugo og enda med CareerCanvas av Felipe Cordero.

Skjermbilde av CareerCanvas-temaet i Hugo Template Gallery
CareerCanvas-temaet i Hugo Template Gallery

Etter at eg klona repoet lokalt, brukte eg ein god del tid på å tilpasse nettstaden til mine preferansar og gjere innhalds- og nettstadstrukturen relevant for den personlege profilen min. Eg brukte òg mykje tid på lokaliserte omsetjingar av CV-en og anna “statisk innhald”. Lokalisering var eit område der ChatGPT Work Mode verkeleg sparte mykje tid. Eg brukte det til å lage bokmåls- og nynorskversjonar av Markdown-filene, og gjekk deretter gjennom og forbetra resultatet sjølv. Orsak, norsklæraren min Ingrid, viss du les dette. Eg blei svært imponert over resultatet. Omsetjingane var grammatisk korrekte, lydde naturleg i staden for ordrett og heldt på engelske fagomgrep der det passa. Dette gjorde utviklingsprosessen monaleg raskare.

Eg gjorde nokre endringar i layout partials for CSS og tema for å betre ytinga og få layouten slik eg ønskte. Eg konfigurerte til dømes SVG-flagg i staden for å gå ut frå at nettlesarane lasta inn rett flaggemoji. DevIcon-biblioteket som blir brukt i techstack-seksjonen på nettstaden, manglar nokre teknologiar eg bruker, så eg la inn lokale SVG-filer i staden. Dei ser betre ut enn FontAwesome-ikona som blir brukte som reserve.

Eg har hatt stor nytte av i18n-funksjonaliteten i Hugo for omsetjingar. Du definerer berre TOML-konfigurasjonsfiler for omsetjingar med konsekvente språknøklar, så kan teksten endrast dynamisk etter valt språk.

Migrering av innhald frå det gamle WordPress-nettstaden

Under researchen min oppdaga eg WP2Hugo Project, som lastar ned alt innhald frå ein WordPress-nettstad og automatisk konverterer alle sider og innlegg til Markdown. Det lastar òg ned alle mediafiler. Dette gjekk mykje raskare enn eg først såg for meg, nemleg å eksportere WordPress XML manuelt og deretter konvertere det sjølv.

Dette gav meg òg eit høve til å rydde opp i innhaldet og sikre at metadataa var konsekvente. Deretter omsette eg alle dei historiske blogginnlegga i bulk. Dette kravde litt meir innsats enn tidlegare, sidan work/agent mode ikkje var særleg effektivt til omsetjingar med modellen eg hadde valt (GPT 5.6 Terra Medium). Eg måtte gjere fleire iterasjonar før all tekst var omsett, og modellen såg òg ut til konsekvent å hoppe over kommentarar i kodeblokker.

Oppsett av Azure Static Web Apps og CI/CD-pipelinen

Dette var svært enkelt. Eg oppretta berre ein static web app i det nye abonnementet mitt, peikte han mot main-branchen i GitHub-repoet, og då var han konfigurert. Azure-avtrykket mitt i denne samanhengen er redusert frå 18 til 1 ressurs. I ettertid burde eg ha gjort dette i starten av prosjektet, slik at konfigurasjonen var på plass i feature-branchen. Eg konfigurerte dessutan GitHub Actions-workflowen til å hente Microsoft Clarity project ID og Google Analytics-tag-konfigurasjon frå repo secrets ved deployment. Deployment tek konsekvent under to minutt, langt raskare enn å halde ved like WordPress-nettstaden, der oppdateringar av motor eller plugins kunne bruke ei stund.

Skjermbilde av Azure Portal som viser Azure Static Web App-ressursen
Azure Static Web App i Azure Portal
Skjermbilde av GitHub Actions-kjøringshistorikken
GitHub Actions-kjøringshistorikk
Skjermbilde av en vellykket GitHub Actions-kjøring
Vellykket GitHub Actions-kjøring

Det kravde litt prøving og feiling, men til slutt blei deployment utløyst etter kvar merge til main-branchen. Det er ikkje nødvendig i feature branches, sidan eg kan køyre nettstaden lokalt.

Optimalisering

Dette tok mest tid. Eg brukte nok fleire dagar på det. Det første eg gjorde etter deployment, var å be partnaren min opne nettstaden. Nokre ting lasta ikkje i Safari og Firefox på iOS, men fungerte fint i andre nettlesarar. Eg var verkeleg usikker på kvifor. Med hjelp frå ChatGPT undersøkte eg problema og spora dei til slutt til layout partials som ikkje var optimaliserte for mobilnettlesarar. Då det var løyst, køyrde eg ein PageSpeed Insights-rapport for nettstaden. Han føreslo ei rekkje forbetringar innan Performance, Accessibility, Best Practices, SEO og Agentic Browsing over fleire iterasjonar.

PlattformFørste rapportEndelig rapport
Mobile
Desktop

Det er verdt å merke seg at mobilrapporten frå PageSpeed Insights simulerer ei dårleg 4G-samband, noko som påverkar resultata noko. Eg gjekk gjennom kvar PageSpeed-rapport og brukte ChatGPT til å forklare ukjende tilrådingar og føreslå moglege forbetringar.

Viktige problemer som ble løst:

  • Eksterne CSS-biblioteker hostes nå lokalt
  • Dupliserte importer av CSS-biblioteker
  • Profilbildet og hero-bakgrunnene er responsive ut fra klientens skjermstørrelse
  • Alle PNG- og JPEG-bilder er konvertert til WEBP- eller AVIF-format for bedre ytelse
  • Nettstedet er nå optimalisert for skjermlesere
Ny versjon av Hubnet Cloud hostet på Azure Static Web Apps

Konklusjon

Dette var eit morosamt prosjekt som lét meg forbetre hostinga av bloggen monaleg utan å koste mykje pengar. Det lærte meg mykje om korleis statiske nettstader fungerer, og kor mykje meir moderne og dynamiske dei er enn CMS-forfedrane som WordPress.

Endå viktigare er at migreringa reduserte Azure-avtrykket mitt frå 18 ressursar til éin, samstundes som yting, tryggleik og vedlikehaldsevne blei betre og driftskostnadene nesten forsvann.

Gjennom heile prosjektet brukte eg ChatGPT og Codex som engineering assistants, ikkje som kodegeneratorar. Dei var uvurderlege for å utforske ukjende område, lage første implementasjonar og forklare nettlesaråtferd, men kvart arkitekturval, kvar code review og den endelege implementeringa var framleis mitt ansvar.

Avslutningsvis blei ei uventa flytting til eit anna land katalysatoren for å modernisere heile bloggplattforma, og i ettertid er eg svært nøgd med resultatet.

Takk