nrk.no

Embedding på nrk.no

Kategorier: Dev & Webutvikling

En essensiell del av internetts natur – embedding av eksternt innhold. Faksimile fra youtube.com

Embedding er en teknikk der man lar en nettside bake inn en løsrevet komponent – gjerne ekstern – som “lever” sitt eget liv ved siden av nettsiden du egentlig besøker. Nettet og dets bruksområder hadde neppe vært slik vi kjenner det i dag, dersom embedding ikke fantes. Vi ser det hver dag – uten kanskje helt å tenke gjennom det – som annonser, kart, videoklipp, kommentarløsninger mm. Men hvordan fungerer det egentlig ? Og hvordan kan du som webutvikler utnytte mulighetene som finnes ? Hvordan bruker vi embedding på nrk.no ? Det er temaet for denne artikkelen – bidra gjerne i kommentarfeltet nedenfor om du mener noen teknikker er utelatt. Men aller først – la oss se litt på historikken bak dagens løsninger.

I gamle dager – <applet />, <object /> og <embed />

De første embedteknikkene dukket opp få år etter at de første nettleserne kom – rett og slett fordi HTML som teknologi var laget for formattering av tekst i dokumenter, mens mange brukere ønsket seg mer interaktivitet enn det nettleseren kunne tilby. Teknologien som ble brukt var Java, og det er nok mange geeks der ute som brukte mange timer på 90-tallet til å sette opp Java på datamaskinene til søsken, foreldre, tanter og onkler. Rent teknisk fungerte Java-applikasjonen som en såkalt «applet» – et «lite program» – som ble aktivert på det stedet i nettsiden det befant seg en <applet />-tag (med attributter for url og parametre til programmet).

Skjermdump fra en eksempelapplet
Skjermdump fra en eksempelapplet

<applet />-tag-ens dager er for øvrig snart historie. Selv om de fleste browsere fortsatt støtter tag-en, ble den fjernet fra html-4-spesifikasjonen allerede i 1999. På grunn av kompleksiteten knyttet til installasjon av java i nettleseren, korrekt html-syntax og ikke minst kunnskap på java som programmeringsspråk blant webutviklere er det idag sjeldent å se java applets i bruk. Eneste unntaket må være den norske løsningen for norske nettbanker – BankID. Ettersom det er avdekket en rekke sikkerhetshull i applet-teknologien de senere årene, har også bankID tenkt til å gå over til javascript-basert innlogging høsten 2014.

Selv om <applet />-tagen ble fjernet fra spesifikasjonen forsvant ikke behovet for tilleggsprogramvare. Applets ble erstattet av de mer generiske tag-ene <object /> og <embed />, som i all hovedsak ble brukt til embedding av flash-innhold som spill, musikk, video med mer. Årsaken til at det ble to tag-er istedetfor én henger sammen med nettleserkrigen som pågikk mellom IE og Netscape på 90-tallet (les mer på A list a part). I Html5 er begge tag-ene standardisert – med noen mindre semantiske forskjeller.

NRK.no har i mange år brukt flash for å produsere ulike typer interaktiv grafikk, f.eks. som den nedenfor som forklarer hendelsesforløpet 22. juli 2011:

Faksimile fra www.nrk.no/multimedia
Faksimile fra www.nrk.no/multimedia

Ved å ta en kikk på embedkoden ovenfor er ikke denne akkurat noe enklere enn det <applet />-tagen tilbød i sin tid. Det har derfor vokst frem en flora av ulike støttebiblioteker som swfobject og flashembed som sørger for korrekt flashembedding. Men flash er nå på vikende front. Med den eksplosive veksten av mobiler og tablets implementeres dagens løsninger stort sett ved hjelp av html5.

<iframe /> redder dagen – nesten

I dag embedder vi eksternt innhold på NRK.no ved hjelp av litt ulike teknikker. Vi stiller normalt krav til at innholdet skal følge responsive prinsipper og at de tilbyr fallbackløsninger for de mest populære plattformene folk bruker der ute – være seg om teknologien heter internet explorer, android, ios eller chrome. Vi tilbyr også selv innhold for embedding eksternt, som f.eks. videoklipp. Videre har vi en egen avdeling med redaksjonelle utviklere som lager løsrevne komponenter – «digitale historiefortellinger» – eksklusivt for nyhetssatsninger på NRK.no.

