Kurssilla tutustutaan Javascriptilla tapahtuvaan moderniin websovelluskehitykseen. Pääpaino on React-kirjaston avulla toteutettavissa single page -sovelluksissa, ja niitä tukevissa Node.js:llä toteutetuissa REST-rajapinnoissa.
Kurssilla käsitellään myös sovellusten testaamista, konfigurointia ja suoritusympäristöjen hallintaa sekä NoSQL-tietokantoja(Mongodb).
osa0 sekvenssikaavioiden piirtäminen
front
npm start
back
npm run watch
lintti
npm run lint
testit
CI=true npm tes
Testauskattavuus saadaan selville suorittamalla testit komennolla
CI=true npm test -- --coverage
json server
```npm run server``
Viimeisten vuosien aikana on noussut esiin tyyli tehdä web-sovellukset käyttäen Single-page application (SPA) -tyyliä, missä sovelluksille ei enää tehdä erillisiä, palvelimen sille lähettämiä sivuja, vaan sovellus koostuu ainoastaan yhdestä palvelimen lähettämästä HTML-sivusta, jonka sisältöä manipuloidaan selaimessa suoritettavalla Javascriptillä.
FRONT:
Komponentti pohjainen JavaScript-kirjasto web-käyttöliittymien tekoon. React päivittää/renderöi käyttöliittymän automaattisesti kun data muuttuu. React osaa päivittää käyttöliittymästä vain ne osat jotka liittyvät muuttuneeseen dataan Reactilla toteutettu käyttöliittymä muodostuu koostetuista komponenteista. Reactissa filosofiana onkin koostaa sovellus useista, pieneen asiaan keskittyvistä uudelleenkäytettävistä komponenteista.React ei käytä html- templateja vaan Javascriptia ja JSX:ää.
JSX on hieman XML-kieleltä näyttävää Javascriptia, jossa jokainen tagi tulee sulkea. JSX:n avulla voi kirjoittaa HTML/XML-tyylistä koodia jossa on sekaisin html-elementtejä ja React-komponentteja. Html-elementit kirjoitetaan pienillä kirjaimilla. React-komponenttien nimet aloitetaan kapiteeleilla. JSX transformoidaan tavalliseksi Javascript-koodiksi. Käännöksen hoitaa automaattisesti Babel. Elementin attribuuteissa sijaitseva Javascript-koodi sijoitetaan JSX-syntaksissa {}-merkkien sisään.
Käytetään selaimen ja palvelimen väliseen kommunikaatioon. Axiosin metodi get palauttaa promisen,joka edustaa asynkronista operaatiota. Promise voi olla tilassa pendin, fulfilled/resolved, rejected. Axios-kirjasto osaa parsia pelvelimelta tulleen datan Javascript-taulukoksi.
Reactin luokkien avulla määritellyillä komponenteilla voidaan määritellä joukko lifecycle-metodeita, eli metodeita, joita React kutsuu tietyssä komponentin “elinkaaren” vaiheessa. Yleinen tapa datan palvelimelta tapahtuvaan hakemiseen on suorittaa se metodissa componentDidMount. React kutsuu metodia sen jälkeen kun konstruktori on suoritettu ja render-metodi on suoritettu ensimmäistä kertaa.
Document Object Model eli DOM on ohjelmointirajapinta eli API, joka mahdollistaa selaimessa esitettävien web-sivuja vastaavien elementtipuiden muokkaamisen ohjelmallisesti.
on HTTP-protokollaan perustuva arkkitehtuurimalli ohjelmointirajapintojen toteuttamiseen. Se määrittelee, millaisilla operaatioilla palvelinten dataa pyydetään, lisätään ja käsitellään.Restin tärkeä määrittävä tekijä on tilattomuus.Toinen tärkeä osa on palvelin–asiakas-malli.Rest pohjaa vahvasti http-protokollan ominaisuuksiin. Http:n metodeja (get, post, put ja delete) sekä eri uri:ta käytetään kuvaamaan pyynnön luonnetta, jolloin itse pyynnön dataan ei tarvitse sisällyttää metatietoja. Jokaisella resurssilla on URL eli sen yksilöivä osoite.Erittäin yleinen konventio on muodostaa resurssien yksilöivät URLit liittäen resurssityypin nimi ja resurssin yksilöivä tunniste.
Erittäin yleinen konventio on muodostaa resurssien yksilöivät URLit liittäen resurssityypin nimi ja resurssin yksilöivä tunniste.
Html n avulla esitetään sivun rakenne ja sisältö = teksti ja kuvat. Htmlon kieli, jonka avulla WWW-selaimelle kerrotaan sivun millaisia osia WWW-dokumentti sisältää.
CSS on kieli, jonka avulla web-sovellusten ulkoasu määritellään
BACKEND
Node.js on avoimen lähdekoodin alustariippumaton JavaScript runtime-ympäristö JavaScript-koodin suorittamiseen palvelimella. Node.js mahdollistaa koodin suorittamisen suoraan palvelimella, jonka jälkeen verkkosivu lähetetään käyttäjälle. Node.jspohjautuu Googlen Chrome V8 JavaScript-moottoriin. Selaimet eivät vielä osaa uusimpia Javascriptin ominaisuuksia ja siksi selainpuolen koodi täytyy kääntää eli transpiloida esim babel:illa. Backendin toteutusympäristönä käytetään kurssilla Node.js:ää Backendissä Nodea suoritetaan koodia suoraan ilman transpilointivaihetta. Saat käynnistettyä interaktiivisen node-repl:in kirjoittamalla komentoriville node.
Node.js:n Express-sovelluskehys Nodella tapahtuvaa web-sovellusten ohjelmointia helpottamaan kehitelty ohjelmointirajapinnan tarjoama kirjasto.
middleware HTTP POST pyyntöjen käsittelyn apuri,middleware. Body-parserin toimintaperiaatteena on, että se ottaa pyynnön mukana olevan JSON-muotoisen datan, muuttaa sen Javascript-olioksi. Tapahtumankäsittelijäfunktio pääsee dataan käsiksi viittaamalla request.Body-parserin toimintaperiaatteena on, että se ottaa pyynnön mukana olevan JSON-muotoisen datan request-oliosta,muuttaa/parsii sen Javascript-olioksi ja sijoittaa request-olion kenttään body ennen kuin routen käsittelijää kutsutaan.
sovelluskehitystyökalu jota käytetään sovelluksen Backendin automaattiseen uudelleenkäynnistykseen.
Tarjoaa standardin tavan sille miten ja missä sovelluksen tila pidetään sekä tavalle tehdä tilaan muutoksia. Sovelluksen tilan hallinta erotetaan kokonaan Reactin komponenttien ulkopuolisiin varastoihin eli storeihin. Storessa olevaa tilaa ei muuteta suoraan, vaan tapahtumien eli actionien avulla.
Koko sovelluksen tila talletetaan yhteen storen tallettamaan Javascript-objektiin.Storen tilaa muutetaan actionien avulla. Actionit ovat olioita, joilla on vähintään actionin tyypin määrittelevä kenttä type.Actionien vaikutus sovelluksen tilaan määritellään reducerin avulla. Käytännössä reducer on funktio, joka saa parametrikseen olemassaolevan staten tilan sekä actionin ja palauttaa staten uuden tilan. Store käyttää reduceria käsitelläkseen actioneja, jotka dispatchataan eli “lähetetään” storelle sen dispatch-metodilla.
React Redux -kirjaston määrittelemä funktio connect on paras ratkaisu siihen, miten Redux-store saadaan välitettyä React-componenteille. Muita kenoja this.props.store tai context.
redux-thunk-kirjasto on ns. redux-middleware, joka mahdollistaa asynkronisten actionien luomisen.
JSON-muotoinen “raakadata”, tiedostoformaatti
NPM: Node Package Manager on pakettien hallinta työkalu, joka mahdollistaa moduulien julkaisun muiden käyttöön. npm eli Javascript-projektien hallintaan liittyvästä, alunperin Node-ekosysteemistä kotoisin oleva työkalu. Nykyään lähes kaikki Javascript-projektit määritellään node “pakkausmanagerin” eli npm:n avulla. Myös create-react-app:in avulla generoidut projektit ovat npm-muotoisia projekteja. Varma tuntomerkki siitä on projektin juuressa oleva tiedosto package.json.
Middlewaret ovat funktioita, joiden avulla voidaan käsitellä request- ja response-olioita. Esim. body-parser.
Yleismaailmallisia periaatteita Web-sovellusten toiminnasta: websovelluksen selaimessa suoritettava Javascript-koodi saa oletusarvoisesti kommunikoida vain samassa originissa olevan palvelimen kanssa. Muista origineista tulevat pyynnöt voidaan salli käyttämällä Noden cors-middlewarea.
json-server tallettaa kaiken datan palvelimella sijaitsevaan tiedostoon db.json. Todellisuudessa data tallennetaan johonkin tietokantaan. json-server on kuitenkin käyttökelpoinen apuväline, joka mahdollistaa palvelinpuolen toiminnallisuuden käyttämisen kehitysvaiheessa ilman tarvetta itse ohjelmoida mitään.
GET:in ja HEAD:in tulisi olla safe.Safety siis tarkoittaa, että pyynnön suorittaminen ei saa aiheuttaa palvelimelle sivuvaikutuksia eli esim. muuttaa palvelimen tietokannan tilaa, pyynnön tulee ainoastaan palauttaa palvelimella olevaa dataa.HTTP-pyynnöistä muiden paitsi POST:in tulisi olla idempotentteja:Eli jos pyynnöllä on sivuvaikutuksia, lopputulos on sama suoritetaanko pyyntö yhden tai useamman kerran.HTTP pyyntötyypeistä POST on ainoa joka ei ole safe eikä idempotent.
Async- ja await ovat ES7:n mukanaan tuoma uusi syntaksi, joka mahdollistaa promisen palauttavien asynkronisten funktioiden kutsumisen siten, että kirjoitettava koodi näyttää synkroniselta.ES7:ssa async ja await tuovat generaattoreiden tarjoaman toiminnallisuuden ymmärrettävästi ja syntaksin puolesta selkeällä tavalla koko Javascript-kansan ulottuville.Mistä tahansa kohtaa Javascript-koodia ei awaitia kuitenkaan pysty käyttämään. Awaitin käyttö onnistuu ainoastaan jos ollaan async-funktiossa.
Metodikutsu Note.find() palauttaa promisen, ja saamme itse operaation tuloksen rekisteröimällä promiselle tapahtumankäsittelijän metodilla then. Kaikki operaation suorituksen jälkeinen koodi kirjoitetaan tapahtumankäsittelijään. Jos haluaisimme tehdä peräkkäin useita asynkronisia funktiokutsuja joutuisimme tekemään kutsut tapahtumankäsittelijästä. Ketjuttamalla promiseja tilanne pysyy jollain tavalla hallinnassa, callback-helvetin eli monien sisäkkäisten callbackien sijaan saadaan aikaan siistihkö then-kutsujen ketju.
Asenna JWT jsonwebtoken-kirjasto, jonka avulla koodimme pystyy generoimaan JSON web token -muotoisia tokeneja.Token on digitaalisesti allekirjoitettu käyttämällä salaisuutena ympäristömuuttujassa SECRET olevaa merkkijonoa. Digitaalinen allekirjoitus varmistaa sen, että ainoastaan salaisuuden tuntevilla on mahdollisuus generoida validi token. Ympäristömuuttujalle pitää muistaa asettaa arvo tiedostoon .env.
Tokenin välittämiseen selaimesta backendiin käytämme ratkaisussamme Authorization-headeria. Tokenin lisäksi headerin avulla kerrotaan mistä autentikointiskeemasta on kyse. Skeeman ilmaiseminen kertoo näissä tapauksissa palvelimelle, miten mukana olevat kredentiaalit tulee tulkita.Käytetään Bearer-skeemaa.
Käyttäjätunnuksia, salasanoja ja tokenautentikaatiota hyödyntäviä sovelluksia tulee aina käyttää salatun HTTPS-yhteyden yli.
bcrypt-kirjasto: salasanojen hashaamiseen
Tietokantaan ei talleteta pyynnön mukana tulevaa salasanaa, vaan funktion bcrypt.hash avulla laskettu hash.
Selaimessa oleva avain-arvo- eli key-value-periaatteella toimiva tietokanta. Storageen talletetut arvot säilyvät vaikka sivu uudelleenladattaisiin. Storage on ns. origin-kohtainen, eli jokaisella selaimella käytettävällä web-sovelluksella on oma storagensa. Koska storageen talletettavat arvot ovat merkkijonoja, emme voi tallettaa storageen suoraan Javascript-oliota, vaan ne on muutettava ensin JSON-muotoon metodilla JSON.stringify. Vastaavasti kun JSON-muotoinen olio luetaan local storagesta, on se parsittava takaisin Javascript-olioksi metodilla JSON.parse.
Sen avulla voidaan määritellä propsit joille on “pakko” antaa arvo.
Sen avulla Redux-storen tilaa ja sitä muuttavia actioneja on mahdollisuus seurata selaimen konsolista.Selaimen lisäosan lisäksi debugatessa tarvitaan kirjastoa redux-devtools-extension.
Reactin valmis komponentti React router tarjoaa erinomaisen ratkaisun React-sovelluksen reititykseen ja navigaation hallintaan.Reititys, eli komponenttien ehdollinen, selaimen urliin perustuva renderöinti otetaan käyttöön sijoittamalla komponentteja Router-komponentin lapsiksi, eli Router-tagien sisälle. Kyseessä on BrowserRouter.Normaalisti selain lataa uuden sivun osoiterivillä olevan urlin muuttuessa. HTML5 history API:n avulla BrowserRouter kuitenkin mahdollistaa sen, että selaimen osoiterivillä olevaa urlia voidaan käyttää React-sovelluksen sisäiseen “reitittämiseen”, eli vaikka osoiterivillä oleva url muuttuu, sivun sisältöä manipuloidaan ainoastaan Javascriptillä ja selain ei lataa uutta sisältöä palvelimelta. Selaimen toiminta back- ja forward-toimintojen ja bookmarkien tekemisen suhteen on kuitenkin loogista, eli toimii kuten perinteisillä web-sivuilla. Selaimen urliin perustuen renderöitävät komponentit määritellään komponentin Route avulla.
Tehtävissä on käytössä MongoDB:tä joka on ns. dokumenttitietokanta. Mongosta käytetään netissä palveluna toimivaa mlab:in kantaa.
Mongoosea voisi luonnehtia: object document mapper (ODM), ja sen avulla Javascript-olioiden tallettaminen mongon dokumenteiksi on suoraviivaista. asennus: npm install mongoose --save
Liitoksen tekeminen suoritetaan mongoosen komennolla populate. Populaten yhteydessä on myös mahdollista rajata mitä kenttiä sisällytettävistä dokumenteista otetaan mukaan.
jest
API:n testaamisen käytetään Facebookin Jest supertest-kirjastoa. Frontin testauksessa käytetään lisäksi AirBnB:n kehittämää enzyme-kirjastoa.
Integraatiotestit = useita sovelluksen komponentteja yhtäaikaa käyttäviä testejä. (“valekomponentilla” eli mockilla.mongo-mock.)
Testien ajaminen konsolista
CI=true npm test
Testauskattavuus saadaan selville suorittamalla testit komennolla
CI=true npm test -- --coverage
Melko primitiivinen HTML-muotoinen raportti generoituu hakemistoon coverage/lcov-report