$30 off During Our Annual Pro Sale. View Details »

Case study: Optimalizace výkonu dApp

Case study: Optimalizace výkonu dApp

Aleš Roubíček
PRO

June 06, 2019
Tweet

More Decks by Aleš Roubíček

Other Decks in Programming

Transcript

  1. Case Study
    Optimalizace výkonu dApp
    @alesroubicek
    #TopMonksCaffe

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. 1. analýza
    • Hlavní úzké hrdlo - Drizzle
    • Kód v žalostném stavu
    • nedodržování pravidel zanesených do linteru
    • nedodržování návrhových vzorů
    • tuna mrtvého a zakomentovaného kódu
    • absence smysluplných testů
    • Spousta chyb a upozornění v konzoli

    View Slide

  6. –Aleš Roubíček
    “The state for rendering of the game should be
    separated from the actual state of the contracts,
    this will allow more asynchronous state
    propagation to rendering pipeline and improved
    timing when actual data will be shown.”

    View Slide

  7. Architektonické nedostatky
    • Render blocking operace v hlavním vlákně
    • Nedodržování vzorů vyžadovaných knihovnami
    • Stav managující komponenty ve view stromu
    • Inicializace stavových komponent s každým view
    • Blockchain state & view state coupling
    • Generátor zbytečného boilerplate

    View Slide

  8. Aplikační stav
    • React, Redux, Web3.js, Drizzle, Pixi.js
    • function view(data) {}
    • Single Atom Application State

    View Slide

  9. Původní strom v Reactu






    View Slide

  10. Vysekání Drizzle z Reactu











    View Slide

  11. Redux & Sagas
    • Úplná extrace komunikace s web3 z lifecycle metod
    komponent do redux-saga
    • Maximální snaha o PureComponents
    • Kompletní eliminace Drizzle stavu a komponent z React
    stromu čistě do Redux Store
    • Reakce na změny v blockchainu pouze přes akce/sagas
    • Masivní očista kódu dle ESlint pravidel a pomocí Prettier

    View Slide

  12. View Slide

  13. 2. analýza
    • Příliš velké moduly kódu
    • Přibalování přirozeně statických assetů
    • Přibalování zbytečných závislostí
    • Render blocking resources v HTML (fonty, scripty)
    • Absence pre-renderu a preloading

    View Slide

  14. Velikost bundle
    • Webpack Bundle Analyzer 

    https://github.com/webpack-contrib/webpack-bundle-analyzer

    View Slide

  15. View Slide

  16. View Slide

  17. /*
    Local
    */
    // import SomeToken from '../../../ontracts/build/contracts/SomeToken.json';
    // import OtherToken from '../../../contracts/build/contracts/OtherToken.json';
    // import FooToken from '../../../contracts/build/contracts/FooToken.json';
    // import BarToken from '../../../contracts/build/contracts/BarToken.json';
    /*
    Ropsten
    */
    import SomeToken from './contracts/SomeToken.json';
    import OtherToken from './contracts/OtherToken.json';
    import FooToken from './contracts/FooToken.json';
    import BarToken from './contracts/BarToken.json';
    const contracts = {
    SomeToken,
    OtherToken,
    FooToken,
    BarToken,
    };
    export function getContract() {
    return contracts;
    }

    View Slide

  18. function contractUrl(contract) {
    const network = process.env['NETWORK'];
    const version = process.env['CONTRACTS_VERSION'];
    const isDev = process.env['NODE_ENV'] !== 'production';
    const prefix = isDev
    ? `/${network}/contracts/`
    : `https://prod.test.com/${network}/contracts/${version}/`;
    return [prefix, contract, '.json'].join('');
    }
    const fetchContract = c \> fetch(contractUrl(c)).then(r \> r.json());
    const contracts = ['SomeToken', 'OtherToken', 'FooToken', 'BarToken'];
    export function getContract() {
    return Promise.all(contracts.map(fetchContract)).then(
    ([SomeToken, OtherToken, FooToken, BarToken]) \> ({
    SomeToken,
    OtherToken,
    FooToken,
    BarToken,
    }),
    );
    }

    View Slide

  19. View Slide

  20. package.json
    {
    "resolutions": {
    "bn.js": “4.11.8",
    }
    }

    View Slide

  21. View Slide

  22. webpack.js
    {
    test: /\.(jpg|png|gif)$/,
    use: [
    { loader: "file-loader" }
    ]
    }

    View Slide

  23. Načítání assetů
    • On-page optimalizace
    • preloading
    • async/defer
    • CDN optimalizace
    • Cachovací hlavičky

    View Slide

  24. Přednačítání assetů



    href="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js">
    href="https://fonts.gstatic.com/s/vt323/v10/pxiKyp0ihIEF2isfFJXUdVNF.woff2">

    View Slide

  25. Asychronní fonty
    <br/>WebFontConfig = {<br/>google: {<br/>families: [<br/>'Space Mono:400,700',<br/>'Work Sans:400,600',<br/>'VT323',<br/>],<br/>},<br/>};<br/>
    src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js">

    View Slide

  26. script async defer

    View Slide

  27. CDN cache boosting
    'use strict';
    exports.handler = (event, context, callback) ;> {
    const response = event.Records[0].cf.response;
    const headers = response.headers;
    headers['Cache-Control'.toLowerCase()] = [{
    key: 'Cache-Control',
    value: "public, max-age=31536000, immutable"
    }];
    callback(null, response);
    };

    View Slide