I likhet med de fleste andre mediehus – og nettet for øvrig – har løsningene gått i retningen <iframe />-tagen som teknologi. En <iframe /> sørger for å maskere bort de vanskelige tekniske detaljene ved flashembedding som beskrevet ovenfor – slik at flash fortsatt kan brukes der det er mest fornuftig, med evt. html5-fallbackløsninger. <iframe />-tag-en lager en ny nettleserkontekst – et «hull» inn i foreldresiden – der oppsettet fullt og helt kontrolleres av innholdstilbyderen.

Faksimile fra youtube.com, fra TV-serien "Ikke gjør dette hjemme"
Faksimile fra youtube.com, fra TV-serien «Ikke gjør dette hjemme»

En stor fordel med <iframe /> er at innholdet som embeddes fra andre domener enn ditt eget ikke har mulighet til å påvirke foreldre-framen den er en del av; dvs. den kjører i en “sandkasse”. Videre er det slik at elementet kan styles på samme måte som andre elementer – og skalere resonsivt for innhold med et gitt aspect-ratio slik eksempelet over viser (se fler embedeksempler på embedresponsively.com/). Dersom innholdet kræsjer, eller tjenesten har uedle hensikter, er det ikke mulig for iframen å bryte ut og «sniffe» hvilken kontekst den befinner seg i. Og dessverre er det er nettopp her mange av utfordringene knyttet til <iframe /> starter.

Ettersom en <iframe /> lever i sin egen nettleserkontekst er den også en god del tregere ytelsesmessig. Den laster ikke sitt innhold før hovedsiden er lastet ferdig (onload-eventen fyres av). Videre er det slik at innhold i en <iframe /> indekseres av søkemotorer som den nettsiden den bor på, uten å kunne identifisere hvilken nettside/url som embedder den. Søkemotorene har riktignok tatt høyde for denne «feilindekseringen» ved å etablere en spesialtag for å referere til hovedinnholdet, en såkalt canonical <link />-tag . En siste og minst like viktig problemstilling – spesielt innen responsive design – er variabel høydejustering basert på innholdet i <iframe />-tag-en.

I motsetning til andre html-elementer utvider ikke høyden på -elementet seg automatisk.
Variabel høydejustering i en <iframe />

Standard HTML-elementer justerer høyden sin basert på innholdet den består av, dvs. «height: auto;» – og dette er ikke tilfelle for >iframe /< som må få definert sin høyde i pixels. Ettersom høyden settes av nettsiden som embedder innhold, har ikke iframen mulighet til å fortelle foreldre-nettsiden om sin nye høyde.

<script /> gir en hjelpende hånd

Problemene med såkalt cross-domain kommunikasjon – dvs. et grensesnitt for API-kommunikasjon mellom vinduer – er heldigvis identifisert for lengst, dog uten at en optimal løsning har etablert seg (ennå – se lenger ned). Løsningen heter window.postMessage – et eventbasert api for strengbasert meldingskommunikasjon mellom vinduer og domener.

Ved hjelp av litt javascript implementerer man en algoritme som måler høyden på innholdet i <iframe />-vinduet og som deretter poster dette som en melding til foreldre-nettsiden. Foreldrenettsiden må på sin side lytte etter slike meldinger og justere høyden på iframen selv. Ettersom kommunikasjonen er strengbasert og eventhåndteringen ikke skjer automatisk fra nettleseren side regnes teknikken som sikker; eller sagt på en annen måte – sikkerheten må ivaretas av utvikleren selv.

Sikkerheten ovenfor ivaretas ved at man kun tillater meldinger fra et domene man forventer å få meldinger fra. I tillegg brukes JSON-parsing for å unngå eksekvering av potensiell farlig javascript-kode. Dersom innholdet skal brukes til noe annet enn høydejustering, f.eks. sette inn HTML bør man i tillegg bruke en html-sanitizer for å unngå potensielle XSS-sårbarheter.

