Přejít k navigační liště

Zdroják » JavaScript » IMA.js – setup aplikace a vytvoření modelů

IMA.js – setup aplikace a vytvoření modelů

Články JavaScript

V tomto díle začneme psát naši ukázkovou aplikaci. Povedeme Vás od úplného začátku až po finální deployment do produkce. V průběhu si ukážeme využití všech hlavních vlastností IMA.js a jak vytvořit často používané prvky webových aplikací.

Minule jsme si framework IMA.js představili, dnes se pustíme do práce.

Ukázková aplikace bude zobrazovat počasí v místě, které:

  • uživatel vyhledá pomocí našeho vyhledávání
  • bude zadáno v URL parametru (SEO optimalizace)
  • uživatel nastaví a uloží jej do cookies.
  • je nastaveno v aplikaci jako výchozí, pokud se nepoužije žádná z výše uvedených možností.

Pro jednoduchost pojmenujeme aplikaci WeatherApp.

Devtooly

Než se pustíme do samotného vývoje ukázkové aplikace, rádi bychom zmínili naše vývojové nástroje v podobě rozšíření do prohlížeče Google Chrome, které si můžete stáhnout zde. Tyto nástroje poskytují jednoduchý způsob, jak sledovat a ladit jednotlivá volání a události, které ve vaší aplikaci probíhají.

Vývojovým nástrojům se budeme blíže věnovat v následujících dílech, pokud však chcete, můžete je začít používat už teď. Případně si o jejich možnostech něco pročíst v dokumentaci.

Setup

Slíbili jsme, že to vezmeme od začátku, ale také to nebudeme prodlužovat. Na instalaci taky není nic zajímavého.

K vývoji budete potřebovat:

  • Node.js ve verzi 10 a výše
  • NPM ve verzi 6 a výše.
cd <-- Váš adresář kde máte projekty -->
npx create-ima-app weather-app

Při dotazu na volbu typu projektu vyberte Empty. IMA.js totiž nabízí 3 demo „aplikace“, ze kterých si můžete vybrat. Jejich ukázky najdete na imajs.io/examples.

Pro naši aplikaci postačí základní Empty (Hello world!). Můžete však použít i Todos (TODO list aplikace) nebo Feed (Twitter-like feed aplikace).

Tímto máme vytvořený skeleton aplikace a nainstalované závislosti.

Adresářová struktura

V adresáři naší aplikace vzniklo několik podadresářů: appbuildnode_modules a server. My se budeme zabývat pouze adresářem app (ostatní jsou vysvětleny svým názvem).

  • assets – obsahuje soubory, které jsou zpracovány pre-processory a zkopírovány do build adresáře.
    • less – LESS soubory definující obecná pravidla, makra, mixins a základní strukturu UI.
    • static – jakékoliv soubory, které nepotřebují preprocessing (JS soubory 3. stran, obrázky, …)
  • component – naše React komponenty, které budeme používat ve views. Více o komponentách si řekneme v 3. díle tohoto seriálu.
  • config – konfigurační soubory aplikace. Nyní se konfigurací nebudeme zabývat a ukážeme si jednotlivé možnosti až je budeme potřebovat v průběhu vytváření aplikace.
  • page – controllery, views a LESS soubory k views.
    • error – stránka, která se zobrazí pokud se vyskytne chyba v průběhu aplikace.
    • home – hlavní stránka aplikace
    • notFound – stránka, která se zobrazí pokud uživatel zadá URL na neexistující routu.

Adresáře assets a config jsou povinné a měly by se v aplikaci vždy nacházet. Ostatní jsou volitelné a můžete si je přejmenovat. Je však potřeba upravit některé konfigurace a přihlížet k tomu v následném vývoji aplikace.

Modely

