Zobrazují se příspěvky se štítkemPrettier. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemPrettier. Zobrazit všechny příspěvky

středa 23. května 2018

React aplikace od začátku do konce

V poslední době jsme byli nuceni napsat více React aplikací, které vždy vychází ze stejného základu. Díky tomu jsem si uvědomil, že i když můžeme jednoduše provést setup čistého projektu, přeci jen je několik částí, které je nutné doplnit vlastním kódem. To mě nakonec dovedlo k myšlence, že jsem vzal čistý list papíru (gitu) a napsal example projekt, který slouží jako základní dev stack.

A tak jsem vytvořil "Aldu"

DEMO: https://alda.app
Git repozitář: https://github.com/ApiTreeCZ/alda

Co je cílem tohoto projektu?


Je to hlavně demonstrace toho, jak lze jednoduše napsat React aplikaci, která má snad vše, co je třeba. Díky tomu je zde přesah i do dalších oblastí jako je třeba nasazení do Kubernetes v Cloudu, CI/CD, apod.

Proč vlastní řešení?


Hlavním důvodem je, že díky rychlé evoluci JavaScript technologií se často dostáváme do stavu, kdy aktualizace jedné knihovny zapříčiní problémy v celém systému. Proto je snaha, aby tento projekt používal co nejaktuálnější knihovny a neustále dokola opravoval problémy, které vznikají s novými verzemi. Ano, svět JavaScriptu má i odvrácenou temnou stranu a tou je "jepičí život" některých knihoven a verzí.

Dalším důvodem je to, co již bylo zmíněno na začátku. Tedy využití Aldy pro start nových projektů.

A nakonec to nejdůležitější a tím je, že když chci propojit několik technologií, tak je velice malá pravděpodobnost, že najdu kompletní řešení. Vždy musím někde napsat nějakou část kódu, která nás nutí k tomu, abychom se stále probírali různými možnostmi, jak to vlastně udělat.

Co ten systém umí?


Tak hlavně je to React a to stačí :) .... Teď važně.

Jedná se React (už zase :)) aplikaci napsanou pomocí TypeScriptu. Celý systém je napsán přes Next.js, tudíž automaticky se jedná o isomorfní aplikaci, která podporuje server side rendering. Díky tomu jí lze nasadit na veřený web a není důvod se bát kvůli SEO a indexování od vyhledávačů.

Abychom trochu dodrželi štábní kulturu, tak v projektu je implementován TSLint a Prettier. Tedy kontrola na zápis kódu a zároveň automatické formátování podle předepsaných pravidel. Statická analýza kódu je v JavaScript světě nutností.

Celý systém je postaven na knihovně material-ui, která před pár dny vyšla oficiálně ve verzi 1.0. Díky tomu jsou CSS psány pomocí JavaScriptu a nakonec generovány jako css třídy.

Dále obsahuje Redux, do kterého si ukládá globálně důležité stavy. Díky tomu je zde redux-form, což je knihovna pro formuláře.

Pro lokalizaci je zde použitá knihovna react-intl, díky které je možné jednoduše používat překlady a to nejen textové, ale i číselné a datumové. Součástí toho je zde napsán vlastní systém generování výchozího jazyka a mergování do ostatních. V praxi to znamená, že když mám třeba výchozí angličtinu a přidám další jazyk, tak texty, které jsem v novém jazyce ještě neimplementoval, budou automaticky v angličtině.

Pro komunikaci s backendem je zde GraphQL a to v implementaci přes Apollo (sorry, ale Relay není ta cesta). Současně s tím je zde i malý backend server, který je vlastním GraphQL serverem. Vedle toho jsou zde navíc použity knihovny, které umožňují samotné GraphQL schéma generovat do TypeScriptu a tím pádem máte zadarmo celý API model a to jak na straně frontendu tak i backendu.

Další částí, která zatím není implementována, ale bude co nejdříve, je přihlašování pomocí JWT tokenu. Tedy autentizace přes login a heslo a autoriace přes JWT token.