Vi har utviklet et generelt script som sørger for å håndtere slik kommunikasjon som beskrevet over. Dette scriptet laster vi både i foreldrevinduet og iframe-vinduet. Slik oppnår vi automatisk høydejustering slik eksemplet nedenfor viser:

Faksimile fra #minhjertesak tilknyttet valget 2013
Faksimile fra #minhjertesak tilknyttet valget 2013

<script /> tar over kontrollen

For at innhold uten fast aspect ratio skal embeddes korrekt er det altså behov for scripttilgang på foreldresiden. Og når scriptet likevel kjører på foreldresiden kan det gjør en del andre operasjoner samtidig.

Et eksempel kan man se fra Twitter sin embedsnutt for deling av lenker:

Tweet-knapp - embedbar fra twitter.com
Tweet-knapp – embedbar fra twitter.com

Eksempelet over tegner først ut en <a />-tag (lenke). Den laster ned Twitter sitt widget-api. API-et sørger for å erstatte <a />-tagen med en <iframe /> som inneholder en tweet-knapp med antall delinger. URL-en til twitter inneholder informasjon som hvilken side brukeren skal twitre om og andre litt kryptiske tallkoder. Fra nettstedseieren sitt ståsted er dette en svært enkel copy-paste-løsning. Det man kanskje ikke er like klar over at denne typen embedding innebærer en potensiell sikkerhetsrisiko. I motsetning til sandkassebaserte <iframe />-tags har man her invitert potensiell uønsket kode hjem til brukerne sine.

I verste fall kan tjenesteleverandøren man embedder bli hacket, og slik bidra med spredning av virus til alle brukere som besøker nettsiden din. Alternativt kan hackere stjele innlogginscookies og slik logge seg inn som deg, dersom embedscriptet brukes i en portal med pålogging. I beste fall kan tjenesteleverandøren foreta svært detaljert tracking av dine surfevaner. De «kryptiske» tallkodene kan i praksis brukes til å krysskoble brukerens surfevaner mot informasjon andre som tilbydere har i sine egne og andres databaser. Som regel er nok denne typen tracking laget for bedre målretting av annonser, men ut fra et personvernståsted er det problematisk at tracking kan gjennomføres uten brukerens samtykke. Til syvende og sist må man som bruker kanskje stole på nettstedseieren eller bruke anonymiserende tjenester når du surfer rundt på weben.

Teknikken med script-embedding er ihvertfall så fleksibel og god at nrk.no stort sett benytter seg av den i en eller annen variant i våre egne embedscript (Se f.eks. www.nrk.no/video og yr.no).

Embedkode fra nrk.no/video
Embedkode fra nrk.no/video

AMD-baserte moduler

NRK.no bruker et CMS (publiseringssystem) som heter Polopoly. I likhet med de fleste andre CMS-er som Escenic, WordPress, Joomla og Drupal publiseres nytt innhold ved hjelp av ulike skjemaer. Malverk og widgets utvikles og slippes i sykluser på alt mellom noen dager til flere måneders varighet (typisk 2-ukers intervaller). Ved større hendelser som brannen i Lærdal, eller i featuremalen der noe skal illustreres interaktivt i form av såkalte “digitale historiefortellinger”, gjør vi dette også ved hjelp av embedding. Embedding gir de redaksjonelle utviklerne fleksibilitet for hurtigere utrulling av pågående nyhetssaker enn det CMS-utviklingssyklusen tilbyr. For å unngå å havne i fellen “jquery soup” har vi utviklet et generisk system for javascript-moduler. Teknikken lener seg hardt på AMD-standarden (Asynchronous Module Definition), med bruk av biblioteket requirejs.

RequireJS sørger for at moduler som eksplisitt definerer sine avhengigheter, sørger for optimalising av størrelse, innlastingsrekkefølge og parallellisering der forholdene tillater det. RequireJS tilbyr videre en måte å definere flere kontekster – et system for å potensielt ukompatible avhengigheter separert.

