Översikt
Efter många veckor av programmerande i Node-plattformen är det nu dags att börja titta på hur du kan ta dina program till webben! Denna vecka inleds med att titta på webbläsaren, hur den är uppbyggd och hur du bör ladda in dina skript i webbläsaren. Information om veckans upplägg annonseras löpande i kursens Zulip-kanal.
Vill du ändå se en gammal “Stå-upp”-vlogg med Mats & Mikael, inspelad under en tidigare kursomgång? Den ger även en introduktion till delkurs B.
Stödjande inspelningar
Section titled “Stödjande inspelningar”Webbläsaren och JavaScript
Section titled “Webbläsaren och JavaScript”Denna inspelning tittar på hur webbläsaren är uppbyggd och vad du ska tänka på när du länkar in JavaScript i webbläsaren.
Webbläsaren – en fientlig programmeringsmiljö
Section titled “Webbläsaren – en fientlig programmeringsmiljö”“The browser is a really hostile programming environment”, enligt Douglas Crockford. Till skillnad från en kontrollerad servermiljö körs klientkod i en miljö utvecklaren inte styr över: många olika webbläsare (Chrome dominerar både i Sverige och globalt, följt av Safari), många olika enhetstyper (mobil, desktop, surfplatta i ungefär jämn fördelning), och varierande stöd för nyare funktioner. Verktyg som caniuse.com och MDN är nödvändiga för att hålla koll på vad som faktiskt går att lita på tvärs över webbläsare – och i grunden är det utvecklarens eget ansvar att testa och hantera skillnaderna, det finns inget centralt skyddsnät.
Från HTML till pixlar: hur en sida renderas
Section titled “Från HTML till pixlar: hur en sida renderas”Webbläsaren bygger upp en sida i flera tydliga steg:
- DOM Construction – HTML läses och parsas till ett DOM-träd (Document Object Model), där varje element blir ett objekt av en specifik typ (
HTMLImageElement,HTMLHeadingElementosv.), alla i grunden ärvande frånHTMLElement→Element→Node→EventTarget. - CSSOM Construction – CSS läses och byggs till ett motsvarande träd (CSSOM) med de beräknade stilarna för varje nod.
- Render Tree construction – DOM och CSSOM slås ihop till ett render-träd. Element med
display: none(eller dolda på annat sätt) tas inte med här. - Layout operation (“reflow”) – varje nods storlek och position i render-trädet räknas ut, och eventuella lager (z-led) skapas.
- Paint operation – varje lager målas upp för sig.
- Composing operation – lagren sätts ihop till den slutliga bilden som visas.
Tillsammans kallas de här stegen den kritiska rendervägen (Critical Rendering Path).
Webbläsarens beståndsdelar
Section titled “Webbläsarens beståndsdelar”En webbläsare byggs av flera samverkande delar: ett användargränssnitt, en browser engine (rendermotorn – DOM, CSSOM, render-träd, layout, målning), en separat JavaScript engine, nätverkshantering och en UI-backend, samt datalagring. De stora webbläsarna skiljer sig åt både i rendermotor och JS-motor: Chrome/Opera/Edge kör Blink + V8, Firefox kör Gecko + SpiderMonkey, Safari kör Webkit + JavaScriptCore, och den numera pensionerade Internet Explorer körde Trident + Chakra.
Parsning och laddning i praktiken
Section titled “Parsning och laddning i praktiken”När webbläsaren parsar ett dokument sker DOM-parsning, CSS-laddning och bildladdning i stort sett parallellt. En vanlig <script>-tagg i <head> beter sig annorlunda: den blockerar DOM-parsningen medan skriptet både laddas ner och körs, vilket kan fördröja hela sidan i onödan. Flera attribut ändrar det beteendet:
<script>sist i<body>– parsningen hinner klart innan skriptet ens börjar laddas, men allt sker fortfarande sekventiellt efteråt.<script async>– skriptet laddas parallellt med DOM-parsningen, men kör så fort det är klart (kan alltså avbryta parsningen mitt i).<script defer>– skriptet laddas parallellt, men körs garanterat först efter att DOM-parsningen är helt klar.<script type="module">– ES-moduler laddas alltid asynkront (somdefer), inklusive alla moduler de i sin tur importerar.
Att köra JavaScript i webbläsaren
Section titled “Att köra JavaScript i webbläsaren”Kod inline direkt i HTML-attribut eller i en <script>-tagg mitt i dokumentet fungerar tekniskt, men bör undvikas: koden blir svår att underhålla, går inte att cacha optimalt, och blockerar DOM-parsningen om den inte hanteras särskilt. Att istället länka in JavaScript som ES-moduler är det rekommenderade sättet:
<head> ... <script type="module" src="js/components/my-hello/my-hello.js"></script> <script type="module" src="js/index.js"></script></head>Moduler laddas asynkront, exekveras i importordning, och stöds brett i moderna webbläsare (se caniuse.com/es6-module) – det här är mönstret som resten av kursens komponentbaserade kod bygger vidare på.
Varför JavaScript i webbläsaren?
Section titled “Varför JavaScript i webbläsaren?”Det var inte givet att det skulle bli JavaScript
Section titled “Det var inte givet att det skulle bli JavaScript”När webben var ung fanns flera konkurrerande idéer om vilket språk som skulle köras i webbläsaren. Java (från Sun) var en stark kandidat – många trodde på 90-talet att Java skulle synas överallt, även i webbläsaren. Microsoft försökte med Visual Basic (VBScript). Netscape, med Brendan Eich, byggde istället ett eget alternativ, ursprungligen döpt till LiveScript – namnet ändrades till JavaScript för att rida på Javas dåvarande popularitet, trots att språken har lite gemensamt. Standarden bakom språket heter idag ECMAScript. Det är alltså långt ifrån en självklarhet att det blev just JavaScript, även om det med facit i hand kan kännas så. Idag finns även WebAssembly, som gör det möjligt att kompilera helt andra språk för körning i webbläsaren – vad som händer på sikt är omöjligt att sia om.
Webapplikationer, inte hemsidor
Section titled “Webapplikationer, inte hemsidor”Det som byggs med JavaScript i webbläsaren idag är sällan statiska webbsidor, utan webapplikationer – Facebook och Slack är typiska exempel, med mycket logik som körs i bakgrunden. Det som kanske är mindre uppenbart: verktyg som Visual Studio Code är i grunden också en webapplikation, byggd med HTML, CSS och JavaScript, paketerad för olika operativsystem med hjälp av Electron. Discord, Pinterest, Instagram och Skype är byggda på liknande sätt, ofta transpilerade till native mobilappar med till exempel React Native. Webben som plattform har alltså redan spridit sig långt bortom webbläsarfönstret.
Webben blir plattformen
Section titled “Webben blir plattformen”Google har länge drivit tanken att webbtekniker duger till att bygga applikationer som fungerar “överallt” utan att behöva paketeras via Electron, React Native eller liknande. Chromebook, byggt kring Chromium, är ett konkret exempel – ett operativsystem där webbläsaren i praktiken är hela gränssnittet. Ett annat resultat av samma tanke är Progressive Web Applications (PWA), standardapplikationer byggda med webbteknik som ändå kan installeras och köras som vilken annan app som helst – ett ämne kursen återkommer till mot slutet.
Att lära sig webbprogrammering handlar alltså inte om en smal nisch, utan öppnar upp för applikationsutveckling brett över plattformar – mobil, desktop och webb – eftersom samma grundverktyg återanvänds så pass mycket.
Introduktion till “Custom elements” och webbkomponenter
Section titled “Introduktion till “Custom elements” och webbkomponenter”Kan du bygga dina egna html-element? Absolut! Denna inspelning tittar på hur.
Kan man ärva HTML-element?
Section titled “Kan man ärva HTML-element?”Eftersom inbyggda HTML-element (HTMLImageElement, HTMLElement osv.) i grunden är klasser, ligger frågan nära till hands: kan man ärva från dem och skapa sina egna? Att direkt instansiera ett inbyggt element med new fungerar dock inte:
const image = new HTMLImageElement() // ERROR: Illegal constructorBakom kulisserna är det fortfarande en klass med en konstruktor, men den som byggt DOM-API:et har medvetet sett till att konstruktorn kastar ett fel om den anropas med new – element i webbläsaren skapas istället via document.createElement(...):
const image2 = document.createElement('img')Ett element skapat på det sättet hamnar inte automatiskt någonstans i DOM-trädet – det är ett löst, “flytande” objekt tills det uttryckligen läggs till, till exempel med appendChild.
Custom element – ett eget HTML-element
Section titled “Custom element – ett eget HTML-element”Att ärva från ett HTML-element är fullt möjligt, och det är precis vad som krävs för att skapa ett custom element – ett självdefinierat element för sådant som saknas bland de inbyggda (till exempel en flagg-väljare för språkbyte, eller en återanvändbar knapp som visar antal öppna merge requests):
class MyCustomElement extends HTMLElement { constructor () { super() // ... }}
customElements.define('my-custom-element', MyCustomElement)customElements.define() registrerar klassen hos webbläsaren under ett valt tagg-namn. Eftersom elementet ska skapas via document.createElement(...), inte med new, är det vanligt att inte exportera klassen – då minskar risken att någon råkar instansiera den fel väg. Ett undantag är om man faktiskt vill låta någon annan komponent ärva vidare från den.
Anonyma klasser
Section titled “Anonyma klasser”Ett vanligt misstag är att kopiera en komponentfil för att skapa en ny, men glömma byta namnet på själva klassen. Ett sätt att undvika det är att skriva klassen anonymt, direkt som andra argument till define:
customElements.define('my-custom-element', class extends HTMLElement { // ...})Eftersom klassen aldrig namnges finns det heller ingen risk att av misstag exportera den. Generellt avråds anonyma klasser (skulle koden ligga i en loop måste klassen då återskapas för varje varv), men eftersom define-koden bara körs en gång per modul är det inget problem här.
Namngivning
Section titled “Namngivning”Ett custom element måste innehålla minst ett bindestreck i taggnamnet – standarden garanterar att inget inbyggt HTML-element någonsin kommer ha ett bindestreck i sitt namn, vilket förhindrar framtida namnkrockar. Konventionen MyCustomElement (PascalCase) för själva klassnamnet följer JavaScripts vanliga klass-namngivning, medan tagg-namnet (my-custom-element) måste vara i kebab-case eftersom bindestreck inte är tillåtet i ett klassnamn.
Vad är egentligen “webbkomponenter”?
Section titled “Vad är egentligen “webbkomponenter”?”Det som skapades ovan kallas ett custom element – men “webbkomponent” är ett bredare, informellt begrepp (ingen egen W3C-standard) som beskriver hur tre riktiga standarder – Custom Elements, HTML Templates och Shadow DOM – tillsammans används för att bygga återanvändbara, isolerade byggstenar för webbsidor. ES-moduler räknas ofta också in, eftersom de är ett naturligt sätt att paketera och dela komponenter.
Idén är densamma som med fysiska komponenter: bygg en isolerad, återanvändbar del en gång (till exempel en knapp som visar en pipeline-status, eller en “clone repository”-widget), och plugga sedan in den var den behövs.
Webbkomponenter kontra ramverk
Section titled “Webbkomponenter kontra ramverk”Custom Elements, HTML Templates och Shadow DOM fungerar och stöds brett idag – men gjorde det inte för fem år sedan. Det förklarar varför JavaScript-ramverk (Angular, React och senare Vue, Svelte m.fl.) växte fram: de löste samma strukturproblem innan webbstandarden själv hann ikapp. I mångt och mycket har utvecklingen gått “varvet runt” – funktionalitet som tidigare krävde ett ramverk finns nu inbyggd i webbläsaren (precis som jQuery till stor del blev överflödigt när dess bekvämligheter togs in i standarden).
Att kursen medvetet satsar på webbkomponenter, byggda ovanpå klass-syntax, är delvis ett svar på återkommande kritik: JavaScript utan någon påtvingad struktur upplevs som svårt att lära sig, eftersom nästan allt går att göra på flera olika sätt. Genom att först etablera ett tydligt sätt att organisera kod (klasser, sedan komponenter byggda av klasser) blir steget till att senare lära sig ett ramverk som React eller Svelte mindre – flera moderna ramverk (Svelte i synnerhet) bygger direkt vidare på webbkomponenter istället för att uppfinna en helt egen abstraktion.
Läsanvisningar
Section titled “Läsanvisningar”Under läsanvisningar hittar du veckans kapitel som ska läsas i kurslitteraturen. Planera upp och dela upp läsningen under veckan.
Övningar
Section titled “Övningar”Under Övningsuppgifter hittar du övningsuppgifter som det är lämpligt att du arbetar med under veckan.
Handledning
Section titled “Handledning”Examinationsuppgift A3
Section titled “Examinationsuppgift A3”Nu är det hög tid att börja arbeta med examinationsuppgift A3.
Läs mer om “Examinationsuppgift A3 - Tjugoett” här.
Utmaningar
Section titled “Utmaningar”Veckans utmaningar handlar om webbläsaren som programmeringsmiljö.
Studiefrågor
Section titled “Studiefrågor”Här är ett antal frågor som du kan försöka besvara och diskutera tillsammans med din AI-assistent. Tveka inte att lyfta någon av frågorna till handledningen för att fortsätta diskussionen med lärare och studiekamrater.
- Jag håller på och lär mig hur man skapar egna html-element med hjälp av “custom elements” och jag vill bygga upp ett exempelprogram för att utforska hur det fungerar. Jag kommer ge dig instruktioner så kan du föreslå kodlösningar och kommentera dem så kan jag lära mig från dig, ok?
- Jag vill börja med ett enkelt element
<hello-message>som bara skriver ut en hälsning i sitt Shadow DOM. Hur hade du gjort? - Nu vill jag att elementet ska kunna ta emot ett attribut
nameoch visa hälsningen med det namnet istället för en generisk text. - Hur kan jag reagera på att attributet
nameändras efter att elementet redan är infogat i sidan? - Jag vill skapa ett andra element som ärver från mitt
hello-message-element och lägger till en knapp som byter hälsningsspråk. - Kan du visa hur jag laddar in mina script-filer i huvuddokumentet på ett sätt som fungerar bra
ihop med moduler (
type="module")?
Här följer tips till hur du kan prioritera bland kursmaterialet för att komma igång med veckan.
- Nu behöver du komma igång med A3. Det är fortfarande drygt 2 veckor till inlämning, men samtidigt så startar kursen upp med nya saker så håll farten uppe och gör så mycket av A3 som du kan. Det kan vara skönt att ha tid innan inlämningen för att finslipa din kod och testa så att allt fungerar.
- Försök prioritera så du också hinner med att titta på de tre föreläsningar som finns. Du behöver inte börja koda i webbläsaren än, men det är värdefullt om du redan nu börjar titta på hur det fungerar.
- När du tittat på föreläsningarna så finns det en (grön) övningsuppgift där du får möjlighet att testa att programmera i webbläsaren och använda den miljön för utveckling. Missa inte att övningsuppgiften har ett inspelat lösningsförslag.
