React -projektin perustaminen

React esittely -blogikirjoituksessa esiteltiin Reactin perusteita yksinkertaisella toteutuksella, jossa React ladattiin käyttöön ns. CDN -latauksella. HTML-sivun lähdekoodiin koodattiin suoraan Javascriptiä joka käytti React -kirjastoa. Tämä tapa sopii keveään Reactin esittelyyn, mutta vähänkään vakavammassa projektissa tämä ei ole ollenkaan riittävä tapa käyttää Reactia.

Tässä blogikirjoituksessa perustamme oikean React -kehitysympäristön, jossa kehitystyö onnistuu helposti ja tehokkaasti. Koodaustyö tapahtuu JavaScript -tiedostojen kautta ja kehittäjä saa käyttöönsä työkaluja jotka helpottavat kehitystyötä.

create-react-app – näppärä työkalu projektin perustamiseen

Täysiverinen React -kehitysympäristö käyttää useita erilaisia ohjelmia, jotka yhdessä muodostavat nykyaikaisen kehitysympäristön. Kehityksessä tarvitaan mm. HTTP-palvelinta jolla kehitysversio pyörii paikallisesti sekä kääntäjää joka kääntää uusimmilla JavaScriptin versioilla koodattua JavaScript -koodia webbiselaimien ymmärtämään, riittävän yhteensopivaan (=”riittävän vanhaan”) JavaScriptin muotoon.

Jotta projektin perustaminen helpottuisi, käytämme projektin perustamiseen näppärää apuohjelmaa nimeltä create-react-app. Itse asiassa create-react-app on npm -kirjasto, joka asennetaan omalle koneelle globaalisti ajettavaksi ohjelmaksi. Asentaminen tapahtuu npm:llä seuraavasti:

Yllä oleva komento asentaa create-react-app:n siten että se voidaan ajaa mistä tahansa hakemistosta käsin.

Siirrytään seuraavaksi sopivaan hakemistoon, jonne haluamme projektihakemiston perustettavan ja suoritetaan create-react-app.

Projekti perustetaan ja npm:n kautta haetaan projektissa tarvittavat kirjastot. Lopulta projekti on valmis käyttöön:

Kuten viimeisestä ohjeesta näkyy, React -ohjelma on valmis käynnistettäväksi. Suoritetaan siis komennot:

Ohjelma käynnistyy ja selaimeen aukeaa osoite http://localhost:3000:

Konsolissa näkyy seuraava teksti:

Mitä kaikkea edellä tapahtui? Tutkitaan ensin projektihakemiston sisältöä:

Näemme, että hakemiston rakenne ja sisältö on itse asiassa varsin yksinkertainen:

.gitignore on Git-versionhallintaa varten perustettu ns. ignore tiedosto, jossa määritellään mitä tiedostoja hakemiston alla ei ole tarpeen laittaa versionhallintaan.

package.json -tiedosto on React -ohjelman sydän. Siellä on määritetty npm -ohjelman avulla ajettavat skriptit sekä ohjelman riippuvuudet ja muut määritykset. Tutustutaan tiedostoon myöhemmin tarkemmin.

node_moduleshakemistoon ladataan ohjelman käyttämät npm -paketit eli ohjelman käyttämät riippuvuudet.

public -hakemistossa on index.html tiedosto, josta ohjelman suoritus käynnistyy.

README.mdtiedostoon voidaan dokumentoida projektiin liittyvää ohjeistusta, joka näkyy automaattisesti kun projektia katselee esim. GitHub-palvelussa.

Mielenkiintoisin osa sijaitsee src -hakemistossa. Siellä on ohjelman lähdekoodi ja tämä hakemisto on paikka, jossa ohjelman kehitys tulee oikeastaan kokonaan tapahtumaan.

Tutustutaan ensin package.json tiedostoon:

Yleiskuva package.json -tiedostosta on varsin yksinkertainen. Tämä johtuu siitä että create-react-app piilottaa projektin todelliset riippuvuudet allensa varsin tehokkaasti. Palataan tähän myöhemmin mutta tutustutaan ensin tiedostoon tässä muodossa.

Tiedostossa on ensin  projektin metatietoa ja sen jälkeen riveillä 5-8 ohjelman käyttämät riippuvuudet eli dependencies (”depsit”). Näemme että riippuvuuksia on tässä vaiheessa ainoastaan Reactiin. Kehitysaikaiset riippuvuudet eli devDependencies on määritetty riveillä 9-11.  Siellä näkyy react-scripts, joka itse asiassa on create-react-app:iin liittyvä skriptikirjasto.

Scripts -osiossa näkyy komennot, jotka voidaan suorittaa ajamalla komento npm [komento]:

npm start käynnistää kehitysympäristön, npm run build rakentaa tuotantopaketin ohjelmasta, npm test suorittaa testit.

