Tvorba internetových aplikací

Jakub Klinkovský

:: České vysoké učení technické v Praze
:: Fakulta jaderná a fyzikálně inženýrská
:: Katedra softwarového inženýrství

Akademický rok 2023-2024

Skriptovací technologie

Od statických stránek k dynamickým aplikacím

Jazyk HTML byl navržen jako statický pro poskytování neměnného obsahu. Postupně vznikly různé skriptovací technologie, které umožňují generovat a/nebo měnit obsah dynamicky.

Skriptovací technologie

  • na straně klienta (kód je prováděn přímo v prohlížeči bez zapojení serveru, přístup k objektové reprezentaci dokumentu)
    Použití: změna stránky v reakci na vstup uživatele (kliknutí myši, stisknutí klávesy)

  • na straně serveru (komunikace pomocí formulářů a URL parametrů, server vygeneruje a odešle příslušný HTML dokument)
    Použití: změna stránky na základě parametrů, dat z formuláře, stavu databáze, uplynulého času, atd.

Statický vs dynamický web server

  1. Statický web server:
    • odesílá pouze soubory uložené na disku (poznámka: skripty pro zpracování na straně klienta jsou z pohledu serveru statické soubory)
    • adresa URL je převedena na cestu v souborovém systému
    • nepotřebná vstupní data (URL parametry, formuláře) se ignorují
    • velmi jednoduchý, efektivní, bezpečný
  2. Dynamický web server:
    • požadavky předává nakonfigurovanému programu včetně všech vstupních dat
    • složitá konfigurace, velké množství protokolů a rozhraní
    • riziko zahlcení a bezpečnostních děr
    • může převzít úlohu statického web serveru

Skriptovací technologie na straně serveru

  1. Dynamický web server (software) – např. Apache, Nginx, Microsoft IIS
  2. Rozhraní pro spuštění programu na serveru
  3. Program v daném skriptovacím jazyku
  4. Databázový systém, souborový systém, operační systém...
  • Možnosti: plnohodnotné aplikace, spolupráce s formuláři, databázemi, soubory na serveru a s elektronickou poštou
  • Potřebné znalosti: HTML, komunikace mezi HTML a serverem (URL, formuláře, HTTP protokol), zkušenost s programováním, případně databáze a OS

Nejběžnější operační systém pro web servery

Systém Podíl
Unix 84.4%
Windows 15.9%

Poznámka:
Unix = Linux + BSD + Darwin + macOS + HP-UX + Solaris + Minix + Unknown

Nejběžnější web servery

Server Podíl
Nginx 34.1%
Apache 30.2%
Cloudflare Server 21.6%
LiteSpeed 13.2%
Microsoft-IIS 5.0%
Node.js 3.1%
Google Servers 0.9%

CGI (Common Gateway Interface)

  • rozhraní, které definuje způsob spuštění programu a předání dat mezi web serverem a CGI skriptem = programem, který generuje HTML dokumenty
  • formát pro předávání parametrů je složitý
  • pro psaní skriptů se používaly interpretované jazyky nebo příkazové shelly Unixu (typicky Perl, ale i C++, ...)
  • správa větších aplikací je programátorsky náročná
  • vytlačen „lepšími“ technologiemi – FastCGI, SCGI
  • v současné době mají nejpopulárnější skriptovací jazyky vlastní API, např. PHP FastCGI Process Manager, Python WSGI nebo ASGI, ASP.NET HTTP Handler, ...

SSI (Server Side Includes)

SSI je jednoduchý skriptovací jazyk, kde se do HTML stránky zadávají jednoduché příkazy (jako HTML komentáře). Patří k nejstarším skriptovacím jazykům.

Příklad:

<!--# if expr="$name = /(.+)@(?P<domain>.+)/" -->
    <!--# echo var="1" -->
    <!--# echo var="domain" -->
<!--# endif -->
<!--# include file="footer.html" -->
  • typická přípona .shtml, .stm, nebo .shtm
  • výhoda: pokud server nebyl schopen provést SSI, uživatel viděl alespoň neinterpretovaný obsah stránky
  • nevýhoda: nelze zpracovávat data od uživatele