Poslední důležitou součástí je příprava pro psaní testů pomocí knihovny Jest. Vedle toho je navíc integrace se službou Coveralls, která na základě výsledků testů provádí analýzu a říká nám, na kolik procent je náš kód pokrytý testy.

Nasazení do Cloudu


Pokud jsem na začátku zmínil, že jsem vytvořil základní stack pro vývoj React aplikací, tak je to jen 50% toho, co jsem udělal. Druhou částí je samotný způsob, jak aplikace funguje z pohledu DevOps.

Pokud to zjednoduším, tak Alda funguje tak, že pokud udělám přes GitHub nový release, tak se automaticky vytvoří Docker image, který se nasadí v Google Cloudu do Kubernetes clusteru přes Helm. Pokud nasadím aplikaci na novou doménu, tak automaticky vytvoří SSL certifikát přes Lets Encrypt. Je prostě cool, když nakonec jedním příkazem nasadíte celý ekosystém, který je škálovatelný. Jediné omezení je pak Vaše peněženka, ze které si musíte zaplatit tolik serverů, kolik uznáte za vhodné.

Celý proces nasazení je popsán v definici pro CircleCI. Ano, Alda používá CircleCI, což je jeden z nejlepších nástrojů pro CI/CD současnosti.

Plány do budoucna?


Na to je jednoduchá odpověď a tím jsou GitHub issues: https://github.com/ApiTreeCZ/alda/issues.

Jedna z věcí, kterou je třeba provést je samotný refactoring. Více implementovat vzory jako třeba: "Higher-Order Components" apod.

Pokud byste něco nového chtěli přidat, neváhejte poslat požadavek :)

Závěr


Hlavním důvodem, proč jsem chtěl sepsat tento článek není ani tak to, že bych chtěl naše řešení nějak propagovat, ale spíše pomoci ostatním, který řeší podobné problémy jako my. Ať už se jedná třeba o spojení material-ui s Next.js či o nasazení do Kubernetes.

Někdy příště popíši blíže celý projekt z pohledu samotného vývoje.

neděle 18. března 2018

Jak psát stabilní kód v JavaScriptu?

Pokud se rozhodnete, že v JavaScriptu napíšete větší část kódu, tak narazíte na to, že bez podpůrných nástrojů se z této cesty může stát peklo. Existuje velké množství vývojářů, kteří Vám řeknou, že JavaScript je bastl a nedá se v něm smysluplně napsat nic jiného, než pár drobností na rozhýbání webu. Opak je pravdou. V současné době je JavaScript nejuniverzálnějším jazykem na světě.

Je vcelku jedno, zda v JavaScriptu píšete aplikace typu backend, web, mobil, desktop, příkazy pro konzoli či třeba cloud funkce. Stále byste se měli snažit o to, abyste svůj kód zapsali tím nejlepším možným způsobem.

JavaScript se za posledních několik let výrazně změnil. Dostali jsme se do stavu, kdy existují dvě skupiny programátorů.

První skupinou jsou ti, kteří ignorují nové ECMAScript specifikace a JavaScript zapisují "starým způsobem". Do této skupiny často spadají lidé, kteří potřebují občas rozhýbat určitou část webu a JavaScript chápají jako jazyk, který přímo vykoná webový prohlížeč. O této skupině vývojářů se dá říci, že vlastně neumí v současném JavaScriptu programovat.

Druhou skupinou jsou vývojáři, kteří umí využít věci jako je Node.js, Babel, Typescript, apod. Kód v JavaScriptu zapisují v nových ECMAScript specifikacích a fakticky jsou schopni z tohoto jazyka často vytěžit maximum. Jedná se o naprosto jiný svět, než je tomu v případě první skupiny.

Abych Vám toto předal trochu více exaktněji, podívejte se na následující příklad, který ilustruje rozdíl mezi první a druhou skupinou:
// prvni skupina
function oldWay(options) {
    return {
        name: options.name,
        hello: function () {
            return 'Hello ' + options.name;
        }
    }
}

// druha skupina
const newWay = ({name}) => ({name, hello: () => `Hello ${name}`});

console.log(oldWay({name: 'Old way'}).hello());
console.log(newWay({name: 'New way'}).hello());