npm run eject on tarkoitettu edistyneemmille käyttäjille (tai oikeastaan vähänkään vakavamman koodauksen harrastajalle): eject komennolla create-react-app -projektin rakenne voidaan ”vapauttaa” kehittäjän käyttöön siten että kaikki kehitysympäristön komponentit ovat vapaasti konfiguroitavissa ja nähtävillä.  Tällöin tosin menetetään react-create-app:n tarjoama helppokäyttöisyys mutta toisaalta osaava kehittäjä saa käyttöönsä huomattavasti laajemman säädettävyyden. Tässä esimerkki, millaiseksi package.json muotoutuu, kun ajetaan npm run eject:

eject on yksisuuntainen eli kerran ejektoitua projektia ei voi enään muuttaa takaisin yksinkertaisempaan muotoon. Mutta edelleen olellisimmat komennot npm start sekä npm run build ovat käytettävissä. Joten ei ole merkitystä, ajatko tässä vaiheessa ejektiä vai et.

Ejektin jäljiltä voimme kuitenkin havaita, että React -projektissamme on nyt käytössä useita komponentteja erilaisiin tarkotuksiin, muun muassa:

Babel -kääntäjillä käännetään JavaScript -ohjelmakoodia selaimelle sopivaan muotoon.

ESLint -kirjastot on tarkoitettu koodaajan apuvälineeksi: ne tarjoavat automaattisen koodityylin tarkkailijan, jonka avulla koodaaja näkee heti jos koodissa on joko tyylillisesti huonoja koodirivejä (esim. sisennykset pielessä) tai jos koodissa käytetään joitain huonoksi tiedettyjä tapoja (esim. määritetään muuttuja jota ei oikeasti käytetä ollenkaan).

WebPack -”bundleria” käytetään pakkaamaan ohjelman sisältämä kokonaisuus yhdeksi kokonaisuudeksi. Lisäksi se sisältää kätevän Webpack Development Server -palvelimen. Se toimii yksinkertaistetusti sanottuna kehitysaikaisena HTTP -palvelimena joka tarjoilee sovelluksen uusimman version selaimelle osoitteessa http://localhost:3000. Se osaa myös ottaa uusimmat koodit käyttöön ”lennossa” joten se soveltuu erinomaisesti kehitysaikaiseen työskentelyyn: kun ohjelmakoodia muutetaan, muutos näkyy välittömästi selaimessa!

Joka tapauksessa: kehitysympäristömme on nyt valmis käyttöön ja voimme alkaa koodiin tutustumisen!

React -projektin rakenne ja toiminta

Avataan projekti jollain koodieditorilla, kuten JavaScript -koodarien suosimalla Visual Studio Code -editorilla.

Jos tutkitaan public -hakemistossa olevaan index.html -tiedostoa, havaitaan että siellä ei juurikaan ole sisältöä body -tagin sisällä:

Body -osiossa on kuitenkin SPA eli Singe Page Application -web ohjelmalle riittävä osuus: div -elementti (jonka id on root). Tähän kohtaan sivulla React -ohjelma lisää HTML- ja JavaScript -sisältöä ohjelmallisesti. React -ohjelmaa kehitettäessä HTML -koodausta ei ole tarpeen edes käyttää tämän enempää vaan kaikki koodaus tehdään JavaScriptillä sekä JSX -kielellä. Kun tämä index-sivu avataan kerran, selaimen ei ole sen jälkeen tarvetta tehdä sivulatausta, koska sivun  sisältöä pystytään muokkaamaan ohjelmallisesti ”lennossa”. Tämä tarjoaa käyttäjälle huomattavasti mukavemman käyttökokemuksen verrattuna ”vanhanaikaiseen” web-sovellukseen jossa toiminnon suorittaminen aiheutti aina sivunlatauksen.

Tutkitaan seuraavaksi paikkaa, joka sijoittaa sivulle sen sisällön. Avataan src -hakemistosta tiedosto index.js:

Sieltä nähdään, että root -elementtiin renderöidään eli ”piirretään” App -tiedostossa oleva React -komponentti.

Tutkitaan siis seuraavaksi App.js –tiedostoa:

Tässä näemmekin jo React -komponentin App. Se on koko ohjelmamme pääkomponentti, jonka render -funktio tuottaa sisällön aiemmin tutkittuun index.html tiedostoon. Render -funktiossa käytetään JSX -kieltä jossa on tuttuja elementtejä HTML -kielestä.

App.js -tiedoston alussa importoidaan käyttöön Reactin Component -luokka, yksi kuvatiedosto sekä tyylit erillisestä tyylitiedostosta.