Nejběžnější serverové skriptovací jazyky

Jazyk Podíl 2022 Podíl 2023 Podíl 2024
PHP 78.1% 77.6% 76.5%
ASP.NET 7.9% 7.2% 6.4%
Ruby 6.0% 5.1% 5.7%
Java 3.7% 4.7% 4.7%
JavaScript 1.8% 2.0% 3.2%
Scala 2.3% 2.9% 3.0%
static files 1.5% 1.9% 1.8%
Python 1.4% 1.4% 1.4%

PHP

PHP = PHP: Hypertext Preprocessor je skriptovací jazyk, který je navržený přímo pro programování webových aplikací.

  • open-source, multiplatformní
  • příkazy se zadávají do HTML mezi tagy <?php a ?>
  • rychlý vývojový cyklus, současná verze 8.3
  • výhody:
    • velké množství dostupných frameworků
    • vestavěné funkce zaměřené na výkon a bezpečnost
  • nevýhody:
    • není vhodný pro vývoj desktopových a mobilních aplikací
    • nestačí jazykům jako Python nebo Ruby co do počtu dostupných knihoven

ASP, ASP.NET, ASP.NET Core

ASP (Active Server Pages) je první serverový skriptovací jazyk od Microsoftu.

  • příkazy se zadávají do HTML mezi značky <% a %>

ASP.NET je framework firmy Microsoft pro vývoj webových aplikací.

  • rozšiřuje ASP o mnoho nových možností: práce s plnohodnotnými jazyky a .NET Frameworkem – rozsáhlý objektový model, přes který se pracuje s databázemi, soubory, cookies, sessions, grafikou atd.
  • open-source

ASP.NET Core

  • modulární reimplementace frameworku ASP.NET
  • open-source

Java, Scala

Java je obecný objektový programovací jazyk a s ním související platforma kombinující různé technologie pro vývoj velkých aplikací. V současnosti je populární pro tvorbu webových aplikací postavených na architektuře klient-server.

  • nevýhoda: komplikovaný systém
  • výhoda: umožňuje provozovat více serverů v rámci jedné aplikace
  • aplikační servery jsou od různých dodavatelů

Scala je objektový a funkcionální programovací jazyk, který lze provozovat na platformě Java. Populární framework pro vývoj webu je Play!

JavaScript

První pokusy použít JavaScript na serveru: SSJS (server-side JavaScript) od firmy Netscape, JScript a JScript.NET od firmy Microsoft.

V současnosti je nejpoužívanější prostředí Node.js:

  • výkonný engine V8 z Google Chrome
  • open-source
  • multiplatformní (MS Windows, GNU/Linux, macOS, Android, ...)
  • hojně využívá model událostí a asynchronní I/O operace (minimalizace režie procesoru, maximalizace výkonu)
  • velký ekosystém dostupných knihoven

Ruby on Rails

Ruby („rubín“) je obecný, vysokoúrovňový, dynamický, interpretovaný programovací jazyk vzniklý roku 1995 v Japonsku.

Ruby on Rails je vysokoúrovňový framework pro vývoj webových aplikací, který používá návrhový vzor MVC (model-view-controller) a filozofii CRUD (create, read, update, delete)

  • ke spuštění webové aplikace stačí databáze a web server
  • základní princip: konvence má přednost před konfigurací (programátor konfiguruje pouze ty části aplikace, které se liší od běžného nastavení)
  • další princip: don't repeat yourself

Python

Python je obecný, vysokoúrovňový, dynamický, interpretovaný programovací jazyk navržený s důrazem na čitelnost kódu. Jeho principy jsou shrnuty v dokumentu Zen of Python.

Skriptovací technologie na straně klienta

  • Příklady: JavaScript, WebAssembly, VBScript, ActionScript, Flash, ...
  • Požadavky: podpora prohlížeče a uživatele (ten nesmí mít zakázáno používání klientských skriptů)
  • Možnosti: stejné jako skriptování na straně serveru (kompletní kontrola nad objektovou reprezentací dokumentu, možnost asynchronního načítání zdrojů)
  • Potřebné znalosti: HTML, základy programování, CSS