Tento kód je založen na využití arrow functions, string interpolation a destructuring assignment. Věřte, že je to jen část vlastností, které nové ECMAScript specifikace nabízí. Teď ruku na srdce, pokud je zde čtenář té první skupiny, poznal by, že ten druhý zápis ve výsledku dělá tu samou věc? Na JavaScript se dá koukat jako na dva jazyky. Na jazyk před ECMAScript 6 a jazyk s ECMAScript 6 a vyšší.

Ale pojďme zpět. Jak zajistit to, abychom v JavaScriptu byli schopni psát stabilní kód, který se nám nerozsype s novou posilou v týmu či tím, že někdo bude psát "starým" a někdo "novým" způsobem?

Airbnb JavaScript Style Guide

První věcí, kterou by každý JavaScript programátor měl začít je, že si přečte a osvojí si style guide, tedy zápis JavaScript kódu. K tomtu účelu se výborně hodí následující příručka Airbnb JavaScript Style Guide.
Dokud si toto neosvojíte, těžko se můžete považovat za seniornějšího JavaScript programátora.

Typescript / Flow

Pokud to s JavaScriptem myslíte skutečně vážně, určitě byste se měli snažit o to, abyste tento jazyk obohatili o statickou typovou kontrolu. Jelikož je JavaScript dynamicky typovaný jazyk, tak v případě, že se Vám projekt v JavaScriptu rozšíří, tak bez typové kontroly je jakýkoli refactoring roven ruské ruletě. Osobně preferuji Typescript a důvody proč, jsem sepsal v článku Proč právě Typescript.

Typescript strict mode

Součástí Typescriptu je i možnost nastavení striktního módu. Toto nastavení se jmenuje přímo "strict". Co se díky tomutu módu vše zapne, najdete v manuálu: https://www.typescriptlang.org/docs/handbook/compiler-options.html

ESLint / TSLint

Další nezbytnou součástí je ESLint (v Typescriptu TSLint). Linting, nebo-li "lustrování" kódu slouží k tomu, aby Vám nadával za to, že jste kód nezapsali zrovna tím nejlepším způsobem. Například Vám řekne, že jste napsali function, místo toho, abyste použili arrow function, že jste string zapsali ve špatných uvozovkách, že jste překročili limit počtu znaků na řádku, apod.
I když možná budete tento linter na začátku nenávidět, tak věřte, že je to dočasné. Časem totiž poznáte, že je to velice dobrý sluha. Dá se říci, že Vás naučí správně zapisovat JavaScript kód.

Prettier

Dalším skvělým pomocníkem je Prettier. Tento nástroj slouží k tomu, že za Vás automaticky formátuje kód. K čemu je to vlastně dobré?
Osobně pracuji tak, že když píšu kód, tak automaticky stále spouštím dvě základní operace nad kódem: "Format code & Optimize imports". Dělám to tak už roky a jsem přesvědčen, že by toto měl dělat každý vývojář. Každý moderní vývojový nástroj (Atom, WebStorm, Visual Studio Code, apod) má tyto dvě operace k dispozici.
Ve chvíli, kdy pracuji na projektu, kde je více lidí, tak bez automatického formátu vzniká problém. Co dokáže naprosto otrávit je, když automaticky formátujete kód jen v editoru a najednou uděláte změny i tam, kde jste vůbec nepracovali. Git Vám poté hlásí, že poslední změnu na daném řádku jste udělali Vy a přitom to není vůbec pravda.
První variantou je, že všem vývojářům přikážete, že musí používat jedno IDE a jeden styl formátování. A věřte, to je to poslední, co chcete dělat. Ne každý chce třeba psát kód v IntelliJ IDEA. Proto zde máme Prettier. Nástroj, který za nás určí pravidla a vy se jim automaticky přizpůsobíte, ať už píšete v poznámkovém bloku či třeba v Atomu.
Druhou důležitou vlastností je to, že Prettier Vám formátuje kód tak, aby správně doplnil závorky, středníky, atd, podle jasně definovaného style guide.

Integrace TSLintu a Prettier s Gitem