Skisse på AMD-basert embedteknikk
Skisse på AMD-basert embedteknikk

Den største fordelen med javascriptbaserte widgets er at man ikke trenger å eksekvere noen høydejusteringsalgoritme og at det stort sett gir bedre ytelse. RequireJS gir dessuten en del andre fordeler sammen med gruntJs, som innlasting av malverk, lazyloading av polyfills – men det temaet blir for stort å fylle i denne artikkelen. Den største ulempen er at innhold laget ved hjelp av javascript i all hovedsak er usynlig for søkemotorer. Det finnes riktignok løsninger for å få til også dette – men det impliserer noe større kompleksitet.

Hvorfor må embedding være så vanskelig ?

Mens vi kanskje ler av løsninger som <applet />, <object /> og <embed /> idag, er det ikke utenkelig at man om noen år kommer til å le av dagens løsninger med <iframe />, <script /> og AMD-moduler. Når HTML5-standarden skulle utformes var motivet i all hovedsak å standardisere allerede eksisterende hacks og «feilbruk» som utviklermiljøene hadde klart å finne på. Siste nytt på embedfronten er teknologien «Web Components».

Ettersom Web Components fortsatt ikke er fullt standardisert er det dessverre relativt dårlig nettleserstøtte enn så lenge:

Nettleserstøtte for web components
Nettleserstøtte for Web components

Teknologien forsøker å løse en del behov som fremgår av diskusjonen ovenfor:

  • templates: en måte å servere html, css og javascript uten eksekvering.
  • shadow-dom: tilgang til endring av utseende for native-komponenter som avspillerknapper på <video /> og <audio />-elementer – der innholdet ikke har tilgang til området utenfor sitt eget scope, annet enn containernoden.
  • custom elements: mulighet til å definere egne elementer for å wrappe egendefinert funksjonalitet
  • imports: importer html på tvers av domener

Som flinkiseleven på første rad har Google sørget for en full implementasjon (av en uferdig standard) i Chrome, samt laget en polyfill ved navn Polymer. Sannsynligvis kan det være fornuftig å avvente standardiseringsarbeidet før man slenger seg på toget, men det kan være godt å vite at veien videre ser lysere ut!

9 kommentarer

    • Aksel Nordal (NRK) (svar til Jørgen Repshus)

      Takk!

      Hvis du trenger en quickfix for høydejusteringer, har Ben Alman (father of gruntJs) laget en jqueryplugin for noen år siden. Litt utdatert – javel – men kan brukes som utgangspunkt for din egen implementasjon.

  1. Der er minst et alternativ til embedresponsively

    https://iframely.com (bruker den når jeg skal embedde slides for slideshare,net)

    Eksempel: http://browsetoolbar.com/#random-slide-iframly-and-php

    https://embed.ly/code

    Har NrK samme muligheter som National Geographic?

    Exempel: http://www.miljøavisen.no

    En av 25 videoer trekkes tilfeldig under første artikkel.

    Jeg har laget nettsteder lenge nok til å være svært skeptisk til embedding av kode fra tredje parts leverandør. Det er en av grunnene til at jeg roterer 25 videoer. Bryetes en lenke, vil den vises ca 1 av 25 ganger, dvs i ca 4 % av tilfellene.

    Jeg skal ikke at mine nettsteder skal se ut som en sveitserost eller et dårlig pyntet juletre.

    Min mest avanserte løsning i 2018 er at jeg først trekker ett tilfeldig tall mellom 1 og 4 som dirigererer meg enten til DailiMotion, Vimeo, YouTube eller tekxt.

    Deretter trekkes en tilfeldig av n videoer. Blir det tull med en leverandør, er det gjort på sekunder å kommentere ut denne leverandøresn mappe.

    Lag en funskjon der man kan embedde dagsnytt 18 sendinger på sekundet og live Tv.

    Svar på denne kommentaren

Legg igjen en kommentar til Jon Kleiser Avbryt svar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *. Les vår personvernserklæring for informasjon om hvilke data vi lagrer om deg som kommenterer.