Princip webových aplikací s klientskými skripty

  1. Klient (prohlížeč na počítači uživatele) načte HTML dokument, ke kterému jsou připojeny skripty.
  2. Během načítání a renderování dokumentu klient také načítá a vykonává skripty.
  3. Skripty pracují s objektovým modelem dokumentu (DOM), který mohou měnit.
  4. Skripty mohou využívat AJAX (Asynchronous JavaScript and XML)
    • koncept je postaven na technologiích: HTML a CSS (prezentace uživateli), DOM (reprezentace stavu), JSON nebo XML (výměna dat), XMLHttpRequest (asynchronní komunikace se serverovou částí aplikace), JavaScript

Document Object Model (DOM)

center contain

Asynchronous JavaScript and XML (AJAX)

center contain

Representational state transfer (REST)

REST je popis softwarové architektury, který se snaží definovat „standardní“ chování webových aplikací. Ne všechny služby mu odpovídají.

Je založen na šesti omezeních:

  1. komunikace mezi klienty a servery – předpoklad nějakého API
    (oddělení zodpovědnosti, klientská část má na starosti UI, server se stará o data)
  2. bezstavová komunikace – vede k efektivitě
    (server neudržuje informace o session, ty musí přijít v každém požadavku)
  3. cacheování – vede k efektivitě a škálovatelnosti
    (opakované požadavky lze eliminovat po dobu platnosti daného zdroje)
  4. jednotné rozhraní (identifikace zdrojů pomocí URI, DOM, media type, HATEOAS)
  5. vrstvený systém (proxy, load balancer, content delivery network)
  6. code on demand (přenos spustitelného kódu – skriptování na straně klienta)

REST v praxi

API splňující požadavky konceptu REST se označují jako „RESTful“. Např. MediaWiki.

Protipříklady:

  • kódování údajů o uživatelském stavu (session) do URL porušuje REST a může negativně ovlivnit cacheování a škálovatelnost serverové aplikace
  • HTTP cookies často porušují REST – mohou se desynchronizovat
  • ignorování hypertextu, media type, návratových kódů, a další protipříklady

Nevýhody:

  • komplikované udržování stavu na straně klienta
  • neřeší bezpečnost

JavaScript

Úvod do skriptování na straně klienta

JavaScript: základy

JavaScript je klientský skriptovací jazyk vyvinutý společnostmi Netscape a Sun roku 1995. První standardizovaná verze ECMAScript 1997, aktuální ECMAScript 2023.
Více o historii: w3schools, zdrojak.cz.

Charakteristiky jazyka:

  • dynamicky typovaný
  • objektově orientovaný
  • case-sensitive (rozlišuje velikost písmen klíčových slov, identifikátorů, atd.)
  • interpretovaný, resp. just-in-time kompilovaný (multiplatformní)

Poznámka: Funguje, když uživatel nevypnul podporu JavaScriptu v prohlížeči.

JavaScript: výhody použití

  • může modifikovat, přidávat a odebírat libovolné elementy v dokumentu
  • může reagovat na události (např. kliknutí, změna dat ve formuláři)
  • může měnit některé vlastnosti prohlížeče (např. text ve stavovém řádku)
  • pomáhá eliminovat komunikaci se serverem (zpracování kódu přímo v prohlížeči)
  • možnost načtení dodatečných dat ze serveru a jejich zobrazení (AJAX)

JavaScript: omezení

  • nemá přístup k souborovému systému uživatele (bezpečnostní riziko)
  • uživatel jej může v prohlížeči zakázat
  • kompatibilita mezi verzí jazyka a verzí prohlížeče
  • nemůže trvale ukládat data (stav aplikace) – jediné spolehlivé a bezpečné úložiště je na serveru

Začlenění JavaScriptu do HTML

  1. Externí soubor připojený pomocí značky script:

    <script src="soubor.js" type="text/javascript"></script>
    
  2. Interní skript napsaný uvnitř značky script.

  3. Kód napsaný v hodnotě vhodného atributu nějaké značky. Většinou se týká událostí. Např. <input onclick="funkce()">