Modely nám v IMA.js aplikacích umožňují pracovat s daty. Pomocí modelů se data načítají, odesílají a transformují. V našem případě budeme využívat základní sestavu modelů (ServiceEntityResource a Factory).

  • Entity představuje objekt držící data nějakého celku (uživatele, článku, …).
  • Factory vytváří ze surových dat instance Entity.
  • Resource stahuje data ze serveru pomocí HTTP požadavků.
  • Service se stará o načítání dat z Resource a následné vytvoření entit pomocí Factory.

Může se vám zdát, že Factory a Resource jsou zbytečné. Data můžeme přece stahovat už v Service a tam také vytváře instance Entity. Ano to jistě můžeme, ale jen v jednodušších případech. Jak se bude aplikace rozrůstat a začnou se objevovat zanořené závislosti, věřte, že samostatné Factory a Resource přijdou vhod.

Pokud by aplikace využívala REST API, můžeme Factory a Resource úplně nahradit použitím @ima/plugin-rest-client. Více o tomto pluginu se dočtete v jeho README.

Na začátku jsme si stanovili, co naše aplikace bude umět. Podle toho si teď rozvrhneme datovou strukturu a vytvoříme modely.

1. Proxy

Data o počasí nám poskytne služba Počasí.cz přes svoje API rozhraní https://wapi.pocasi.seznam.cz. My ale na toto API rozhraní budeme přistupovat přes naši proxy. Vyhneme se tak problémům s CORS.

Proxy vytvoříme na stejném serveru, který se stará o výdej webové aplikace. Ve výchozím stavu je server připravený pouze pro jednu proxy. My jich však budeme potřebovat více. V souboru weather-app/server/server.js – funkce runNodeApp – najdeme řádek:

.use(environment.$Proxy.path + '/', proxy(environment.$Proxy.server, environment.$Proxy.options)

Vidíme, že server používá Express framework a pro proxy jeden z jeho doplňků express-http-proxy. Nastavení proxy se nachází v souboru weather-app/app/environment.js. Soubor obsahuje jednoduchý Node.js modul, který vrací objekt. Hlavními klíči objektu jsou prodtest a dev. Tyto klíče představují nastavení pro jednotlivé vývojové prostředí s tím, že všechny vycházejí z prod prostředí.

Poznámka: Tento styl konfigurace (prod – test – dev) si zapamatujte, neobjevuje se naposledy.

Naši proxy potřebujeme nastavit pouze v produkčním nastavení.

// app/environment.js

module.exports = (() => {
    return {
        prod: {
            // ...
            $Proxy: {
                path: '/api',   // na této URL bude proxy poslouchat
                server: 'https://wapi.pocasi.seznam.cz', // zde bude proxy přeposílat požadavky
                options: {
                    proxyReqPathResolver: function (req) {
                        const queryString = req.url.split('?')[1];

                        return '/v2/forecast' + (queryString ? '?' + queryString : '');
                    }
                }
            }
        }
        // ...
    }

2. Načítání dat o předpovědi počasí

V předchozím bodě jsme si nastavili proxy, která poslouchá na URL /api. Aby jsme URL neopakovali v aplikaci několikrát, přidáme ji do nastavení v souboru weather-app/app/config/settings.js. Zde se používá stejný styl konfigurace jako v environment.js.

// app/config/settings.js

export default (ns, oc, config) => {
  // ...
  return {
    prod: {
        // ...
        App: {
            api: config.$Protocol + '//' + config.$Host + '/api'
        }
    }
  }
}

V adresáři weather-app/app/model vytvoříme podadresář pro předpověď počasí – forecast. V tomto adresáři vytvoříme soubory  ForecastService.jsForecastResource.jsForecastFactory.js a ForecastEntity.js.

Začneme vytvořením ForecastResource. V aplikaci IMA.js funguje DI (Dependency Injection) skrz OC (Object Container). Více o OC a DI se dočtete v dokumentaci.

// app/model/forecast/ForecastResource.js
import { HttpAgent } from '@ima/core';

export default class ForecastResource {
	static get $dependencies() {
		return [HttpAgent, '$Settings.App.api']; // $Settings umožňuje vkládat nastavení pomocí DI
	}

	constructor(http, apiUrl) {
		this._http = http;
		this._api = apiUrl;
    }

    async getForecast(lat, lon) {
		const response = await this._http.get(
            this._api,
            { lat, lon, include: ['place', 'daily'] } // query parametry
        );

		return response.body;
	}
}

Následuje ForecastFactory. Prozatím bude obsahovat jen jednu metodu, která z předaných dat vytvoří instanci ForecastEntity.

// app/model/forecast/ForecastFactory.js
import ForecastEntity from './ForecastEntity';

export default class ForecastFactory {

    static get $dependencies() {
        return [];
    }

    createEntity(data) {
        return new ForecastEntity(data);
    }
}

ForecastEntity pouze vezme data z constructoru a vytvoří si z nich vlastní properties.

// app/model/forecast/ForecastEntity.js
export default class ForecastEntity {

    constructor(data) {
        this.place = data.place;

        this.daily = data.daily;

        Object.freeze(this);
    }
}

ForecastService bude obsahovat prozatím pouze jednu metodu getForecast. Ta pomocí ForecastResource načte data ze serveru a poté vytvoří instance ForecastEntity pomocí ForecastFactory.

// app/model/forecast/ForecastService.js
import ForecastResource from './ForecastResource';
import ForecastFactory from './ForecastFactory';

export default class ForecastService {
    static get $dependencies() {
        return [ForecastResource, ForecastFactory];
    }

    constructor(resource, factory) {
        this._resource = resource;
        this._factory = factory;
    }

    async getForecast(lat, lon) {
        const result = await this._resource.getForecast(lat, lon);

        return this._factory.createEntity(result);
    }

Vytvořili jsme také model pro geocoder – vyhledávání místa podle názvu z URL. Nebudeme zde ale rozepisovat kompletní postup, protože se v mnohém shoduje s modelem pro předpověď počasí. Kompletní podobu geocoder modelu najdete v kódu ukázkové aplikace.

Závěr

Po tomto díle byste měli mít nainstalovanou a funkční IMA.js aplikaci. Zároveň jsme si připravili datovou vrstvu (modely) pro další díl, ve kterém si ukážeme, jak data načítat a zobrazovat.

Komentáře

Subscribe
Upozornit na
guest
2 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Antonin Bouchal

Ahoj Vojto.

Býval jsem docela fanda Imy a myslím, že jsme se potkali vašem taky na workshopu o ní.

Nicméně jsem měl za to, že projekt byl mrtvý stejně jako Este. Z jednoduchého důvodu, že vyšel Next.js.

Mohl bys prosím shrnout, v čem nyní spočívá gro a hlavní důvod zvolit imu a ne next.js?

shemale01

jo, v Este jsem dělal, dělal jsem i v Next a musím uznat, že čistý React je lepší, přehlednější. Z mého pohledu ani Ima, ani Next nepřináší nic nového, resp. to co je v nich vyřešeno, není nic co bych nebyl schopen napsat. Nehledě na to, že osobně se mi architektura Nextu nelíbí. Next prošel docela bouřlivým vývojem, dost často se nám stávalo, že nová minor verze rozje**la projekt, přestal fungovat. Za sebe, Next povařuji za paskvil pro lidi, který jsou líní napsat pár řádek navíc. Jo Ima, kdyby vznikla, tak před 10 lety, ale teď je krapet zastarale, hlavně že se snaží do JS zavádět OOP a DI, které sem nepatří. Holt seznam…

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.

Pocta C64

Za prvopočátek své programátorské kariéry vděčím počítači Commodore 64. Tehdy jsem genialitu návrhu nemohl docenit. Dnes dokážu lehce nahlédnout pod pokličku. Chtěl bych se o to s vámi podělit a vzdát mu hold.