Nyní se pojďme podívat na to, jak využít TSLint a Prettier při práci s Gitem. Berme v potaz, že již máte projekt v Gitu. Projekt je v Typescriptu a jedná se o React aplikaci.

Nejprve do projektu přídáme závislost na tslint a tslint-react:
npm i -D tslint tslint-react

Poté do projektu přidáme soubor tslint.json:
{
  "extends": [
    "tslint:recommended",
    "tslint-react"
  ],
  "rules": {
    "max-line-length": [
      false,
      160
    ],
    "semicolon": [
      true,
      "always",
      "ignore-bound-class-methods"
    ],
    "quotemark": [
      true,
      "single",
      "jsx-double"
    ],
    "member-ordering": [
      true,
      "variables-before-functions"
    ],
    "ordered-imports": false,
    "interface-name": false,
    "object-literal-key-quotes": [
      true,
      "as-needed"
    ],
    "object-literal-sort-keys": false,
    "no-object-literal-type-assertion": false,
    "no-empty-interface": false,
    "jsx-no-multiline-js": false,
    "jsx-boolean-value": false,
    "member-access": false
  }
}

Do package.json stačí přidat následující skript:
"scripts": {
    "tslint": "tslint -c tslint.json 'src/**/*'"
}

A poté spustit:
npm run tslint
Hlásí Vám tslint chybu? Pokud ano, tak nezbýbá, než ony chyby opravit :)

Nyní pojďme přidat prettier:
npm i -D husky prettier pretty-quick
Současně s knihovnou prettier nainstalujeme knihovnu husky, která slouží k tomu, že vytvoří git hook.

Dále v projektu vytvoříme soubor .prettierrc.json:
{
  "printWidth": 160,
  "tabWidth": 4,
  "parser": "typescript",
  "singleQuote": true,
  "bracketSpacing": false,
  "trailingComma": "all",
  "arrowParens": "always"
}

Jelikož použijeme pretty-quick pro provedení automatického formátování, je třeba definovat soubor .prettierignore, ve kterém určíme adresáře a soubory, které z automatického formátovaní chceme vynechat:
.circleci/
.next/
dist/
package.json
package-lock.json

Poté, co máme základní konfiguraci hotovou, nezbývá, než obohatit náš package.json:
"scripts": {
    "tslint": "tslint -c tslint.json 'src/**/*'",
    "precommit": "pretty-quick --staged && npm run tslint"
}
A nyní stačí zkusit provést commit do gitu :)

Toto řešení je postavené na tom, že používáte Git. Před tím, než se provede samotný commit do Gitu, tak se nejprve spustí formát kódu a poté se překontroluje pomocí TSLintu. Pokud máte něco špatně, commit se neprovede. Pokud Vám nevyhovuje precommit, můžete využít i možnost prepush, tedy před tím, než se provede push do remote git repozitáře. Nicméně výsledkem je, že se Vám do společného Git repozitáře vždy dostane pouze kód, který je spravné formátovaný a zkontrolovaný pomocí linteru.

Kromě Git hooku je určitě vhodné, abyste toto provedli ještě v CI. Tedy ve vašem nástroji na continuous integration. V našem případě se jedná o CircleCI, kde pouze spustíme samotný příkaz npm run tslint a tím zajistíme, že před nasazením na server nemáme v kódu něco špatně.

Závěr

Zajistit štábní kultruru v JavaScript projektech není složitá záležitost. Celé je to pouze o tom, že čím déle budete věci jako je TSLint či Prettier ignorovat, tím víc práce v budoucnu budete mít.
Také je dobré zmínit, že nelze nekriticky spoléhat na tyto nástroje. Stále je pouze na Vás, zda kód, který napíšete je nakonec funkční. Nejsou to nástroje, které Vás například zbaví nutnosti psát unit testy.
A co vy? Používáte některé ze zmíněných nástrojů?

Když programátor založí a řídí firmu

Jako malý jsem chtěl být popelářem. Ani ne tak proto, že bych měl nějaký zvláštní vztah k odpadkům, ale hrozně se mi líbilo, jak...