Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

7. díl - Nasazení na server

JavaScript 3D webová hra Nasazení na server

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulém díle jsem ukazoval výrobu user interface pro hru. V tomto posledním díle ukáži nasazovaní celého projektu na server.

Nasazování na server

První polovinu tutoriálu jsem vyráběl statické JavaScriptové soubory. Ty se dají lehce nakopírovat na server např. pomocí FTP. Nevýhodou tohoto postupu je, že po každé změně musím aktualizované soubory překopírovat ručně. V průběhu kopírování nastává doba, kdy jsou na serveru smíchané soubory ze staré a nové verze. A pokud kopírování selže, může se produkční verze rozbít úplně.

Potom jsem ukázal, jaké jsou nevýhody čistého JavaScriptu a přešel jsem na TypeScript. Teď už nemohu soubory překopírovat přímo. Mohu si ale nechat vytvořit transpilovaný JavaScriptový soubor a dále postupovat úplně stejně:

npm build

To, co se mi vytvoří do složky build, nakopíruju na server.

Tento postup je OK, pokud budu aktualizovat aplikaci několikrát ročně, navštěvuje ji málo lidí a není potřebná příliš velká spolehlivost. Pokud bych chtěl aktualizovat častěji např. každý den či týden, bylo by dobré celý postup automatizovat.

Continuous integration

Mnoho hostingů má podporu continuous integration. To je proces, který převede zdrojové kódy aplikace na stav, kdy je nová verze nasazená pro uživatele. Pokud máš vlastní (nebo virtuální) server můžeš si nainstalovat některý z continuous integration nástrojů. Jedním z nich je např. Strider.

Impulzem pro nasazení nové verze může být tlačítko v administrace, příkaz v konzoli nebo nový commit v git repozitáři (obvykle ve větvi production). Potom se spustí několik kroků:

  1. Vytvoří se nějaké oddělené místo (např. nová složka) pro novou verzi aplikace.
  2. Do tohoto místa se naklonuje git repozitář na commitu, který má být nasazen.
  3. Spustí se npm install. To nainstaluje všechny závyslosti, které máme nastavené v package.json.
  4. Spustí se npm build. To vytvoří ze zdrojových souborů a nainstalovaných závyslostí jeden produkční JavaScriptový soubor.
  5. Spustí se testy. (Popíšu dále v článku.)
  6. Spustí se samotná aplikace. Zde si liší jednoduché hostingy (např. GitHub Pages), které prostě přes https odesílají vytvořené produkční soubory a opravdové node.js hostingy (např. Heroku), které spustí přednastavený node.js skript.
  7. Stará verze se přepne se za novou.

My použijeme výše zmíněné GitHub Pages. Nejdříve nainstalujeme nástroj, který umí s GitHub Pages pracovat:

npm install gh-pages --dev

Do package.json přidáme url hry na GitHub pages pod hodnotu homepage (ta je ve formátu https://[uživa­tel].github.i­o/[projekt]/). A do scripts přidáme predeploy a deploy.

{
  "name": "web-game",
  "homepage": "https://hejny.github.io/web-game/",
  "dependencies": {
    //...
  },
  "devDependencies": {
    "gh-pages": "^1.0.0",
    //...
  },
  "scripts": {
    //...
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  }
}

Nyní stačí v administraci GitHubu nastavit GitHub Pages na větev "gh-pages".

Testy

Pokud commitnu něco chybného, proces continuous integration zachová původní verzi a mě pouze upozorní. Tím se vyhnu nasazení vadné verze pro uživatele či znefunkčnění celé webové stránky. Existuje několik nejběžnějších druhů chyb:

  • Chybu v syntaxi (např. chybějící závorku) odhalí TypeScript transpilátor.
  • Chybu v typování odhalí TypeScript transpilátor. Pokud bychom nepoužívali TypeScript, tento druh chyb by se projevil až za běhu, což by mohlo mít mnohem horší následky.
  • Chyba za běhu (např. komponenta vyhodí chybu při rendrování).
  • Logická chyba (např. akce změní stav aplikace tak, jak jsme neočekávali).

Chyby v syntaxi a typování jsou otravné, odhalí se ale ještě před nasazením programu na produkci. Logické chyby a chyby za běhu se odhalují mnohem hůře. Mít chybu v běžící aplikaci je nepříjemné a často velmi drahé. Proto se píší automatizované testy, které odhalují chyby ještě před nasazením aplikace pro uživatele. Jak správně psát testy je velmi složitá disciplína. Já pro hru napíši několik jednoduchých testů:

components.test.ts

import * as React from "react";
import * as ReactDOM from "react-dom";
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import * as injectTapEventPlugin from 'react-tap-event-plugin';
import {createStore} from 'redux';
import { Provider } from 'react-redux';
import {stateReducer} from '../redux-reducers/index';
import Root from "../react-components/root";
import Heading from "../react-components/heading";
import BlockColor from "../react-components/block-color";
injectTapEventPlugin();

const store = createStore(stateReducer, {});

it('Root renders without crashing', () => {
    const div = document.createElement('div');
    ReactDOM.render(
        <Provider store={store}>
            <MuiThemeProvider>
                <Root/>
            </MuiThemeProvider>
        </Provider>
        , div);
});

it('Heading renders without crashing', () => {
    const div = document.createElement('div');
    ReactDOM.render(
        <Provider store={store}>
            <MuiThemeProvider>
                <Heading/>
            </MuiThemeProvider>
        </Provider>
        , div);
});

it('BlockColor renders without crashing', () => {
    const div = document.createElement('div');
    ReactDOM.render(
        <Provider store={store}>
            <MuiThemeProvider>
                <BlockColor/>
            </MuiThemeProvider>
        </Provider>
        , div);
});

state.test.ts

import {createStore} from 'redux';
import {stateReducer} from '../redux-reducers/index';

const store = createStore(stateReducer, {});

describe('blocks', () => {

    it('should increase number of blocks after dispatch BLOCK_ADD', () => {
        const oldState = store.getState();
        store.dispatch({type:'BLOCK_ADD',newBlock:{}});
        const newState = store.getState();
        expect(newState.blocks.length).toBe(oldState.blocks.length+1);
    });

    it('should descrease number of blocks after dispatch BLOCK_DELETE', () => {
        const oldState = store.getState();
        store.dispatch({type:'BLOCK_DELETE',blockId:oldState.blocks[0].id});
        const newState = store.getState();
        expect(newState.blocks.length).toBe(oldState.blocks.length-1);
    });

});

describe('ui', () => {

    it('should toggle drawer after dispatch UI_DRAWER_TOGGLE', () => {
        const oldState = store.getState();
        store.dispatch({type:'UI_DRAWER_TOGGLE'});
        const newState = store.getState();
        expect(newState.ui.drawer).toBe(!oldState.ui.drawer);
    });

    it('should change color after dispatch UI_COLOR_SET', () => {
        store.dispatch({type:'UI_COLOR_SET',value:'#123456'});
        const newState = store.getState();
        expect(newState.ui.color).toBe('#123456');
    });

});

Dokončenou hru si můžeš stáhnout pod článkem, nebo jít do Git repozitáře, kde najdeš nejnovější verzi zdrojových kódů. Nebo si ji rovnou můžeš vyzkoušet na hejny.github.io/web-game.


 

Stáhnout

Staženo 2x (9.89 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Pavol Hejný
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje vývoji mnoha www aplikací - http://pavolhejny.cz/
Miniatura
Předchozí článek
Uživatelské rozhraní
Miniatura
Všechny články v sekci
Vytvoř si vlastní 3D webovou hru
Aktivity (1)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!