Ve prospěch mikro-frameworků Hyperapp # Kdo jsem * *Aleš Růžička* - @alesruzickaeu * Full stack vývojář (.Net) * Back-end je primární # Moje Front-end historie 1. jQuery + Silverlight (RIP 2015) 1. AngularJS (RIP 2016) 1. JavaScriptová únava # Protože > ES6, ES2016, Babel, TypeScript, JSX, > Node.js, NPM, > WebPack, Gulp, Grunt, > React, Redux, Angular, Vue.js, Ember, Mithril # Protože * Nic z toho jsem neznal * Nebylo známo, co zůstane * Jak se rozhodnout, co je pro mě # Co jsem chtěl - moderní framework * Schopnost přidat to existující multi-page aplikace * Jednoduché, deklarativní API * Stav jako zdroj pravdy * JavaScript především * Dodávaný s baterkama # Co jsem nechtěl * Transpilovat * 200kB+ JavaScriptu navíc * Učit se, co zítra bude pasé * Zvlášní licence (React) Hyperapp to the rescue # Proč? - Protože 1. Má, co jsem chtěl 1. Nemá, co jsem nechtěl 1. A zvládne to na 403 řádách kódu včetně prázných - *2kB* ``` !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(e.hyperapp={})}(this,function(e){"use strict";e.h=function(e,n){for(var t=[],r=[],o=arguments.length;o-- >2;)t.push(arguments[o]);for(;t.length;){var u=t.pop();if(u&&u.pop)for(o=u.length;o--;)t.push(u[o]);else null!=u&&!0!==u&&!1!==u&&r.push(u)}return"function"==typeof e?e(n||{},r):{nodeName:e,attributes:n||{},children:r,key:n&&n.key}},e.app=function(e,n,t,r){var o,u=[].map,i=r&&r.children[0]||null,l=i&&function e(n){return{nodeName:n.nodeName.toLowerCase(),attributes:{},children:u.call(n.childNodes,function(n){return 3===n.nodeType?n.nodeValue:e(n)})}}(i),f=[],a=!0,c=p(e),s=function e(n,t,r){for(var o in r)"function"==typeof r[o]?function(e,o){r[e]=function(e){var u=o(e);return"function"==typeof u&&(u=u(y(n,c),r)),u&&u!==(t=y(n,c))&&!u.then&&h(c=m(n,p(t,u),c)),u}}(o,r[o]):e(n.concat(o),t[o]=p(t[o]),r[o]=p(r[o]));return r}([],c,p(n));return h(),s;function d(e){return"function"==typeof e?d(e(c,s)):null!=e?e:""}function v(){o=!o;var e=d(t);for(r&&!o&&(i=function e(n,t,r,o,u){if(o===r);else if(null==r||r.nodeName!==o.nodeName){var i=function e(n,t){var r="string"==typeof n||"number"==typeof n?document.createTextNode(n):(t=t||"svg"===n.nodeName)?document.createElementNS("http://www.w3.org/2000/svg",n.nodeName):document.createElement(n.nodeName),o=n.attributes;if(o){o.oncreate&&f.push(function(){o.oncreate(r)});for(var u=0;u<n.children.length;u++)r.appendChild(e(n.children[u]=d(n.children[u]),t));for(var i in o)b(r,i,o[i],null,t)}return r}(o,u);n.insertBefore(i,t),null!=r&&k(n,t,r),t=i}else if(null==r.nodeName)t.nodeValue=o;else{!function(e,n,t,r){for(var o in p(n,t))t[o]!==("value"===o||"checked"===o?e[o]:n[o])&&b(e,o,t[o],n[o],r);var u=a?t.oncreate:t.onupdate;u&&f.push(function(){u(e,n)})}(t,r.attributes,o.attributes,u=u||"svg"===o.nodeName);for(var l={},c={},s=[],v=r.children,h=o.children,m=0;m<v.length;m++){s[m]=t.childNodes[m];var y=g(v[m]);null!=y&&(l[y]=[s[m],v[m]])}for(var m=0,N=0;N<h.length;){var y=g(v[m]),w=g(h[N]=d(h[N]));if(c[y])m++;else if(null==w||a)null==y&&(e(t,s[m],v[m],h[N],u),N++),m++;else{var x=l[w]||[];y===w?(e(t,x[0],x[1],h[N],u),m++):x[0]?e(t,t.insertBefore(x[0],s[m]),x[1],h[N],u):e(t,s[m],null,h[N],u),c[w]=h[N],N++}}for(;m<v.length;)null==g(v[m])&&k(t,s[m],v[m]),m++;for(var m in l)c[m]||k(t,l[m][0],l[m][1])}return t}(r,i,l,l=e)),a=!1;f.length;)f.pop()()}function h(){o||(o=!0,setTimeout(v))}function p(e,n){var t={};for(var r in e)t[r]=e[r];for(var r in n)t[r]=n[r];return t}function m(e,n,t){var r={};return e.length?(r[e[0]]=e.length>1?m(e.slice(1),n,t[e[0]]):n,p(t,r)):n}function y(e,n){for(var t=0;t<e.length;)n=n[e[t++]];return n}function g(e){return e?e.key:null}function N(e){return e.currentTarget.events[e.type](e)}function b(e,n,t,r,o){if("key"===n);else if("style"===n)for(var u in p(r,t)){var i=null==t||null==t[u]?"":t[u];"-"===u[0]?e[n].setProperty(u,i):e[n][u]=i}else"o"===n[0]&&"n"===n[1]?(n=n.slice(2),e.events?r||(r=e.events[n]):e.events={},e.events[n]=t,t?r||e.addEventListener(n,N):e.removeEventListener(n,N)):n in e&&"list"!==n&&!o?e[n]=null==t?"":t:null!=t&&!1!==t&&e.setAttribute(n,t),null!=t&&!1!==t||e.removeAttribute(n)}function k(e,n,t){function r(){e.removeChild(function e(n,t){var r=t.attributes;if(r){for(var o=0;o<t.children.length;o++)e(n.childNodes[o],t.children[o]);r.ondestroy&&r.ondestroy(n)}return n}(n,t))}var o=t.attributes&&t.attributes.onremove;o?o(n,r):r()}}}); ``` <img src="hyperapplogo.png" style="height:25vh;"> # Apka 1/5 - import ``` const { h, app } = hyperapp ``` # Apka 2/5 - stav ``` const state = { count: 0 } ``` # Apka 3/5 - akce ``` const actions = { up: value => state => ({ count: state.count + value }) } ``` # Apka 4/5 - view ``` const view = (state, actions) => ( h('button', { onclick: () => actions.up(1) }, state.count) ) ``` # Apka 5/5 - spustit ``` app(state, actions, view, document.body) ``` # Nečekané výhody * Pochopil jsem, jak podobné frameworky fungují * Primitivní router jsem napsal na 30 řádek * Dostatečný i pro malou SPA PWA * 3 670 řádek Další podobné případy # LiteDB - *345 kB* * NoSQL databáze * Serverless, single-user * Užití 1. Ukládání kolik kávy denně vypiji 1. Ukládání velkých dat ve workflow systému # Doporučení nakonec [Writing Less Damned Code – Heydon Pickering – btconfBER2016](https://youtu.be/tzfHlEFd2Fk) Děkuji