Značka script se může vyskytovat ve značce head (typické použití) nebo i ve značce body (umístění na konec dokumentu pro optimalizaci přístupnosti).

Syntaxe JavaScriptu – ECMAScript

Syntaxe jazyka JavaScript je podobná jazykům C/C++/Java.

Základy:

Poznámka: Následující příklady si zkoušejte interaktivně, např. pomocí konzole v prohlížeči (Ctrl+Shift+I) nebo na https://flems.io/

Proměnné

Deklarace proměnné se provádí pomocí klíčových slov var, let, nebo const, možno i s inicializací. Deklarace proměnné není povinná, stačí přiřazení. Datový typ se rozpozná automaticky.

Výrazy se tvoří z konstant, proměnných, operátorů a volání funkcí.

Příklady:

var x;
let x2 = undefined;
const a = "this value cannot be reassigned";

Viz také rozdíly mezi var a let.

Název musí začínat písmenem (resp. podtržítkem), poté lze použít i číslice.

Datové typy

Primitivní datové typy:

  • Undefined (nedefinovaný typ): speciální hodnota undefined
  • Number: 1, 2.3, 3e4, atd. (pouze 64-bitová s plovoucí desetinnou čárkou)
  • BigInt: 9999999999999999n, BigInt(1234567890123456789012345)
  • String: "já jsem string", 'já jsem taky string'
    (řetězec ve dvojitých uvozovkách interpretuje metaznaky, např. \n)
  • Boolean: true a false
  • Object, Symbol, Function, ...

Viz také Standard built-in objects.

Operátory

  1. řetězcové: + (spojení řetězců)
  2. aritmetické:
    • unární: +, -, ++, --,
    • binární: +, -, *, / (neceločíselné), % (zbytek po dělení), ** (mocnění)
  3. bitové: (negace), & (and), | (or), ^ (xor)
  4. bitové posuny: <<, >>, >>>
  5. logické (mají zkrácené vyhodnocování): ! (negace), && (and), || (or), podmíněný operátor: c ? t : f
  6. relační: >, <, >=, <=, ==, !=, ===, !==
  7. přiřazovací: = a kombinace s binárním operátorem (např. +=),
  8. a další...

Priorita operátorů

Priorita operátorů (od nejvyšší po nejnižší, na téže úrovni zleva doprava):

  1. závorky ()
  2. unární operátory: ! ∼ - ++ --
  3. * / %
  4. binární aritmetické operátory: + (řetězce!) + (čísla) - (čísla)
  5. << >> >>>
  6. <= >= < >
  7. == === != !===
  8. & ^ |
  9. && || ?:
  10. = += -= atd.
  11. , (operátor čárka, např. uvnitř kulatých nebo hranatých závorek)

Řízení běhu skriptu I

  • Podmíněný příkaz if-else
    Příklad: (složené závorky jsou nepovinné, stejně jako v C++)
    if (a < 5) {
      b += 2;
    }
    else { // nepovinná část
      b = 0;
    }
    
  • Přepínač switch
    Příklad:
    switch (a) {
      case 1: b = 5; c = 10; break;
      case 2: b = 7; break;
      default: b = 0; // nepovinná část
    }
    

Řízení běhu skriptu II

  • Cyklus for
    Příklad:
    for (let i = 0; i < 10; i++) {
      b += 4;
      t += "ha";
    }
    
    // iterování přes prvky pole
    const items = ["a", "b", "c"];
    for (let i in items) {
      text += items[i];
    }
    
    // iterování přes atributy objektu
    const person = {fname: "John", lname: "Doe", age: 25};
    for (let key in person) {
      text += person[key];
    }
    

Řízení běhu skriptu III

  • Cyklus while s podmínkou na začátku      Příklad:
    while (a < 5) {
      text += a + "a";
      a++;
    }
    
  • Cyklus do-while s podmínkou na konci     Příklad:
    // provede se alespoň 1x
    do {
      b += 3;
      a--;
    } while (a > 3);
    
  • Příkazy continue a break