React -ohjelman kehittäminen siis lähtee tästä App.js -tiedostosta eteenpäin! Koodarin tehtävänä on suunnitella ohjelman käyttöliittymäsuunnitelman perusteella uusia React -komponentteja ja sijoittaa niitä näytölle. Käytännössä koodari siis toteuttaa uusia tiedostoja, joissa on Reactin Component -luokasta peritty, aivan kuteen App.js -tiedostossa. Ohjelman rakenne pyritään määrittämään osissa ja ”näytöt” muodostetaan yhdistelemällä komponentteja kokonaisuudeksi. Tiedostoon voi sisällyttää toisia komponentteja kun ottaa ne käyttöön import -menetelmällä. Luokan render -funktio määrittää, mitä komponentteja ja muuta sisältöä näytölle halutaan.

React -projektin kehittäminen create-react-app -rungon päälle

Kuten edellisessä blogipostauksessa todettiin, React -ohjelman suunnittelu lähtee komponenttiajettelusta: käyttöliittymä pyritään ajattelemaan komponenttien kautta ja sivulla näkyvät elementit toteutetaan erillisiin tiedostoihin jolloin syntyy helpommin ymmärrettävämpi ohjelmarakenne, kohtuullisen kokoisia ohjelmatiedostoja ja kaiken lisäksi komponentteja joita voidaan hyvässä tapauksessa uudelleenkäyttää useassa paikassa ohjelmaa.

Suunnittelemme seuraavaksi pienen ohjelman, jossa on muutama komponentti. Näin voimme kokeilla ohjelman jakamista komponentteihin ja näemme miten React-järjestelmän kehittäminen käynnistyy.

Tavoite: haluamme tehdä Reactilla sovelluksen, missä käyttäjä voi katsella Tampereen alueen tieliikennekameroiden reaaliaikaisia kuvia. Tarvitsemme vain näytön, jossa käyttäjä valitsee alasvetolistasta jonkin Tampereen ympäristössä olevan kelikameran nimen ja sen jälkeen alasvetolistan alapuolella näytetään kelikameran kuva.

Suunnitelma: toteutetaan yksi ”sivu” (= React- komponetti), johon asetellaan kaksi komponenttia: kameran valintakomponentti CameraSelection sekä valitun kameran kuvaa näyttävä komponentti CameraView. Pääkomponentilla eli ”sivulla” on hallussaan tila eli state, jossa on tallessa valittu kamera. Kun käyttäjä valitsee näytettävän kameran valintakomponentilla, valintakomponentti välittää valinnan pääkomponentille ja se puolestaan välittää uuden tiedon kuvaa näyttävälle komponentille.

Ei muuta kuin koodaamaan!

Perustetaan ensin src -hakemistoon kaksi hakemistoa komponenteille: CameraSelection ja CameraView.

Toteutetaan ensin kameran valintakomponentti:

CameraSelection -komponentille annetaan kaksi propertyä: selectedPresetId ja onSelect. Näistä ensimmäinen kertoo komponentille, mikä valinta sen kuuluu näyttää aktiivisena. Toinen ”propsi” taas on valinnan käsittelevä ”callback” funktio. Komponentissa on kovakoodattuna taulukkoon muutama kamera Tampereen seudulta. Oikeassa projektissa kameralistaus voitaisiin hakea Liikenneviraston REST-rajapinnasta mutta jätetään se harjoitustehtäväksi tai toiseen blogipostaukseen.

Seuraavaksi voisimme lisätä tämän komponentin käyttöön ohjelman ”pääsivulle” eli App.js -tiedostoon:

App.js -tiedostostossa näkyy uusi komponentti korostettuna. Huomaa myös komponentin tila eli state, jossa on tallessa nykyinen valinta.

Todetaan että valintakomponentti näkyy sivulla:

Tämän jälkeen toteutetaan vielä kamerakuvan näyttävä komponentti:

Tämä komponentti saa propsina vain halutun presetId:n, jonka perusteella se näyttää tieliikennekameran kuvan Liikenneviraston palvelusta.

Otetaan CameraView käyttöön App.js tiedostossa:

Projektimme on valmis! Testataan toimintaa valitsemalla Rantatunnelin kamera:

Yhteenveto

create-react-app tekee React -projektin aloittamisen helpoksi. Se ottaa mukaan perus-riippuvuudet ja tarjoaa kehitystyölle hyvän perustan. Sen päälle on hyvä jatkaa omaa kehitystyötä ja toteuttaa mitä hienoimpia web-palveluita. React -ohjelman koon ja vaatimusten kasvaessa create-react-app -pohja ei kuitenkaan riitä kovin pitkälle, mutta pohjan päälle on helppo ottaa käyttöön esim. tilanhallintakomponentti Redux. Siitä ja muitakin Reactin kehitystyössä käytettävistä työkaluista voidaankin sitten puhua omassa blogipostauksessaan.