Sovelluksen siirtäminen verkkoon
Learning objectives
- Tutustut selaimessa toimivan sovelluksen siirtämiseen verkkoon.
Sovelluksen siirtäminen verkkoon vaatii, että käytössä olevalla koneella on Dartin sovelluskehityskirjasto (Dart SDK) asennettuna. Ohjeet sovelluskehityskirjaston asentamiseen löytyvät osoitteesta https://dart.dev/get-dart. Mikäli uusien ohjelmien asennus käytössäsi olevalle koneelle ei ole mahdollista, ei tämä haittaa. Kurssin suorittamisen kannalta sovelluksen siirtäminen verkkoon ei ole pakollista.
Siirrämme tässä verkkoon edellisessä osassa toteutetun kyselysovelluksen. Lopputulos on tarkasteltavissa osoitteessa https://fitech101.github.io/kysely/.
Sovelluksen siirtäminen verkkoon vaatii sekä sovelluksen valmistelun verkkoon siirtämistä varten että konkreettisen tilan, johon sovellus siirretään. Käytämme valmisteluun Dartin sovelluskehityskirjastoa, jonka asentamiseen löytyvät ohjeet osoitteesta https://dart.dev/get-dart. Hyödynnämme sovelluksen tilana sovellusten versiointiin tarkoitettua Github-palvelua.
Sovelluksen valmistelu
Sovelluksen valmistelu sisältää Dart-kielisen lähdekoodin kääntämisen selainten ymmärtämäksi JavaScript-kieleksi, JavaScript-kielisen tiedoston linkkaamisen HTML-dokumenttiin sekä tyylitiedoston linkkaamisen HTML-dokumenttiin.
Sekä HTML-dokumentti, CSS-tyylitiedosto, että Dart-kielinen lähdekoodi tulee tallentaa erillisiin tiedostoihin. Tallentaminen tulee tehdä tekstieditorilla tai muulla ohjelmalla, joka ei lisää tiedostoihin tyylejä. Tällainen editori on Windows-koneissa esimerkiksi notepad -- vastaavasti esimerkiksi Word ei tässä tapauksessa toimi. Hyvä vaihtoehto editorille on Visual Studio Code-ohjelmointiympäristö.
Oletetaan, että käytössämme on kolme tiedostoa: main.dart, index.html, ja styles.css. Tiedostojen sisällöt vastaavat aluksi edellisessä luotua ohjelmaa ja materiaalissa käytössä olleen ohjelmointiympäristön sisältöä.
Tiedoston main.dart sisältö on seuraava:
import 'dart:html';
main() {
var kysymykset = [];
var vaihtoehdot = [];
vaihtoehdot.add({'teksti': 'Kyllä', 'oikein': true});
vaihtoehdot.add({'teksti': 'Ei', 'oikein': false});
kysymykset.add({
'teksti': 'Siistiä?',
'vaihtoehdot': vaihtoehdot
});
kysymykset.add({
'teksti': 'Toimiiko?',
'vaihtoehdot': vaihtoehdot
});
querySelector('#seuraava').onClick.listen((e) {
kysymykset.shuffle();
asetaKysymys(kysymykset[0]);
});
}
asetaKysymys(kysymys) {
asetaKysymysteksti(kysymys['teksti']);
asetaVastausvaihtoehdot(kysymys['vaihtoehdot']);
}
asetaKysymysteksti(teksti) {
querySelector('#kysymys').text = teksti;
}
asetaVastausvaihtoehdot(vaihtoehdot) {
querySelector('#vastaukset').children.clear();
for (var i = 0; i < vaihtoehdot.length; i++) {
lisaaVastausvaihtoehto(vaihtoehdot[i]);
}
}
lisaaVastausvaihtoehto(vaihtoehto) {
var elementti = Element.div();
elementti.className = 'vaihtoehto';
elementti.text = vaihtoehto['teksti'];
elementti.onClick.listen((e) {
if (vaihtoehto['oikein']) {
elementti.text = 'oikein!';
} else {
elementti.text = 'väärin!';
}
});
querySelector('#vastaukset').children.add(elementti);
}Tiedoston index.html sisältö on seuraava:
<div id='kysymys'>Klikkaa nappia aloittaaksesi.</div>
<div id='vastaukset'>
</div>
<div id="nappi">
<button id="seuraava">Seuraava kysymys</button>
</div>Tiedoston styles.css sisältö on seuraava:
body {
background-color: snow;
padding: 1rem;
}
#kysymys {
background-color: lightgreen;
border-radius: 15px;
text-align: center;
padding: 1rem;
margin: 1rem;
}
.vaihtoehto {
background-color: lightblue;
border-radius: 15px;
text-align: center;
padding: 1rem;
margin: 1rem;
}
.vaihtoehto:hover {
background-color: lightskyblue;
}
#seuraava {
padding: 1rem;
margin: 1rem;
}
#nappi {
text-align: center;
}Oletetaan, että kaikki tiedostot sijaitsevat samassa kansiossa. Dart-kielisen kirjaston valmistelu verkkoon siirtämistä varten tapahtuu Dart SDK:n mukana tulevalla dart-komennolla. Käynnistetään käyttöjärjestelmän konsoli kansioon, jossa tiedostot sijaitsevat. Kansiossa suoritetaan komento dart compile js -o app.js main.dart.
$ dart compile js -o app.js main.dart
Compiled [...] characters Dart to [...] characters JavaScript in [...] seconds
Dart file main.dart compiled to JavaScript: app.jsKomento luo main.dart-nimisestä Dart-kielistä lähdekoodia sisältävästä tiedostosta JavaScript-kielisen lähdekooditiedoston. Komento tallentaa luodun JavaScript-kielisen lähdekoodi tiedostoon app.js.
Mikäli käytössäsi on vanha versio Dart SDK:sta (<= 2.17.0), ylemmän esimerkin komennon sijasta vastaava komento kääntämiseen on dart2js -o app.js main.dart -- Dart SDK:n version saa selville suorittamalla komennon dart --version.
Uusilla versiolla Dart SDK:sta (>= 2.12.0), kääntäminen ei onnistu suoraan, sillä uudempi Dart ei salli mahdollisia null-arvoista aiheutuvia ajonaikaisia virheitä. Dart ilmoittaa tällöin seuraavanlaisista ongelmista:
main.dart:20:30:
Error: Property 'onClick' cannot be accessed on 'Element?' because it is potentially null.
- 'Element' is from 'dart:html'.
querySelector('#seuraava').onClick.listen((e) {
^^^^^^^
main.dart:32:29:
Error: Property 'text' cannot be accessed on 'Element?' because it is potentially null.
- 'Element' is from 'dart:html'.
querySelector('#kysymys').text = teksti;
^^^^
main.dart:36:32:
Error: Property 'children' cannot be accessed on 'Element?' because it is potentially null.
- 'Element' is from 'dart:html'.
querySelector('#vastaukset').children.clear();
^^^^^^^^
main.dart:56:32:
Error: Property 'children' cannot be accessed on 'Element?' because it is potentially null.
- 'Element' is from 'dart:html'.
querySelector('#vastaukset').children.add(elementti);
^^^^^^^^
Error: Compilation failed.Ongelman voi ratkaista kertomalla Dart:lle että projektin tulee toimia vanhalla Dart:n versiolla luomalla projektitiedosto pubspec.yaml.
name: sovellus_verkkoon
environment:
sdk: '>=2.7.0 <3.0.0'Jonka jälkeen, konsolissa samassa kansiossa tulee vielä ajaa komento, jolla asetetaan projektille pubspec.yaml:n mukaiset riippuvuudet.
dart pub getNyt Dart SDK tietää että projektissa ei välttämättä vielä ole null-tarkastuksia ja kääntäminen onnistuu.
Ulkopuolisia kirjastoja sisältävät sovellukset
Tässä esimerkissä oletetaan, että sovellus ei käytä ulkopuolisia kirjastoja. Ulkopuolisia kirjastoja (kuten käyttämämme tietokantakirjasto) sisältävät projektit paketoidaan käyttöä varten Dartin https://dart.dev/tools/webdev-komentirivityökalulla.
Kun Dart-kielinen lähdekooditiedosto on käännetty JavaScript-kielelle, se linkataan index.html-tiedostoon. Muokataan index.html-tiedostoa ensin siten, että se sisältää HTML-dokumenteissa olevat html, head, ja body-elementit.
<html>
<head>
<title>Kyselysovellus</title>
</head>
<body>
<div id='kysymys'>Klikkaa nappia aloittaaksesi.</div>
<div id='vastaukset'>
</div>
<div id="nappi">
<button id="seuraava">Seuraava kysymys</button>
</div>
</body>
</html>JavaScript-kielinen tiedosto tuodaan sivun käyttöön script-elementin avulla. Elementille asetetaan attribuutti src, jonka arvoksi tulee JavaScript-kielisen tiedoston nimi (eli tässä app.js) sekä attribuutti defer, jolle ei aseteta arvoa. Attribuutti src määrää myös mistä kyseistä tiedostoa etsitään -- mikäli arvoksi asetetaan vain tiedoston nimi, haetaan tiedostoa samasta kansiosta kuin missä tiedosto index.html sijaitsee. Attribuutti defer määrää, että JavaScript-tiedoston sisältö suoritetaan vasta kun sivu on täysin latautunut. Mikäli attribuutti jätetään pois, on mahdollista että ohjelma ei löydä seuraava-nappia, jota käytetään seuraavan kysymyksen hakemiseen.
Alla olevassa esimerkissä HTML-dokumenttiin on lisätty linkki app.js-nimiseen JavaScript-tiedostoon. Kun selain lataa HTML-dokumentin, lataa se myös JavaScript-tiedoston.
<html>
<head>
<title>Kyselysovellus</title>
<script src='app.js' defer></script>
</head>
<body>
<div id='kysymys'>Klikkaa nappia aloittaaksesi.</div>
<div id='vastaukset'>
</div>
<div id="nappi">
<button id="seuraava">Seuraava kysymys</button>
</div>
</body>
</html>Tyylitiedoston linkkaaminen HTML-dokumenttiin toimii samalla tavalla, joskin käytetyn elementin nimi on eri. Tyylitiedosto ladataan elementillä link, jolle annetaan kaksi attribuuttia: ladattavan tiedoston tyyppi (rel="stylesheet") ja ladattavan tiedoston osoite (href="styles.css"). Alla olevaan HTML-dokumenttiin on lisätty linkki tyylitiedostoon.
<html>
<head>
<title>Kyselysovellus</title>
<script src='app.js' defer></script>
<link rel='stylesheet' href='styles.css'>
</head>
<body>
<div id='kysymys'>Klikkaa nappia aloittaaksesi.</div>
<div id='vastaukset'>
</div>
<div id="nappi">
<button id="seuraava">Seuraava kysymys</button>
</div>
</body>
</html>Samalla tavalla kuin script-elementin src-attribuutti, link-elementin href-attributti määrää myös mistä tiedostoa haetaan. Mikäli attribuutin arvoksi annetaan vain tiedoston nimi, haetaan tiedostoa samasta kansiosta kuin missä index.html-tiedosto sijaitsee. Sivun voi halutessaan avata selaimella omalta koneelta -- tämä onnistuu esimerkiksi menemällä index.html-dokumentin sisältävään kansioon tiedostojärjestelmässä, klikkaamalla tiedostoa, ja valitsemalla avaa selaimessa.
Kysymysten lataaminen sovelluksessa
Kuten ehkä huomaat, edellä käsiteltävä sovellus on sovelluksen versio, joka ei lataa kysymyksiä verkosta. Mikäli haluat että sovellus lataa kysymykset, voit luoda JSON-muotoisen dokumentin samaan kansioon, missä sovellus sijaitsee, ja muokata sovellusta siten, että dokumentti haetaan nykyisestä osoitteesta. Tämä onnistuu muuttamalla main-funktio seuraavaan muotoon:
main() async {
var osoite = 'kysymykset.json';
var sisalto = await HttpRequest.getString(osoite);
var sanakirja = jsonDecode(sisalto);
var kysymykset = sanakirja['kysymykset'];
querySelector('#seuraava').onClick.listen((e) {
kysymykset.shuffle();
asetaKysymys(kysymykset[0]);
});
}Yllä oletetaan, että kysymykset sijaitsevat tiedostossa nimeltä kysymykset.json ja että kyseinen tiedosto on samassa kansiossa tiedoston index.html kanssa.
Sovelluksen siirtäminen verkkoon
Tässä esimerkissä sovellus siirretään Github-palveluun, josta sitä voi tarkastella. Mikä tahansa muukin sijainti toimii, mikäli sellainen on saatavilla. Oletuksena on, että Githubiin on luotu (ilmainen) käyttäjätunnus.
Luodaan Githubiin ensin uusi tiedostovarasto (repository). Tämä tapahtuu valitsemalla Create a new repository (tai valitsemalla Repositories-kohdan vierestä New). Asetetaan tässä tiedostovaraston nimeksi kysely ja valitaan että tiedostovarasto on julkinen (public).
Tämän jälkeen klikataan nappia Create repository, joka luo tiedostovaraston. Nyt käytössämme on paikka, johon voimme lisätä tiedostoja. Vaikka käytämme tässä termiä tiedostovarasto, termi ei kuvaa täysin tiedostovaraston toiminnallisuutta. Varastoinnin lisäksi tiedostovarasto pitää kirjaa tiedostojen historiasta ja muutoksista -- tämän lisäksi tiedostovarastoon lisättyjen tiedostojen historian tarkastelu on mahdollista.
Githubin käyttöön voidaan käyttää Git-nimistä versionhallintaohjelmistoa. Git on oleellinen työväline ohjelmistojen kehityksessä -- jos osaat käyttää sitä, kannattaa poiketa seuraavista ohjeista. Tutustumme tässä hieman yksinkertaisempaan tapaan.
Klikataan sivulta linkkiä upload an existing file eli lisää olemassaoleva tiedosto. Tämä avaa seuraavanlaisen sivun, johon lisättävät tiedostot voidaan raahata ja pudottaa (drag and drop).
Liitetään sivulle tiedostot index.html, app.js, ja styles.css. Kun tiedostot näkyvät lisättyjen listalla (kuten alla), klikataan Commit changes-nappia.
Kun Commit changes-nappia on painettu, tiedostot siirtyvät tiedostovarastoon. Tämä saattaa kestää hetken.
Tämän jälkeen tiedostovaraston asetuksia tulee muokata siten, että tiedostovarasto tietää mistä sivut näytetään. Valitaan Settings ja etsitään asetussivulta kohta Github Pages. Valitaan sijainniksi master ja kansioksi / (root). Klikataan tämän jälkeen nappia Save.
Nyt lisättyjä tiedostoja voi tarkastella selaimella. Tiedostojen sijainti määräytyy käyttäjätunnuksen (tai organisaatiotunnuksen) ja tiedostovaraston nimen perusteella. Yllä olevassa esimerkissä käyttäjätunnus (tai organisaatiotunnus) on FITech101 ja tiedostovaraston nimi on kysely.
Sivu löytyy osoitteesta tunnus.github.io/tiedostovaraston_nimi eli tässä tapauksessa osoitteesta https://fitech101.github.io/kysely/.
Question not found or loading of the question is still in progress.
Hi! Please help us improve the course!
Please consider the following statements and questions regarding this part of the course. We use your answers for improving the course.
I can see how the assignments and materials fit in with what I am supposed to learn.
I find most of what I learned so far interesting.
I am certain that I can learn the taught skills and knowledge.
I find that I would benefit from having explicit deadlines.
I feel overwhelmed by the amount of work.
I try out the examples outlined in the materials.
I feel that the assignments are too difficult.
I feel that I've been systematic and organized in my studying.
How many hours (estimated with a precision of half an hour) did you spend reading the material and completing the assignments for this part? (use a dot as the decimal separator, e.g 8.5)
How would you improve the material or assignments?