Výjimky

Syntaxe pro zachytávání výjimek je podobná C++:

try {
  tryStatements
} catch (exceptionVar) {
  catchStatements
} finally {
  finallyStatements
}

Pro vyvolání výjimky slouží příkaz throw:

throw error; // Throws a previously defined value (e.g. within a catch block)
throw new Error("Required"); // Throws a new Error object

Deklarace funkce

  • definice a deklarace nové funkce:
    function jmeno(vstup1, vstup2...) {
      příkazy_těla_fce
    }
    
    • Vstupů může být libovolné množství nebo nemusí být žádný (závorky povinné, třebaže prázdné).
    • Je-li mezi příkazy těla funkce uveden příkaz return x;, pak funkce vrátí hodnotu výrazu x a skončí.
    • Funkce smí vrátit nejvýše jednu hodnotu.
  • volání funkce: výraz jmeno(hodnoty_vstupů) (výsledek může být undefined)

Více na w3schools: JavaScript function Statement nebo JavaScript Functions.

„Arrow function“ syntaxe

Alternativní způsob definice funkce:

var h =   () => "Hello, world!";
var f =   (a, b) => a + b;
var g =   x => { return x ** 2; };
  • vhodný způsob pro anonymní funkce (funkcionální programování)
  • oproti deklaraci s klíčovým slovem function má tato syntaxe řadu omezení

Více na MDN Web Docs

Nativní objekty

  • null

  • Array: const array_name = [item1, item2, ...];

  • Date: const d = new Date("2022-03-25"); (celkem 9 různých „konstruktorů“)

  • Error: throw new Error("Something went wrong.");

  • Math: Math.PI atd.

  • Regular Expression: /pattern/modifiers;

  • Function: var add = function(x, y) { return x + y; };

Deklarace objektu

POJO = Plain Old JavaScript Object:

const person = {
  name: {
    first: "John",
    last: "Doe"
  },
  age: 25,
  hobbies: ["chess", "programming"]
};

Tato syntaxe vedla k definici formátu JSON (JavaScript Object Notation).

Přistup k atributům (a metodám) – lze je dynamicky měnit (přiřazovací operátor):

  • pomocí tečky: person.name.first
  • pomocí hranatých závorek: person["name"]["first"]

Více informací: w3schools tutorial, Object initializer, Working with JSON.

Deklarace třídy

Základní syntaxe pro deklaraci třídy:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

let r = new Rectangle(1, 2);

Tělo třídy může obsahovat: definice metod, gettery, settery, atributy.

Atributy i metody mohou být označeny klíčovým slovem static.

Atributy i metody mohou být buď veřejné (defaultně) nebo privátní.

Strict mode

Strict mode umožňuje programátorům volitelně zapnout striktnější režim interpretování kódu JavaScriptu, který má oproti standardnímu módu několik odlišností:

  1. Tiché chyby se projeví výjimkami (např. přiřazení do nedeklarované proměnné, deklarace funkce s duplicitními parametry, atd.)
  2. Umožňuje interpretu provést lepší optimalizace kódu (např. díky zjednodušené správě oboru platnosti proměnných)
  3. Zakazuje určité syntaktické prvky, které by mohly odporovat budoucím verzím standardu ECMAScript

Strict mode lze zapnout příkazem "use strict"; buď pro celý skript (na začátku souboru) nebo pro určitou funkci (na začátku její definice).

Třídy a moduly jsou vždy automaticky ve strict mode.

JavaScript v prostředí prohlížeče

JavaScript = ECMAScript + BOM + DOM

  • window = objekt poskytující interakci s prohlížečem (browser object model, BOM)
    • document = objekt reprezentující obsah dokumentu (DOM)
    • location – objekt reprezentující aktuální URL
    • history – poskytuje rozhraní pro navigaci mezi navštívenými stránkami
      (ve většině prohlížečů omezený kvůli bezpečnosti)
    • navigator – sada vlastností prohlížeče
    • ...

Objektový model prohlížeče (BOM)