├── .gitignore ├── 2015-03-amsjs ├── 01-relative-paths │ ├── index.js │ └── package.json ├── 02-node_modules │ ├── index.js │ └── package.json ├── 03-local-modules │ ├── index.js │ └── package.json ├── 04-namespaces │ ├── index.js │ └── package.json ├── 05-linklocal │ ├── index.js │ └── package.json ├── README.md ├── outline.md ├── proposal.md └── resources.md ├── 2015-03-jsmvc ├── README.md ├── outline.md ├── proposal.md └── resources.md ├── 2015-05-frontend-developer-meetup ├── README.md ├── notes.md ├── outline.md ├── research.md └── slides.md ├── 2015-10-melb-nodejs └── README.md ├── 2015-10-nodeninjas └── README.md ├── 2015-10-sydjs └── README.md ├── 2015-11-campjs-vi ├── 1_hihat.js ├── 2_db.js ├── 2_servers.js ├── 3_graphics.js ├── 5_networking.js ├── 6_hyperscript.js ├── 7_baudio.js ├── README.md ├── gl.png ├── index.frag ├── index.vert ├── linux │ ├── hostname │ ├── id_rsa │ ├── id_rsa.pub │ ├── linux.pid │ ├── stderr.log │ └── stdout.log ├── package.json ├── packages.md └── proposal.md ├── 2015-11-nodeninjas ├── 1.js ├── 2.js ├── 3.js ├── 4.js ├── 5.js ├── 6.js ├── README.md ├── package.json ├── proposal.md └── start.sh ├── 2015-11-sydjs ├── 1.js ├── 2.js ├── 3.js ├── 4.js ├── README.md ├── proposal.md └── start.sh ├── 2016-02-melb-nodejs ├── 01_http.js ├── 02_worker.js ├── README.md └── package.json ├── 2016-02-melbjs └── README.md ├── 2016-03-melbcss ├── README.md ├── demo-1.js ├── demo-2.js ├── demo-3.css ├── demo-3.js ├── package.json └── proposal.md ├── 2016-04-pivotal-labs └── README.md ├── 2016-05-nodeconf-london ├── README.md └── proposal.md ├── 2016-05-nodeschool-tokyo └── README.md ├── 2016-06-nodeconf-oslo ├── README.md ├── demo │ ├── client.js │ ├── package.json │ ├── schema.proto │ └── server.js ├── outline.md └── proposal.md ├── 2016-07-react-hamburg └── README.md ├── 2016-07-remote-meetup ├── README.md └── index.js ├── 2016-08-cascadiafest └── proposal.md ├── 2016-09-node-interactive-eu ├── 01_vanilla.js ├── 02_css.js ├── README.md ├── dist │ ├── bundle.css │ ├── bundle.js │ └── index.html ├── package.json └── proposal.md ├── 2016-09-nodejs-berlin ├── README.md └── proposal.md ├── 2016-10-nodeconf-eu ├── README.md └── notes.md ├── 2016-10-upfront ├── README.md └── proposal.md ├── 2016-11-dapphack ├── README.md ├── dat.css ├── dist │ ├── bundle.css │ ├── bundle.js │ └── index.html ├── in.js ├── index.js ├── out.js ├── package.json ├── proposal.md ├── slider.js └── whatever │ └── .dat │ ├── 000072.ldb │ ├── 000073.ldb │ ├── 000074.log │ ├── 000075.ldb │ ├── 000076.ldb │ ├── 000077.ldb │ ├── CURRENT │ ├── LOCK │ ├── LOG │ └── MANIFEST-000002 ├── 2016-11-nodefest-jp └── proposal.md ├── 2016-12-holyjs ├── README.md └── proposal.md ├── 2016-12-jsconf-au └── proposal.md ├── 2017-01-nodeconf-bp ├── README.md └── proposal.md ├── 2017-05-jsconf-eu ├── README.md └── proposal.md ├── 2017-05-jsday-it ├── README.md └── proposal.md ├── 2017-06-fluent ├── README.md └── proposal.md ├── 2020-rust-latam.md ├── 2020-rustlab.md ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /2015-03-amsjs/01-relative-paths/index.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const koa = require('koa') 3 | const server = koa() 4 | 5 | const port = 1337 6 | 7 | server.use(function *() { 8 | this.body = 'Hello World' 9 | }) 10 | 11 | server.listen(port, summary) 12 | -------------------------------------------------------------------------------- /2015-03-amsjs/01-relative-paths/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01-relative-paths", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^0.18.1", 13 | "server-summary": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2015-03-amsjs/02-node_modules/index.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const koa = require('koa') 3 | const server = koa() 4 | 5 | const port = 1337 6 | 7 | server.use(function *() { 8 | this.body = 'Hello World' 9 | }) 10 | 11 | server.listen(port, summary) 12 | -------------------------------------------------------------------------------- /2015-03-amsjs/02-node_modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-node_modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^0.18.1", 13 | "server-summary": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2015-03-amsjs/03-local-modules/index.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const koa = require('koa') 3 | const server = koa() 4 | 5 | const port = 1337 6 | 7 | server.use(function *() { 8 | this.body = 'Hello World' 9 | }) 10 | 11 | server.listen(port, summary) 12 | -------------------------------------------------------------------------------- /2015-03-amsjs/03-local-modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "03-local-modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^0.18.1", 13 | "server-summary": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2015-03-amsjs/04-namespaces/index.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const koa = require('koa') 3 | const server = koa() 4 | 5 | const port = 1337 6 | 7 | server.use(function *() { 8 | this.body = 'Hello World' 9 | }) 10 | 11 | server.listen(port, summary) 12 | -------------------------------------------------------------------------------- /2015-03-amsjs/04-namespaces/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "04-namespaces", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^0.18.1", 13 | "server-summary": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2015-03-amsjs/05-linklocal/index.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const koa = require('koa') 3 | const server = koa() 4 | 5 | const port = 1337 6 | 7 | server.use(function *() { 8 | this.body = 'Hello World' 9 | }) 10 | 11 | server.listen(port, summary) 12 | -------------------------------------------------------------------------------- /2015-03-amsjs/05-linklocal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "05-linklocal", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^0.18.1", 13 | "server-summary": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /2015-03-amsjs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │ 4 | │ NPM, local modules │███ 5 | │ & you │███ 6 | │ │███ 7 | │ Yoshua Wuyts │███ 8 | │ 2015-03-05 │███ 9 | │ │███ 10 | └─────────────────────────┘███ 11 | ███████████████████████████ 12 | ███████████████████████████ 13 | ``` 14 | --- 15 | # hello, I'm yoshua 16 | 17 | - writes a lot of JS 18 | - for wercker 19 | - and Open Source 20 | 21 | --- 22 | # unix 23 | 24 | - been around since the 1970's 25 | - holy scriptures of programming 26 | 27 | --- 28 | # node architecture 29 | 30 | ## Relative paths 31 | 32 | [demo 01] 33 | 34 | --- 35 | # node architecture 36 | 37 | ## Relative paths 38 | 39 | ✔ modular code 40 | ✔ live updates 41 | ✖ loose coupling 42 | ✖ easy extraction to npm 43 | ✖ modularized dependencies 44 | ✖ flat directory structure 45 | ✔ explicitly local 46 | 47 | --- 48 | # node architecture 49 | 50 | ## node_modules 51 | 52 | [demo 02] 53 | 54 | --- 55 | # node architecture 56 | 57 | ## node_modules 58 | 59 | ✔ modular code 60 | ✔ live updates 61 | ✔ loose coupling 62 | ✔ easy extraction to npm 63 | ✔ scoped dependencies 64 | ✖ flat directory structure 65 | ✖ explicitly local 66 | 67 | --- 68 | # node architecture 69 | 70 | ## namespaces 71 | 72 | [demo 03] 73 | 74 | --- 75 | # node architecture 76 | 77 | ## namespaces 78 | 79 | ✔ modular code 80 | ✔ live updates 81 | ✔ loose coupling 82 | ✔ easy extraction to npm 83 | ✔ modularized dependencies 84 | ✖ flat directory structure 85 | ✔ explicitly local 86 | 87 | ---- 88 | # node architecture 89 | 90 | ## local modules 91 | 92 | [demo 04] 93 | 94 | --- 95 | # node architecture 96 | 97 | ## local modules 98 | 99 | ✔ modular code 100 | ✖ live updates 101 | ✔ loose coupling 102 | ✔ easy extraction to npm 103 | ✔ modularized dependencies 104 | ✔ flat directory structure 105 | ✔ explicitly local 106 | 107 | --- 108 | # node architecture 109 | 110 | ## linklocal 111 | 112 | [demo 05] 113 | 114 | --- 115 | # node architecture 116 | 117 | ## linklocal 118 | 119 | ✔ modular code 120 | ✔ live updates 121 | ✔ loose coupling 122 | ✔ easy extraction to npm 123 | ✔ modularized dependencies 124 | ✔ flat directory structure 125 | ✔ explicitly local 126 | 127 | ---- 128 | ``` 129 | ┌─────────────────────────┐ 130 | │ │ 131 | │ Wercker is hiring! │███ 132 | │ │███ 133 | │ werck │███ 134 | │ @wercker.com │███ 135 | │ │███ 136 | └─────────────────────────┘███ 137 | ███████████████████████████ 138 | ███████████████████████████ 139 | ``` 140 | 141 | --- 142 | ``` 143 | ┌────────────────────────────┐ 144 | │ NODESCHOOL AMSTERDAM │ 145 | │ presents │███ 146 | │ │███ 147 | │ │███ 148 | │ INTERNATIONAL DAY 2015 │███ 149 | │ May 23rd │███ 150 | └────────────────────────────┘███ 151 | ██████████████████████████████ 152 | ██████████████████████████████ 153 | ``` 154 | --- 155 | # Thank you! 156 | 157 | github: yoshuawuyts 158 | twitter: @yoshuawuyts 159 | 160 | Or offline where the beer is. 161 | -------------------------------------------------------------------------------- /2015-03-amsjs/outline.md: -------------------------------------------------------------------------------- 1 | - Welcome 2 | 3 | - whoami 4 | 5 | - Talk about unix principles 6 | - tell people what they are (commandments of programming) 7 | - explain a bit about abstractions and interfaces 8 | 9 | - Talk about architecture anno now 10 | - example of paths (../../../) 11 | - example of `node_modules` (and errors with tooling) 12 | 13 | - Show example of requiring a file 14 | - Solves problems of deeply nested paths 15 | - Solves problem of inflexible code & hard refactors 16 | - Might want to do an example with the file tree in there 17 | 18 | - Show example of namespaces 19 | - Solves problem of ambiguous names 20 | - Compatible with npm namespaces 21 | 22 | - Show example of symlinks 23 | - Solves problem of development 24 | 25 | - Show example of flat directory structure 26 | - Neatly defined dependencies 27 | - Easy to break out functionality 28 | - Easy to open source 29 | - Amount of modules shouldn't matter 30 | - Just gradually grind up abstractions 31 | - And keep on releasing modules 32 | 33 | - Notes 34 | - Works for both frontend & backend 35 | - Integrates with private registry / tar store 36 | - Start with a monolith, but plan ahead 37 | 38 | - Links 39 | 40 | - Thank you 41 | - Nodeschool May 23rd 42 | - Check out wercker to see what we're building 43 | - Many a thanks 44 | -------------------------------------------------------------------------------- /2015-03-amsjs/proposal.md: -------------------------------------------------------------------------------- 1 | In this talk Yoshua will take you into the brave new world of NPM 2's local modules and show (some very practical) methods on how to structure applications following the unix philosophy. 2 | 3 | For organizers only: 4 | ================== 5 | The goal is to give people some practical information on how to use npm 2.0, linklocal (https://github.com/timoxley/linklocal), npm scoped modules and project structuring. So far information about local modules is scarcely available, and both Nodesource and wercker haven't published any articles about linklocal yet so it'll probably be new information for everyone in the audience. Thanks! 6 | -------------------------------------------------------------------------------- /2015-03-amsjs/resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | - [amsjs](http://www.meetup.com/AmsterdamJS/events/220509732/) 3 | -------------------------------------------------------------------------------- /2015-03-jsmvc/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │ 4 | │ Modular clients │███ 5 | │ with NPM! │███ 6 | │ │███ 7 | │ Yoshua Wuyts │███ 8 | │ 2015-03-24 │███ 9 | │ │███ 10 | └─────────────────────────┘███ 11 | ███████████████████████████ 12 | ███████████████████████████ 13 | ``` 14 | --- 15 | # hello, I'm yoshua 16 | - writes a lot of JS 17 | - for wercker 18 | - and Open Source 19 | 20 | --- 21 | # Why modules? 22 | - small 23 | - composable 24 | - no compromises 25 | 26 | --- 27 | # NPM scripts 28 | - npm {pre,post,re,}start 29 | - npm run `` 30 | - npm {pre,post,}test 31 | 32 | --- 33 | # NPM scripts 34 | [demo] 35 | 36 | --- 37 | # Components 38 | - virtual-dom 39 | - deku 40 | - polyfill-webcomponents 41 | 42 | --- 43 | # Loading data from the server 44 | - request 45 | - jsonist 46 | - simple-store 47 | 48 | --- 49 | # Routing 50 | - wayfarer 51 | - hash-match 52 | - pathname-match 53 | 54 | --- 55 | ``` 56 | ┌─────────────────────────┐ 57 | │ │ 58 | │ Wercker is hiring! │███ 59 | │ │███ 60 | │ werck │███ 61 | │ @wercker.com │███ 62 | │ │███ 63 | └─────────────────────────┘███ 64 | ███████████████████████████ 65 | ███████████████████████████ 66 | ``` 67 | 68 | --- 69 | # Thank you! 70 | - github: yoshuawuyts 71 | - twitter: @yoshuawuyts 72 | 73 | Or offline, fast asleep. 74 | 75 | --- 76 | # Links 77 | - [slides] https://github.com/yoshuawuyts/talks 78 | - [npm docs] https://docs.npmjs.com/misc/scripts 79 | -------------------------------------------------------------------------------- /2015-03-jsmvc/outline.md: -------------------------------------------------------------------------------- 1 | - Welcome 2 | 3 | - whoami 4 | 5 | - Why modules 6 | - Build-your-own-framework 7 | 8 | - Neato patterns you can use 9 | - npm run 10 | - npm start 11 | - npm prebuild 12 | 13 | - Neato modules you can use 14 | - browserify 15 | - babel - ES6 16 | - wzrd - quick demo's 17 | - wayfarer - router 18 | - virtual-dom 19 | 20 | - tools of the trade (npm, browserify, commonjs) 21 | - talk about unix principles and why it's a good idea to use small things 22 | - discoverability (show off npm search?, list stuff?) 23 | - show a bunch of cool stuff 24 | - es6 + browserify 25 | - wzrd 26 | - glslify 27 | - some mvc router stuffs ? 28 | - deku + es6 template strings vs react 29 | - webcomponent polyfills 30 | 31 | - talk about a bunch of things 32 | -------------------------------------------------------------------------------- /2015-03-jsmvc/proposal.md: -------------------------------------------------------------------------------- 1 | # Modular clients with npm! 2 | In this talk Yoshua will take you on a journey that will make you want to 3 | unshackle yourself from frameworks and venture into the wonderful realm of modular 4 | client programming. 5 | -------------------------------------------------------------------------------- /2015-03-jsmvc/resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | - [Jake Verbaten: NPM-style Frontend [JSConf2014]](https://www.youtube.com/watch?v=8w0_Xw7PPFQ) 3 | - [Event page](http://www.meetup.com/JavaScript-MVC-Meetup-Amsterdam/events/217298402/) 4 | -------------------------------------------------------------------------------- /2015-05-frontend-developer-meetup/README.md: -------------------------------------------------------------------------------- 1 | # unbundling the frontend 2 | 3 | Yoshua Wuyts 4 | 5 | http://yoshuawuyts.com 6 | https://{github,twitter}.com/yoshuawuyts 7 | https://npmjs.org/~yoshuawuyts 8 | 9 | ``` 10 | $ npm install -g tslide 11 | $ tslide slides.md 12 | ``` 13 | 14 | Frontend Developer Meetup Ams May 2015 15 | 16 | --- 17 | 18 | # unix philosophy 19 | 20 | ``` 21 | 'Make each program do one thing well.' 22 | ``` 23 | --- 24 | 25 | # unix philosophy 26 | 27 | ``` 28 | 'Make each program do one thing well.' 29 | + 'To do a new job, build afresh rather than complicate' 30 | + 'old programs by adding new features.' 31 | ``` 32 | 33 | --- 34 | 35 | # unix philosophy 36 | 37 | - modularity - write simple parts connected by clean interfaces 38 | - composition - design programs to be connected with other programs 39 | - parsimony - write a big program only as a last resort 40 | - separation - split the engine from the interface 41 | 42 | --- 43 | 44 | # custom elements 45 | 46 | ``` 47 | Create your own HTML tags and elements 48 | ``` 49 | 50 | --- 51 | 52 | # custom elements 53 | 54 | register a custom element: 55 | 56 | ``` js 57 | document.registerElement('custom-button', { 58 | prototype: Object.create(window.HTMLButtonElement.prototype), 59 | extends: 'button' 60 | }) 61 | ``` 62 | 63 | --- 64 | 65 | # custom elements 66 | 67 | render a custom element: 68 | 69 | ``` js 70 | document.createElement('custom-button') 71 | document.createElement('button', 'custom-button') 72 | ``` 73 | 74 | --- 75 | 76 | # custom elements 77 | 78 | render a custom element from html: 79 | 80 | ``` html 81 | foobar 82 | 83 | ``` 84 | 85 | --- 86 | 87 | # custom elements 88 | 89 | lifecycle hooks: 90 | 91 | ``` 92 | .createdCallback() // after element was created 93 | .attachedCallback() // after element was attached to DOM 94 | .detachedCallback() // after element was detached from dom 95 | .attributeChangedCallback() // on element attribute change 96 | ``` 97 | 98 | --- 99 | 100 | # virtual-dom 101 | 102 | ``` 103 | All the benefits of React with none of the cruft 104 | ``` 105 | 106 | --- 107 | 108 | # virtual-dom 109 | 110 | performant elements: 111 | 112 | ``` js 113 | const createElement = require('virtual-dom/create-element') 114 | const h = require('virtual-dom/h') 115 | 116 | const tree = h('div', 'pumpkin pie') 117 | const el = createElement(tree) 118 | document.body.appendChild(el) 119 | ``` 120 | 121 | --- 122 | 123 | # virtual-dom 124 | 125 | performant & pretty elements: 126 | 127 | ``` js 128 | const createElement = require('virtual-dom/create-element') 129 | const vhtml = require('virtual-html') 130 | 131 | const tree = vhtml('
pumpkin pie
') 132 | const el = createElement(tree) 133 | document.body.appendChild(el) 134 | ``` 135 | 136 | --- 137 | 138 | # virtual-dom 139 | 140 | render loop: 141 | 142 | ``` js 143 | setInterval(() => { 144 | var newTree = render(count) 145 | var patches = diff(tree, newTree) 146 | rootNode = patch(rootNode, patches) 147 | tree = newTree 148 | }, 1000) 149 | ``` 150 | 151 | --- 152 | 153 | # base-element 154 | 155 | api: 156 | 157 | ``` js 158 | el = baseElement(targetNode) // create new base element 159 | el.on(event, cb) // event handler 160 | el.html(tag, opts, value) // create virtual-hyperscript nodes 161 | el.toString(data) // render nodes as html 162 | ``` 163 | 164 | --- 165 | 166 | # base-element 167 | 168 | static element: 169 | 170 | ``` js 171 | const createElement = require('base-element') 172 | const vhtml = require('virtual-html') 173 | 174 | const el = createElement(document.body) 175 | el.render(() => el.html(vhtml(``))) 176 | ``` 177 | 178 | --- 179 | 180 | # base-element 181 | 182 | event: 183 | 184 | ``` js 185 | const createElement = require('base-element') 186 | const vhtml = require('virtual-html') 187 | 188 | const el = createElement(document.body) 189 | el.render(() => { 190 | const html = el.html(vhtml(``)) 191 | html.on('click', () => { 192 | window.alert(e.target.innerText + ' button was clicked') 193 | }) 194 | return html 195 | }) 196 | ``` 197 | 198 | --- 199 | 200 | # base-element 201 | 202 | server side rendering: 203 | 204 | ``` js 205 | const createElement = require('base-element') 206 | const vhtml = require('virtual-html') 207 | 208 | const el = createElement(document.body) 209 | el.render(text => el.html(vhtml(``))) 210 | 211 | el.toString('SOUND THE ALARM') 212 | // => '' 213 | ``` 214 | 215 | --- 216 | 217 | # base-element 218 | 219 | with custom elements: 220 | 221 | ``` js 222 | const createCustom = require('custom-element') 223 | const createElement = require('base-element') 224 | const vhtml = require('virtual-html') 225 | 226 | const custom = createCustom() 227 | custom.on('created', () => { 228 | const el = createElement(custom) 229 | el.render(text => el.html(vhtml(``))) 230 | }) 231 | ``` 232 | 233 | --- 234 | 235 | # css-modules 236 | 237 | ``` 238 | Every selector has the potential to have unintended side effects 239 | by targeting unwanted elements or clashing with other selectors. 240 | ``` 241 | 242 | --- 243 | 244 | # css-modules 245 | 246 | explicit exports: 247 | 248 | ``` css 249 | .foo { 250 | font-size: 2rem; 251 | } 252 | 253 | /* exported globally */ 254 | :global .foo { 255 | color: green; 256 | } 257 | ``` 258 | 259 | --- 260 | 261 | # css-modules 262 | 263 | module usage: 264 | 265 | ``` js 266 | import styles from './styles.css' 267 | 268 | el.innerHTML = ` 269 |
wombat
270 | ` 271 | ``` 272 | 273 | --- 274 | 275 | # css-modules 276 | 277 | resulting html: 278 | 279 | ``` css 280 |
wombat
281 | ``` 282 | 283 | --- 284 | 285 | # data fetching 286 | 287 | - relay? 288 | - graphql? 289 | - window.fetch? 290 | 291 | --- 292 | 293 | # learn more 294 | 295 | - https://github.com/shama/base-element 296 | - https://github.com/Matt-Esch/virtual-dom 297 | - https://github.com/Raynos/main-loop 298 | 299 | --- 300 | 301 | # learn more 302 | 303 | - https://github.com/css-modules/css-modules 304 | - http://webcomponents.org/articles/interview-with-joshua-peek/ 305 | - https://github.com/yoshuawuyts/knowledge/blob/master/modules.md#dom 306 | 307 | --- 308 | 309 | # thanks 310 | 311 | ``` js 312 | const el = document.createElement('span') 313 | el.textContent = 'thank you!' 314 | document.body.appendChild(el) 315 | ``` 316 | 317 | --- 318 | 319 | # thanks 320 | 321 | ``` html 322 | thank you! 323 | ``` 324 | -------------------------------------------------------------------------------- /2015-05-frontend-developer-meetup/notes.md: -------------------------------------------------------------------------------- 1 | # proposal 2 | Previous talks included: 3 | - local modules 4 | - neat modules for the client 5 | 6 | Feel like talking about something related, but different this time. Breaking 7 | stuff apart is very important, and the client is missing a uniform way of doing 8 | this. Talking about killing frameworks is controversial; how else would one 9 | structure applications right? *cough* 10 | 11 | What we're going to talk about here is how we can stop repeating ourselves 12 | every time the next big thing pops up. Lock in is holding us back, common 13 | interfaces are the way forward. 14 | 15 | ## Unbundling the frontend 16 | The great unbundling is upon us! Backend engineers talk microservices, but us 17 | on the frontend are building mostly monoliths. How can we unbundle our clients 18 | without repeating ourselves? How can we prepare our code to be compatible with 19 | The Next Big Framework? (And the one after that?) Let me show you a glimpse of 20 | the future. 21 | 22 | ## See Also 23 | - [substack/jsdc.tw-2014](https://raw.githubusercontent.com/substack/jsdc.tw-2014/master/readme.markdown) - used format + unix slides 24 | -------------------------------------------------------------------------------- /2015-05-frontend-developer-meetup/outline.md: -------------------------------------------------------------------------------- 1 | # main 2 | 3 | > How can we unbundle client-side elements to stop repeating ourselves. 4 | 5 | - Framework specific components create a lot of duplication and unnecessarily 6 | add a learning curve to components. 7 | - Standards aim to solve this (e.g. webcomponents) but they don't tackle the 8 | deeper problems of reusability. 9 | - Also: standards don't solve all problems yet (scene graph api, anyone?) 10 | - The solution is to decouple implemntation from framework. 11 | 12 | # describe problem 13 | - there is a lot of repetition in inventions 14 | - framework-specific elements are created time after time 15 | - interface is confounded with core functionality 16 | - which leads to repetition (everyone maintains their own core) 17 | - and framework lock-in 18 | 19 | --- 20 | 21 | # describe current (broken) solutions 22 | - frameworks encourage this behavior 23 | - by bundling standard components in (routers, viewcomponents) 24 | - not splitting up their elements for reusability (virtual-dom) 25 | - not using the ecosystem of elements (assert) 26 | - or providing abstractions that require buy-in (jsx) 27 | 28 | - webcomponents solve all problems right? 29 | - webcomponents solve shit, they're just a different framework 30 | - but at least a framework we can agree on 31 | - up until then we need to solve it differently 32 | - standards are missing; common ground between components (scene graph) is 33 | lacking 34 | 35 | --- 36 | 37 | # describe how decoupling elements are the solution to this 38 | 39 | > So now then, how do we decouple our elements? / which elements do we decouple? 40 | 41 | - decoupled router vs framework-specific routers (backbone, react-router) 42 | - decoupled data vs integrated data 43 | - decoupled elements vs integrated elements (base-element is the future) 44 | 45 | # sections 46 | - unix philosophy 47 | - custom elements (next big thing) 48 | - virtual-dom (neato) 49 | - base-element 50 | - css-modules 51 | -------------------------------------------------------------------------------- /2015-05-frontend-developer-meetup/research.md: -------------------------------------------------------------------------------- 1 | # anatomy of a modular client 2 | This talk is to introduce people to the idea of a modular, event driven 3 | portable client. 4 | 5 | ## isomorphicism -> portability 6 | - parity 7 | - does not mean render client === render server 8 | - reuse components, not glue code 9 | 10 | ## server 11 | - well defined interfaces 12 | - .on for events 13 | - also: what elements are events? 14 | - signalling 15 | - show wayfarer 16 | - show simple-store 17 | - .pipe for streams 18 | - just data over time 19 | - everything that mutates should be a stream 20 | - heck, even stateful components can be streams 21 | 22 | ## architecture 23 | - event driven 24 | - one-way data flows 25 | - basically streams 26 | - wrapped up in browserify (see also: isomorphic) 27 | 28 | ## tools 29 | - provide encapsulation 30 | - web components allow hooking elements into logic 31 | 32 | ## anatomy of a component 33 | - base-element as a module 34 | - component-specific wrappers 35 | - possible default to webcomponents since it's a standard 36 | - expose internals so wrappers are possible 37 | - mention custom-element 38 | 39 | #mk2 40 | ## uniform components 41 | - button 42 | - list 43 | - form 44 | 45 | ## build on top of these abstractions 46 | - infinite scrolling 47 | - button with several states 48 | - dom events 49 | - xhr submission 50 | 51 | ## work towards specific use cases 52 | - twitter feed 53 | - facebook like button 54 | - login form for your new startup? 55 | 56 | ## wrapped for any framework you want 57 | - webcomponents 58 | - react 59 | - ember 60 | 61 | ## tools 62 | - npm = isomorphic code = portable code 63 | - base element that renders both server + client 64 | - shared-abstractions-as-a-module: lowest common denominator 65 | 66 | ## find the correct abstractions 67 | At fabrique I heard people were looking for stuff that did touch events well. 68 | How do you handle that? What's the correct way of listening to keybindings and 69 | firing events based on that? 70 | 71 | Oh, and don't forget to shit on react router for being everything that is wrong 72 | with client side code. 73 | 74 | # describe why frameworks are used - so that we know why we're talking about 75 | - frameworks are used so that people have a common set of expectations 76 | - frameworks focus very much on the interface of things (lifecycles, methods, etc) 77 | - frameworks provide a common interface for elements to communicate 78 | - following that reasoning web components are a framework 79 | - ~ bash is a framework 80 | - ~ node's `require()` is a framework 81 | - but that's not bad 82 | -------------------------------------------------------------------------------- /2015-05-frontend-developer-meetup/slides.md: -------------------------------------------------------------------------------- 1 | # unbundling the frontend 2 | 3 | Yoshua Wuyts 4 | 5 | http://yoshuawuyts.com 6 | https://{github,twitter}.com/yoshuawuyts 7 | https://npmjs.org/~yoshuawuyts 8 | 9 | ``` 10 | $ npm install -g tslide 11 | $ tslide README.md 12 | ``` 13 | 14 | Frontend Developer Meetup Ams May 2015 15 | 16 | --- 17 | 18 | # unix philosophy 19 | 20 | ``` 21 | 'Make each program do one thing well.' 22 | ``` 23 | --- 24 | 25 | # unix philosophy 26 | 27 | ``` 28 | 'Make each program do one thing well.' 29 | + 'To do a new job, build afresh rather than complicate' 30 | + 'old programs by adding new features.' 31 | ``` 32 | 33 | --- 34 | 35 | # unix philosophy 36 | 37 | - modularity - write simple parts connected by clean interfaces 38 | - composition - design programs to be connected with other programs 39 | - parsimony - write a big program only as a last resort 40 | - separation - split the engine from the interface 41 | 42 | --- 43 | 44 | # custom elements 45 | 46 | ``` 47 | Create your own HTML tags and elements 48 | ``` 49 | 50 | --- 51 | 52 | # custom elements 53 | 54 | register a custom element: 55 | 56 | ``` js 57 | document.registerElement('custom-button', { 58 | prototype: Object.create(window.HTMLButtonElement.prototype), 59 | extends: 'button' 60 | }) 61 | ``` 62 | 63 | --- 64 | 65 | # custom elements 66 | 67 | render a custom element: 68 | 69 | ``` js 70 | document.createElement('custom-button') 71 | document.createElement('button', 'custom-button') 72 | ``` 73 | 74 | --- 75 | 76 | # custom elements 77 | 78 | render a custom element from html: 79 | 80 | ``` html 81 | foobar 82 | 83 | ``` 84 | 85 | --- 86 | 87 | # custom elements 88 | 89 | lifecycle hooks: 90 | 91 | ``` js 92 | .createdCallback() // after element was created 93 | .attachedCallback() // after element was attached to DOM 94 | .detachedCallback() // after element was detached from dom 95 | .attributeChangedCallback() // on element attribute change 96 | ``` 97 | 98 | --- 99 | 100 | # virtual-dom 101 | 102 | ``` 103 | All the benefits of React with none of the cruft 104 | ``` 105 | 106 | --- 107 | 108 | # virtual-dom 109 | 110 | performant elements: 111 | 112 | ``` js 113 | const createElement = require('virtual-dom/create-element') 114 | const h = require('virtual-dom/h') 115 | 116 | const tree = h('div', 'pumpkin pie') 117 | const el = createElement(tree) 118 | document.body.appendChild(el) 119 | ``` 120 | 121 | --- 122 | 123 | # virtual-dom 124 | 125 | performant & pretty elements: 126 | 127 | ``` js 128 | const createElement = require('virtual-dom/create-element') 129 | const vhtml = require('virtual-html') 130 | 131 | const tree = vhtml('
pumpkin pie
') 132 | const el = createElement(tree) 133 | document.body.appendChild(el) 134 | ``` 135 | 136 | --- 137 | 138 | # virtual-dom 139 | 140 | render loop: 141 | 142 | ``` js 143 | setInterval(() => { 144 | var newTree = render(count) 145 | var patches = diff(tree, newTree) 146 | rootNode = patch(rootNode, patches) 147 | tree = newTree 148 | }, 1000) 149 | ``` 150 | 151 | --- 152 | 153 | # base-element 154 | 155 | api: 156 | 157 | ``` js 158 | el = baseElement(targetNode) // create new base element 159 | el.on(event, cb) // event handler 160 | el.html(tag, opts, value) // create virtual-hyperscript nodes 161 | el.toString(data) // render nodes as html 162 | ``` 163 | 164 | --- 165 | 166 | # base-element 167 | 168 | static element: 169 | 170 | ``` js 171 | const createElement = require('base-element') 172 | const vhtml = require('virtual-html') 173 | 174 | const el = createElement(document.body) 175 | el.render(() => el.html(vhtml(``))) 176 | ``` 177 | 178 | --- 179 | 180 | # base-element 181 | 182 | event: 183 | 184 | ``` js 185 | const createElement = require('base-element') 186 | const vhtml = require('virtual-html') 187 | 188 | const el = createElement(document.body) 189 | el.render(() => { 190 | const html = el.html(vhtml(``)) 191 | html.on('click', () => { 192 | window.alert(e.target.innerText + ' button was clicked') 193 | }) 194 | return html 195 | }) 196 | ``` 197 | 198 | --- 199 | 200 | # base-element 201 | 202 | server side rendering: 203 | 204 | ``` js 205 | const createElement = require('base-element') 206 | const vhtml = require('virtual-html') 207 | 208 | const el = createElement(document.body) 209 | el.render(text => el.html(vhtml(``))) 210 | 211 | el.toString('SOUND THE ALARM') 212 | // => '' 213 | ``` 214 | 215 | --- 216 | 217 | # base-element 218 | 219 | with custom elements: 220 | 221 | ``` js 222 | const createCustom = require('custom-element') 223 | const createElement = require('base-element') 224 | const vhtml = require('virtual-html') 225 | 226 | const custom = createCustom() 227 | custom.on('created', () => { 228 | const el = createElement(custom) 229 | el.render(text => el.html(vhtml(``))) 230 | }) 231 | ``` 232 | 233 | --- 234 | 235 | # css-modules 236 | 237 | ``` 238 | Every selector has the potential to have unintended side effects 239 | by targeting unwanted elements or clashing with other selectors. 240 | ``` 241 | 242 | --- 243 | 244 | # css-modules 245 | 246 | explicit exports: 247 | 248 | ``` css 249 | .foo { 250 | font-size: 2rem; 251 | } 252 | 253 | /* exported globally */ 254 | :global .foo { 255 | color: green; 256 | } 257 | ``` 258 | 259 | --- 260 | 261 | # css-modules 262 | 263 | module usage: 264 | 265 | ``` js 266 | import styles from './styles.css' 267 | 268 | el.innerHTML = ` 269 |
wombat
270 | ` 271 | ``` 272 | 273 | --- 274 | 275 | # css-modules 276 | 277 | resulting html: 278 | 279 | ``` css 280 |
wombat
281 | ``` 282 | 283 | --- 284 | 285 | # data fetching 286 | 287 | - relay? 288 | - graphql? 289 | - window.fetch? 290 | 291 | --- 292 | 293 | # learn more 294 | 295 | - https://github.com/shama/base-element 296 | - https://github.com/Matt-Esch/virtual-dom 297 | - https://github.com/Raynos/main-loop 298 | 299 | --- 300 | 301 | # learn more 302 | 303 | - https://github.com/css-modules/css-modules 304 | - http://webcomponents.org/articles/interview-with-joshua-peek/ 305 | - https://github.com/yoshuawuyts/knowledge/blob/master/modules.md#dom 306 | 307 | --- 308 | 309 | # thanks 310 | 311 | ``` js 312 | const el = document.createElement('span') 313 | el.textContent = 'thank you!' 314 | document.body.appendChild(el) 315 | ``` 316 | 317 | --- 318 | 319 | # thanks 320 | 321 | ``` html 322 | thank you! 323 | ``` 324 | -------------------------------------------------------------------------------- /2015-10-melb-nodejs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ pipe, emit, │██ 5 | │ stream, listen │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2015-10-22 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | 16 | ## Hello, I'm Yosh 17 | - interfaces 18 | - unix 19 | - node 20 | - consulting 21 | 22 | --- 23 | 24 | ## How to learn streams? 25 | - star all of @mafintosh's modules 26 | - write an article on how to use streams 27 | - write a bunch of stream modules 28 | - include streams training in consulting offer 29 | - give a talk on streams 30 | 31 | --- 32 | 33 | ## Streams in 20 mins 34 | - why streams? 35 | - how do streams work? 36 | - modules 37 | - cool things 38 | 39 | --- 40 | 41 | ## Why streams? 42 | - _extremely_ fast 43 | - composable 44 | - clear purpose 45 | - neat syntax 46 | - based on events (observables!) 47 | 48 | --- 49 | 50 | ## Basics 51 | Streams originate from the unix shell 52 | ```sh 53 | $ cat ./my-file > ./other-file 54 | ``` 55 | ```js 56 | const fs = require('fs') 57 | 58 | fs.createReadStream('./my-file') 59 | .pipe(fs.createWriteStream('./other-file')) 60 | ``` 61 | 62 | --- 63 | 64 | ## Basics 65 | 4 types of streams 66 | - read: data can be read from 67 | - write: data can be written to 68 | - duplex: data can be read from and written to 69 | - transform: data can be written to, 70 | transformed and then read from 71 | 72 | --- 73 | 74 | ## Basics 75 | 2 stream modes 76 | - default: operate on buffers and strings 77 | - objectMode: operate on anything 78 | 79 | --- 80 | 81 | ## Basics 82 | buffers! 83 | - binary data (octet) 84 | - allocated on the heap 85 | - different garbage collection 86 | - performant 87 | 88 | --- 89 | 90 | ## Basics 91 | Streams use events under the hood 92 | ```js 93 | const stream = require('readable-stream') 94 | 95 | // primitive .pipe() 96 | const stream1 = new stream.PassThrough() 97 | const stream2 = new stream.PassThrough() 98 | 99 | stream1.on('readable', () => { 100 | stream1.on('data', (data) => stream2.write(data)) 101 | stream1.on('end', () => stream2.end()) 102 | }) 103 | ``` 104 | 105 | --- 106 | 107 | ## Basics 108 | Read -> transform -> write 109 | ```sh 110 | $ cat ./my-file | grep 'foo' 111 | ``` 112 | ```js 113 | const through = require('through2') 114 | const fs = require('fs') 115 | 116 | const rs = fs.createReadStream('./my-file') 117 | const ts = grep(/foo/) 118 | const ws = process.stdout 119 | rs.pipe(ts).pipe(ws) 120 | 121 | function grep (regex) { 122 | return through((chunk, enc, cb) => { 123 | if (regex.test(String(chunk)) this.push(chunk) 124 | cb() 125 | }) 126 | } 127 | ``` 128 | 129 | --- 130 | 131 | ## Async 132 | Deferred streams (performant promise alternative) 133 | ```js 134 | const stream = require('stream') 135 | const fs = require('fs') 136 | 137 | function myAsyncFn () { 138 | const pts = new stream.PassThrough() 139 | 140 | process.nextTick(function () { 141 | const rs = fs.createReadStream('foobar.jpg') 142 | rs.pipe(pts) 143 | }) 144 | 145 | return pts 146 | } 147 | ``` 148 | 149 | --- 150 | 151 | ## Modules 152 | Event handling is cumbersome, modules make it better 153 | ```js 154 | // lets do a simple file copy 155 | const fs = require('fs') 156 | 157 | const rs = fs.createReadStream('./original.txt') 158 | const ws = fs.createWriteStream('./copy.txt') 159 | 160 | // use pump instead of rs.pipe(ws) 161 | pump(rs, ws, function (err) { 162 | if (err) return console.error('Copy error!', err) 163 | console.log('Copied successfully') 164 | }) 165 | ``` 166 | 167 | --- 168 | 169 | ## Modules 170 | HTTP servers! Write a file to the client 171 | ```js 172 | const http = require('http') 173 | const fs = require('fs') 174 | 175 | http.createServer((req, res) => { 176 | res.setHeader('Content-Type', 'text/css') 177 | fs.createReadStream('./my-css').pipe(res) 178 | }).listen() 179 | ``` 180 | 181 | --- 182 | 183 | ## Modules 184 | Databases! Scan a full db on each request 185 | ```js 186 | const level = require('level') 187 | const http = require('http') 188 | 189 | const db = level('/tmp/demo-db') 190 | 191 | http.createServer((req, res) => { 192 | db.createReadStream().pipe(res) 193 | }).listen() 194 | ``` 195 | 196 | --- 197 | 198 | ## Modules 199 | HTML templates! 200 | ```js 201 | const hyperstream = require('hyperstream') 202 | const http = require('http') 203 | 204 | http.createServer((req, res) => { 205 | const rs = fs.createReadStream('./index.html') 206 | const ts = hyperstream({ 207 | body: { _append: '

Hello World

' } 208 | }) 209 | rs.pipe(ts).pipe(res) 210 | }).listen() 211 | ``` 212 | 213 | --- 214 | 215 | ## Modules 216 | Torrents! 217 | ```js 218 | const torrentStream = require('torrent-stream') 219 | const path = require('path') 220 | const fs = require('fs') 221 | 222 | const engine = torrentStream('magnet:my-magnet-link') 223 | 224 | engine.on('ready', () => engine.files.forEach(file => { 225 | const outFile = path.join(__dirname, file.name) 226 | const rs = file.createReadStream() 227 | const ws = fs.createWriteStream(outFile) 228 | rs.pipe(ws) 229 | })) 230 | ``` 231 | 232 | --- 233 | 234 | ## Modules 235 | And much much more! 236 | - tar-stream (zip / tar) 237 | - ssejson (server sent events) 238 | - pbs (protocol buffers) 239 | - response-stream (http) 240 | - tape (tests) 241 | - airswarm (local mesh networking) 242 | 243 | --- 244 | 245 | ## Recap 246 | - 4 types of streams 247 | - communicate using events 248 | - everything-as-a-stream 249 | - userland makes streams nice 250 | - there's a (stream) package for that 251 | 252 | --- 253 | 254 | ## Thank.pipe(you)! 255 | - twitter.com/yoshuawuyts 256 | - github.com/yoshuawuyts 257 | 258 | Slides available on 259 | - https://github.com/yoshuawuyts/talks/2015-10-pipe-stream-emit-listen 260 | - npm i -g tslide to view the slides 261 | -------------------------------------------------------------------------------- /2015-10-nodeninjas/README.md: -------------------------------------------------------------------------------- 1 | # Node.js ninjas lightning talk: 5 modules in 5 minutes 2 | 3 | Yoshua Wuyts 4 | 5 | http://yoshuawuyts.com 6 | https://{github,twitter}.com/yoshuawuyts 7 | https://npmjs.org/~yoshuawuyts 8 | 9 | ``` 10 | $ npm install -g tslide 11 | $ tslide README.md 12 | ``` 13 | 14 | --- 15 | 16 | - [wsnc](https://github.com/substack/wsnc) 17 | - [bloomrun](https://github.com/mcollina/bloomrun) 18 | - [noderify](https://github.com/dominictarr/noderify) 19 | - [psy](https://github.com/substack/psy) 20 | - [garnish](https://github.com/mattdesl/garnish) 21 | 22 | --- 23 | 24 | # thanks 25 | 26 | ✨✨✨✨ 27 | -------------------------------------------------------------------------------- /2015-10-sydjs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ What is node? │██ 5 | │ │██ 6 | │ Yoshua Wuyts │██ 7 | │ James Richardson │██ 8 | │ 2015-10-28 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | 16 | ## Node.js in 5 17 | 18 | - What is this Node thing? 19 | - What are packages? 20 | - Cool things 21 | 22 | --- 23 | 24 | ## What is Node? 25 | 26 | - JS without a browser! 27 | - Super tiny core library 28 | - Filesystem 29 | - Network glue 30 | 31 | --- 32 | 33 | ## What is Node? 34 | 35 | Good old JavaScript 36 | ```js 37 | console.log('hello world!') 38 | // => 'hello world' 39 | ``` 40 | 41 | --- 42 | 43 | ## What is Node? 44 | 45 | Access to the filesystem: 46 | 47 | ```sh 48 | $ cat ./README.md 49 | ``` 50 | 51 | --- 52 | 53 | ## What is Node? 54 | 55 | Access to the filesystem: 56 | 57 | ```js 58 | const fs = require('fs') 59 | fs.createReadStream('./README.md') 60 | .pipe(process.stdout) 61 | ``` 62 | 63 | --- 64 | 65 | ## What is Node? 66 | 67 | With network support: 68 | 69 | ```sh 70 | $ curl google.com 71 | ``` 72 | 73 | --- 74 | 75 | ## What is Node? 76 | 77 | Requesting files from a server: 78 | 79 | ```js 80 | const http = require('http') 81 | http.get('http://google.com', res => { 82 | res.pipe(process.stdout) 83 | }) 84 | ``` 85 | 86 | --- 87 | 88 | ## What is Node? 89 | 90 | Or serving files: 91 | 92 | ```js 93 | const http = require('http') 94 | http.createServer((req, res) => { 95 | res.end('hello world!') 96 | }).listen(8080) 97 | ``` 98 | 99 | --- 100 | 101 | ## What is Node? 102 | 103 | Tiny, but complete stdlib: 104 | 105 | - crypto 106 | - cluster 107 | - dgram (UDP) 108 | - readline 109 | 110 | --- 111 | 112 | ## What are packages? 113 | 114 | Packages are tiny snippets of code 115 | that you can install for free. 116 | 117 | --- 118 | 119 | ## What are packages? 120 | 121 | ```sh 122 | $ npm install noop2 123 | ``` 124 | 125 | --- 126 | 127 | ## What are packages? 128 | 129 | ```js 130 | const noop = require('noop2') 131 | noop() 132 | // ... it was not very effective 133 | ``` 134 | 135 | --- 136 | 137 | ## Or something more interesting 138 | 139 | ```js 140 | const level = require('level') 141 | const http = require('http') 142 | 143 | const db = level('/tmp/demo-db') 144 | 145 | http.createServer((req, res) => { 146 | db.createReadStream().pipe(res) 147 | }).listen() 148 | ``` 149 | 150 | --- 151 | 152 | ## Recap 153 | 154 | - node is super tiny 155 | - let's you access filesystem, network 156 | - there's a module for that™ 157 | 158 | --- 159 | 160 | ## Thank you! 161 | 162 | Come to the meetup next Thursday! 163 | 164 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/1_hihat.js: -------------------------------------------------------------------------------- 1 | const toBuffer = require('electron-canvas-to-buffer') 2 | 3 | const canvas = document.createElement('canvas') 4 | const context = canvas.getContext('2d') 5 | const width = canvas.width 6 | const height = canvas.height 7 | 8 | const gradient = context.createLinearGradient(0, 0, width, 0) 9 | gradient.addColorStop(0, '#f39821') 10 | gradient.addColorStop(1, '#f321b0') 11 | 12 | context.fillStyle = gradient 13 | context.fillRect(0, 0, width, height) 14 | 15 | process.stdout.write(toBuffer(canvas, 'image/png')) 16 | window.close() 17 | 18 | // hihat render.js --node --exec > image.png 19 | // says --voice=daniel 'bond, james bond' 20 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/2_db.js: -------------------------------------------------------------------------------- 1 | const level = require('level') 2 | 3 | const db = level('/var/tmp/campdb') 4 | 5 | db.put('foo', 'bar', function (err) { 6 | if (err) throw err 7 | console.log('done') 8 | }) 9 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/2_servers.js: -------------------------------------------------------------------------------- 1 | const json = require('JSONStream') 2 | const level = require('level') 3 | const http = require('http') 4 | 5 | const db = level('/var/tmp/campdb') 6 | 7 | const server = http.createServer(function (req, res) { 8 | db.createReadStream() 9 | .pipe(json.stringify()) 10 | .pipe(res) 11 | }) 12 | 13 | server.listen(8080, function () { 14 | console.log('listening on port 8080') 15 | }) 16 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/3_graphics.js: -------------------------------------------------------------------------------- 1 | const gl = require('gl')(512, 512, { preserveDrawingBuffer: true }) 2 | const triangle = require('a-big-triangle') 3 | const save = require('save-pixels') 4 | const Shader = require('gl-shader') 5 | const ndarray = require('ndarray') 6 | const fs = require('fs') 7 | 8 | const pixels = new Uint8Array(512 * 512 * 4) 9 | const frag = fs.readFileSync('index.frag', 'utf8') 10 | const vert = fs.readFileSync('index.vert', 'utf8') 11 | const shader = Shader(gl, vert, frag) 12 | 13 | shader.bind() 14 | shader.uniforms.iResolution = [512, 512] 15 | shader.uniforms.iGlobalTime = 0 16 | triangle(gl) 17 | 18 | gl.readPixels(0, 0, 512, 512, gl.RGBA, gl.UNSIGNED_BYTE, pixels) 19 | 20 | save(ndarray(pixels, [512, 512, 4]).transpose(1, 0, 2).step(-1, -1), 'png') 21 | .pipe(fs.createWriteStream('gl.png')) 22 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/5_networking.js: -------------------------------------------------------------------------------- 1 | const swarm = require('webrtc-swarm') 2 | const sh = require('signalhub') 3 | const wrtc = require('wrtc') 4 | 5 | const hub = sh('') 6 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/6_hyperscript.js: -------------------------------------------------------------------------------- 1 | const h = require('hyperscript') 2 | 3 | const el = h('div#page', [ 4 | h('div.hello', [ 5 | h('p', 'hi'), 6 | h('p', 'world') 7 | ]) 8 | ]) 9 | 10 | // node 11 | // console.log(el.outerHTML) 12 | 13 | // browser with budo 14 | document.querySelector('body').appendChild(el) 15 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/7_baudio.js: -------------------------------------------------------------------------------- 1 | const baudio = require('baudio') 2 | 3 | // beep 4 | // var n = 0 5 | // var b = baudio(function (t) { 6 | // const x = Math.sin(t * 262 + Math.sin(n)) 7 | // n += Math.sin(t) 8 | // return x 9 | // }) 10 | 11 | // crackle 12 | // var b = baudio(function (t, i) { 13 | // return (( 14 | // (i & 0x71) * Math.floor(i / 3571) * Math.floor(i / 3559) 15 | // ) % 256) / 128 - 1 16 | // }) 17 | 18 | // ramp 19 | var b = baudio(function (t, i) { 20 | var n = 28 21 | var c = 10 * (1 + Math.sin(i / 20000) / 10000) 22 | return Math.sin( 23 | (t % 15) * 150 * (t % 30) * Math.floor(Math.sin(t) * 5) 24 | ) + (t << 3) * (t & 0x7f) / 256 + Math.sin(t * 5000) * Math.max(0, Math.sin(t * n + c * Math.sin(t * 20))) 25 | }) 26 | 27 | setInterval(function () { 28 | b.play() 29 | }, 100) 30 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ 11 rad packages │██ 5 | │ │██ 6 | │ Yoshua Wuyts │██ 7 | │ 2015-11-22 │██ 8 | │ │██ 9 | └─────────────────────────┘██ 10 | ███████████████████████████ 11 | ``` 12 | 13 | --- 14 | ## Hello, I'm Yosh 15 | - interfaces 16 | - unix 17 | - node 18 | - consulting 19 | 20 | --- 21 | ## WARNING 22 | ## MAD SCIENCE AHEAD 23 | 24 | ---- 25 | ## Electron 26 | - hihat 27 | - says 28 | 29 | --- 30 | ## WebGL 31 | - headless-gl 32 | 33 | --- 34 | ## OS 35 | - linux 36 | 37 | --- 38 | ## Frontend 39 | - hyperscript 40 | - budo 41 | 42 | --- 43 | ## Networking 44 | - SignalHub 45 | - WebRTC-swarm 46 | 47 | --- 48 | ## Servers 49 | - LevelDB 50 | - http-ndjson 51 | - bole 52 | 53 | --- 54 | ## Sound 55 | - baudio 56 | 57 | --- 58 | ## Thank you! 59 | - twitter.com/yoshuawuyts 60 | - github.com/yoshuawuyts 61 | 62 | Slides available on: 63 | - https://github.com/yoshuawuyts/talks/2015-11-21-ten-modules 64 | - npm i -g tslide to view the slides 65 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2015-11-campjs-vi/gl.png -------------------------------------------------------------------------------- /2015-11-campjs-vi/index.frag: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | uniform float iGlobalTime; 4 | uniform vec2 iResolution; 5 | 6 | vec2 noiseOffset = vec2(0.0); 7 | 8 | vec2 squareFrame_6_0(vec2 screenSize, vec2 coord) { 9 | vec2 position = 2.0 * (coord.xy / screenSize.xy) - 1.0; 10 | position.x *= screenSize.x / screenSize.y; 11 | return position; 12 | } 13 | 14 | 15 | 16 | mat3 calcLookAtMatrix_8_1(vec3 origin, vec3 target, float roll) { 17 | vec3 rr = vec3(sin(roll), cos(roll), 0.0); 18 | vec3 ww = normalize(target - origin); 19 | vec3 uu = normalize(cross(ww, rr)); 20 | vec3 vv = normalize(cross(uu, ww)); 21 | 22 | return mat3(uu, vv, ww); 23 | } 24 | 25 | 26 | 27 | 28 | vec3 getRay_7_2(mat3 camMat, vec2 screenPos, float lensLength) { 29 | return normalize(camMat * vec3(screenPos, lensLength)); 30 | } 31 | 32 | vec3 getRay_7_2(vec3 origin, vec3 target, vec2 screenPos, float lensLength) { 33 | mat3 camMat = calcLookAtMatrix_8_1(origin, target, 0.0); 34 | return getRay_7_2(camMat, screenPos, lensLength); 35 | } 36 | 37 | 38 | 39 | 40 | void orbitCamera_2_3( 41 | in float camAngle, 42 | in float camHeight, 43 | in float camDistance, 44 | in vec2 screenResolution, 45 | out vec3 rayOrigin, 46 | out vec3 rayDirection, 47 | in vec2 fragCoord 48 | ) { 49 | vec2 screenPos = squareFrame_6_0(screenResolution, fragCoord); 50 | vec3 rayTarget = vec3(0.0); 51 | 52 | rayOrigin = vec3( 53 | camDistance * sin(camAngle), 54 | camHeight, 55 | camDistance * cos(camAngle) 56 | ); 57 | 58 | rayDirection = getRay_7_2(rayOrigin, rayTarget, screenPos, 2.0); 59 | } 60 | 61 | 62 | 63 | // 64 | // Description : Array and textureless GLSL 2D/3D/4D simplex 65 | // noise functions. 66 | // Author : Ian McEwan, Ashima Arts. 67 | // Maintainer : ijm 68 | // Lastmod : 20110822 (ijm) 69 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 70 | // Distributed under the MIT License. See LICENSE file. 71 | // https://github.com/ashima/webgl-noise 72 | // 73 | 74 | vec3 mod289_1_4(vec3 x) { 75 | return x - floor(x * (1.0 / 289.0)) * 289.0; 76 | } 77 | 78 | vec4 mod289_1_4(vec4 x) { 79 | return x - floor(x * (1.0 / 289.0)) * 289.0; 80 | } 81 | 82 | vec4 permute_1_5(vec4 x) { 83 | return mod289_1_4(((x*34.0)+1.0)*x); 84 | } 85 | 86 | vec4 taylorInvSqrt_1_6(vec4 r) 87 | { 88 | return 1.79284291400159 - 0.85373472095314 * r; 89 | } 90 | 91 | float snoise_1_7(vec3 v) 92 | { 93 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 94 | const vec4 D_1_8 = vec4(0.0, 0.5, 1.0, 2.0); 95 | 96 | // First corner 97 | vec3 i = floor(v + dot(v, C.yyy) ); 98 | vec3 x0 = v - i + dot(i, C.xxx) ; 99 | 100 | // Other corners 101 | vec3 g_1_9 = step(x0.yzx, x0.xyz); 102 | vec3 l = 1.0 - g_1_9; 103 | vec3 i1 = min( g_1_9.xyz, l.zxy ); 104 | vec3 i2 = max( g_1_9.xyz, l.zxy ); 105 | 106 | // x0 = x0 - 0.0 + 0.0 * C.xxx; 107 | // x1 = x0 - i1 + 1.0 * C.xxx; 108 | // x2 = x0 - i2 + 2.0 * C.xxx; 109 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 110 | vec3 x1 = x0 - i1 + C.xxx; 111 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 112 | vec3 x3 = x0 - D_1_8.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 113 | 114 | // Permutations 115 | i = mod289_1_4(i); 116 | vec4 p = permute_1_5( permute_1_5( permute_1_5( 117 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 118 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 119 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 120 | 121 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 122 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 123 | float n_ = 0.142857142857; // 1.0/7.0 124 | vec3 ns = n_ * D_1_8.wyz - D_1_8.xzx; 125 | 126 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 127 | 128 | vec4 x_ = floor(j * ns.z); 129 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 130 | 131 | vec4 x = x_ *ns.x + ns.yyyy; 132 | vec4 y = y_ *ns.x + ns.yyyy; 133 | vec4 h = 1.0 - abs(x) - abs(y); 134 | 135 | vec4 b0 = vec4( x.xy, y.xy ); 136 | vec4 b1 = vec4( x.zw, y.zw ); 137 | 138 | //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; 139 | //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; 140 | vec4 s0 = floor(b0)*2.0 + 1.0; 141 | vec4 s1 = floor(b1)*2.0 + 1.0; 142 | vec4 sh = -step(h, vec4(0.0)); 143 | 144 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 145 | vec4 a1_1_10 = b1.xzyw + s1.xzyw*sh.zzww ; 146 | 147 | vec3 p0_1_11 = vec3(a0.xy,h.x); 148 | vec3 p1 = vec3(a0.zw,h.y); 149 | vec3 p2 = vec3(a1_1_10.xy,h.z); 150 | vec3 p3 = vec3(a1_1_10.zw,h.w); 151 | 152 | //Normalise gradients 153 | vec4 norm = taylorInvSqrt_1_6(vec4(dot(p0_1_11,p0_1_11), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 154 | p0_1_11 *= norm.x; 155 | p1 *= norm.y; 156 | p2 *= norm.z; 157 | p3 *= norm.w; 158 | 159 | // Mix final noise value 160 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 161 | m = m * m; 162 | return 42.0 * dot( m*m, vec4( dot(p0_1_11,x0), dot(p1,x1), 163 | dot(p2,x2), dot(p3,x3) ) ); 164 | } 165 | 166 | 167 | 168 | float orenNayarDiffuse_5_12( 169 | vec3 lightDirection, 170 | vec3 viewDirection, 171 | vec3 surfaceNormal, 172 | float roughness, 173 | float albedo) { 174 | 175 | float LdotV = dot(lightDirection, viewDirection); 176 | float NdotL = dot(lightDirection, surfaceNormal); 177 | float NdotV = dot(surfaceNormal, viewDirection); 178 | 179 | float s = LdotV - NdotL * NdotV; 180 | float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); 181 | 182 | float sigma2 = roughness * roughness; 183 | float A = 1.0 + sigma2 * (albedo / (sigma2 + 0.13) + 0.5 / (sigma2 + 0.33)); 184 | float B = 0.45 * sigma2 / (sigma2 + 0.09); 185 | 186 | return albedo * max(0.0, NdotL) * (A + B * s / t) / 3.14159265; 187 | } 188 | 189 | 190 | float gaussianSpecular_3_13( 191 | vec3 lightDirection, 192 | vec3 viewDirection, 193 | vec3 surfaceNormal, 194 | float shininess) { 195 | vec3 H = normalize(lightDirection + viewDirection); 196 | float theta = acos(dot(H, surfaceNormal)); 197 | float w = theta / shininess; 198 | return exp(-w*w); 199 | } 200 | 201 | 202 | float fogFactorExp2_4_14( 203 | const float dist, 204 | const float density 205 | ) { 206 | const float LOG2 = -1.442695; 207 | float d = density * dist; 208 | return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0); 209 | } 210 | 211 | 212 | 213 | 214 | float voxelModel(vec3 p) { 215 | return 5.0 * snoise_1_7(p.xyz * 0.05 + vec3(0, noiseOffset.x * sin(noiseOffset.y), 0)) - p.y > 8.0 ? 1.0 : 0.0; 216 | } 217 | 218 | vec2 raymarchVoxel(vec3 ro, vec3 rd, out vec3 nor) { 219 | vec3 pos = floor(ro); 220 | vec3 ri = 1.0 / rd; 221 | vec3 rs = sign(rd); 222 | vec3 dis = (pos - ro + 0.5 + rs * 0.5) * ri; 223 | 224 | float res = -1.0; 225 | vec3 mm = vec3(0.0); 226 | 227 | for (int i = 0; i < 96; i++) { 228 | float k = voxelModel(pos); 229 | if (k > 0.5) { 230 | res = k; 231 | break; 232 | } 233 | 234 | mm = step(dis.xyz, dis.yxy) * step(dis.xyz, dis.zzx); 235 | dis += mm * rs * ri; 236 | pos += mm * rs; 237 | } 238 | 239 | if (res < -0.5) { 240 | return vec2(-1.0); 241 | } 242 | 243 | nor = -mm * rs; 244 | 245 | vec3 vpos = pos; 246 | vec3 mini = (pos-ro + 0.5 - 0.5*vec3(rs))*ri; 247 | float t = max(mini.x, max(mini.y, mini.z)); 248 | 249 | return vec2(t, 0.0); 250 | } 251 | 252 | float attenuate(float d) { 253 | return pow(clamp(1.0 - d / 60.0, 0.0, 1.0), 2.95); 254 | } 255 | 256 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 257 | vec2 uv = fragCoord.xy / iResolution.xy * 2.0 - 1.0; 258 | vec3 color = vec3(1.1, 0.98, 1.3); 259 | vec3 ro, rd; 260 | 261 | float rotation = sin(iGlobalTime * 0.124) * 3.3; 262 | float height = 2.0 + (sin(iGlobalTime) * 0.5 + 0.5) * 0.5; 263 | float dist = 4.0; 264 | orbitCamera_2_3(rotation, height, dist, iResolution.xy, ro, rd, fragCoord); 265 | 266 | ro.z -= iGlobalTime * 10.; 267 | 268 | vec3 nor; 269 | vec2 t = raymarchVoxel(ro, rd, nor); 270 | if (t.x > -0.5) { 271 | vec3 pos = ro + rd * t.x; 272 | vec3 mat = abs(fract(pos + 0.5)); 273 | 274 | mat = fract(smoothstep(-0.3, 0.15, mat - 0.5) + 0.5); 275 | mat = pow(1.0 - (mat) * 4., vec3(0.8)); 276 | mat = 1.0 - clamp(vec3(mat.x * mat.y + mat.y * mat.z + mat.x * mat.z), 0.2, 0.35); 277 | 278 | vec3 lpos1 = ro + vec3(sin(iGlobalTime) * 5., cos(iGlobalTime) * 5., 2.); 279 | vec3 lcol1 = vec3(1, 0.5, 0.3) * 3.; 280 | vec3 ldir1 = normalize(lpos1 - pos); 281 | float att1 = attenuate(length(lpos1 - pos)); 282 | float dif1 = orenNayarDiffuse_5_12(ldir1, -rd, nor, 0.3, 1.0); 283 | float spc1 = gaussianSpecular_3_13(ldir1, -rd, nor, 2.25) * 0.5; 284 | vec3 lpos2 = ro + vec3(cos(iGlobalTime) * 3., sin(iGlobalTime) * 3., 2.); 285 | vec3 lcol2 = vec3(0.3, 0.5, 0.9) * 1.9; 286 | vec3 ldir2 = normalize(lpos2 - pos); 287 | float att2 = attenuate(length(lpos2 - pos)); 288 | float dif2 = orenNayarDiffuse_5_12(ldir2, -rd, nor, 0.3, 1.0); 289 | float spc2 = gaussianSpecular_3_13(ldir2, -rd, nor, 2.25) * 0.5; 290 | 291 | color = mix(color, 292 | att1 * lcol1 * (spc1 + dif1 * mat) + 293 | att2 * lcol2 * (spc2 + dif2 * mat) , 294 | 1.0 - fogFactorExp2_4_14(t.x, 0.028 - pos.y * 0.001) 295 | ); 296 | } 297 | 298 | color.r *= 1.0 - dot(uv, uv) * 0.15; 299 | color.r = smoothstep(0.1, 1.0, color.r); 300 | 301 | fragColor.rgb = color; 302 | fragColor.a = 1.0; 303 | } 304 | 305 | void main() { 306 | mainImage(gl_FragColor.rgba, gl_FragCoord.xy); 307 | } 308 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/index.vert: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | attribute vec2 position; 4 | 5 | void main() { 6 | gl_Position = vec4(position, 1, 1); 7 | } -------------------------------------------------------------------------------- /2015-11-campjs-vi/linux/hostname: -------------------------------------------------------------------------------- 1 | casper-jack-harley-garfield -------------------------------------------------------------------------------- /2015-11-campjs-vi/linux/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAkmu63gqg3y9d3iQPN/kEjufAZXa5Wo8t+as3+n1Q2HA5MT8LdTywpAVG 3 | cJGC5SPNHPU08+PRgy+Yh3ZuTteq706tFtdZngIGjHZBRougf81tdGdHKdDzQ5BMIA52qyK+ 4 | f8gJcJlvDlUXypuXs64CQkQJeUdn5yJaA41wHfMjNc8jEHWqy9sgnhzmcYbJowcZ0IlMcOAS 5 | Je3U40tgauKPBKni52iqKMss953fol/vg203XJWBLMgz7B7+8fTi7+q2Vs2tqVrxSSJTjUD2 6 | 0MnkC9ZbzGX0liuxLK9o3NKZ4bw34ckbg6JseERrR7PxsXxVkavMNSteWMqHbtQ8skfnuQID 7 | AQABAoIBAAWVTAvZdebsxHSLBXWJ7k2Qsrpru4ejfApQKBNKIgIOzW9+Su6OgOHQPa5fLhGU 8 | uuaGxx0hq8SH1RYdQvmIqcD0TA9Z6NXol91VSQnqmxUkfS76HTGQASarYuu6AXZnHcJ7mziK 9 | 8TwnrH+STUeRtA5Yz8+rFGAw5CPMieDqe4Y6r/1syB/Ik9BNPswVnMiIszUu4B7EM5Wcif/8 10 | USs5hZj5xI/sgMbq8IBAWqRs2h8HURIiqplOh88J42yKg9X4EHiLu2LiAJKRdCX1KaoLsWBo 11 | /os89sfwWT12NiXE6/AN2tapNUeGzdaGPEmfrDeZ0JusDzM0CikDDQOyUVGgswECgYEAzgSV 12 | 5BHBGz4lwh26wAkPTtSnZeXzKZhUGFpA49aGk4n4H0ehz9VOl4o9Sgn215Qw5zqJ07xHNi+M 13 | plBXKEyVapM73Erj1sGL6zoTztZz5Ra4JuJgIicEWqkO0tqWa7iBsCPqiOF24bx5m790fyhz 14 | dSB4nAPsgNXI1l/Icez1tFkCgYEAtfGsMTUp8MvuoREQ5DILFAlLLcadlUmrZWgf+8F3C4L0 15 | ZewWr1w5IngLxizL/tlEs/d1A5hXFLo/HeN97wnIzednNZiCbY0Do35f5za9UMwahgYKH2CY 16 | ATNEbdqVVYA45vV9dwBoQIhb/SIEDEVrm8HArB55bJ3TFArqFmC44mECgYAahNSWiwKEczeB 17 | CTqkxYXG6/CwWS03yXfpupRnv5GLJFNgE2Rs0FRRhWXmReoUTesNmKdtLessumosbmMJuPHy 18 | ygkGjk1Ns5RDLzKliU1Zy9bgins9ajBRSzmxQpniO9nVxonGHN+kpxIwTjC8vYQ/K3LbAlZL 19 | Lzmu/p1arNnj4QKBgQAKapOZHZoRFxvKTNfSuKq5su6C6GQNL/KIE7YBC8ps9kpXq3SBBZ6f 20 | wo+qANaM+JNeWkRwuEAEB8WlSGjlToIYh674+oo9C12x9oI3EoM0JPs/wQjDUxxgtTats13p 21 | TzXywwszzOorB6N8kn341eCbQjRtpjD9buuushFExrTPAQKBgBFqCxHl1jbiTYW7Cve6F+eq 22 | eEPhNOETGjCYrPQhheZANxhqgC5ieddqg7ubN/bEL44SH4+D8S/E133U69Z5BQRQ9rXdY8E7 23 | Z1on0vnwAr+QbfSnnTITUlrF5t2Ua3pU2HbpxmIgosCUqzYlhpc7mChi1i4TF05vB6HHKOA2 24 | /PFE 25 | -----END RSA PRIVATE KEY----- 26 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/linux/id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCSa7reCqDfL13eJA83+QSO58Bldrlajy35qzf6fVDYcDkxPwt1PLCkBUZwkYLlI80c9TTz49GDL5iHdm5O16rvTq0W11meAgaMdkFGi6B/zW10Z0cp0PNDkEwgDnarIr5/yAlwmW8OVRfKm5ezrgJCRAl5R2fnIloDjXAd8yM1zyMQdarL2yCeHOZxhsmjBxnQiUxw4BIl7dTjS2Bq4o8EqeLnaKooyyz3nd+iX++DbTdclYEsyDPsHv7x9OLv6rZWza2pWvFJIlONQPbQyeQL1lvMZfSWK7Esr2jc0pnhvDfhyRuDomx4RGtHs/GxfFWRq8w1K15Yyodu1DyyR+e5 root@localhost -------------------------------------------------------------------------------- /2015-11-campjs-vi/linux/linux.pid: -------------------------------------------------------------------------------- 1 | 52997 -------------------------------------------------------------------------------- /2015-11-campjs-vi/linux/stderr.log: -------------------------------------------------------------------------------- 1 | Error return from kevent change: Invalid argument 2 | Error return from kevent change: No such file or directory 3 | Error return from kevent change: No such file or directory 4 | Error return from kevent change: No such file or directory 5 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/linux/stdout.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2015-11-campjs-vi/linux/stdout.log -------------------------------------------------------------------------------- /2015-11-campjs-vi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2015-11-21-ten-modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Yoshua Wuyts ", 10 | "license": "ISC", 11 | "dependencies": { 12 | "JSONStream": "^1.0.7", 13 | "a-big-triangle": "^1.0.2", 14 | "baudio": "^2.1.2", 15 | "browserify": "^12.0.1", 16 | "budo": "^6.0.4", 17 | "garnish": "^4.1.1", 18 | "gl": "^2.1.5", 19 | "gl-shader": "^4.0.6", 20 | "glslify": "^2.3.1", 21 | "hihat": "^2.5.0", 22 | "hyperscript": "^1.4.7", 23 | "level": "^1.3.0", 24 | "linux": "^2.6.0", 25 | "ndarray": "^1.0.18", 26 | "save-pixels": "^2.3.0", 27 | "says": "^1.0.2", 28 | "sheetify": "^3.1.0", 29 | "signalhub": "^4.3.1", 30 | "webrtc-swarm": "^2.2.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/packages.md: -------------------------------------------------------------------------------- 1 | - linux 2 | - gl (headless-gl) 3 | - hihat 4 | - says 5 | - sheetify 6 | - hyperscript 7 | - signalhub 8 | - webrtc-swarm 9 | - garnish 10 | - budo 11 | - baudio 12 | - leveldb 13 | -------------------------------------------------------------------------------- /2015-11-campjs-vi/proposal.md: -------------------------------------------------------------------------------- 1 | # twenty modules in twenty minutes 2 | In where yosh will a broad spectrum of Node development showing off a modules 3 | you may or may not have heard of, but are pretty rad. 4 | 5 | ## whoami 6 | Yoshua is a JavaScript programmer with over 300 modules on npm. He's appeared 7 | on the Nodeup podcast to talk about modules and keeps a big list of rad 8 | modules. 9 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/1.js: -------------------------------------------------------------------------------- 1 | const err = new Error('oh my, something went wrong') 2 | console.log(err.stack) 3 | console.log(err.message) 4 | err.foo = 'bar' 5 | throw err 6 | 7 | // ! node 1.js 8 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/2.js: -------------------------------------------------------------------------------- 1 | const value = { foo: 'bar' } 2 | validate(value, function (err, res) { 3 | if (err) return console.error(err) 4 | console.log(res) 5 | }) 6 | 7 | // (obj, fn(err?, val?)) -> null 8 | function validate (obj, cb) { 9 | if (!obj.baz) { 10 | const err = new Error('No baz property') 11 | return cb(err) 12 | } 13 | cb(null, 'success!') 14 | } 15 | 16 | // ! node 2.js 17 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/3.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | square(3) 4 | 5 | function square (num) { 6 | // compare and throw if false 7 | assert.equal(typeof num, 'number', 'num is number') 8 | return num * num 9 | } 10 | 11 | // ! node 3.js 12 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/4.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const http = require('http') 3 | 4 | const server = http.createServer(function (req, res) { 5 | server.close() 6 | }) 7 | server.listen(8080, summary(server)) 8 | 9 | http.get('http://localhost:8080') 10 | 11 | // ! node 4.js 12 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/5.js: -------------------------------------------------------------------------------- 1 | const boleStream = require('bole-stream') 2 | const httpNdjson = require('http-ndjson') 3 | const stdout = require('stdout-stream') 4 | const bole = require('bole') 5 | const http = require('http') 6 | 7 | bole.output({ level: 'debug', stream: stdout }) 8 | const logStream = boleStream({ level: 'debug' }) 9 | 10 | const server = http.createServer(function (req, res) { 11 | const httpLogger = httpNdjson(req, res) 12 | httpLogger.pipe(logStream, { end: false }) 13 | res.end() 14 | }).listen(8080) 15 | 16 | http.get('http://localhost:8080', function (res) { 17 | server.close() 18 | }) 19 | 20 | // ! node 5.js 21 | // ! node 5.js | garnish 22 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/6.js: -------------------------------------------------------------------------------- 1 | const boleStream = require('bole-stream') 2 | const httpNdjson = require('http-ndjson') 3 | const sizeStream = require('size-stream') 4 | const stdout = require('stdout-stream') 5 | const pumpify = require('pumpify') 6 | const bole = require('bole') 7 | const http = require('http') 8 | 9 | bole.output({ level: 'debug', stream: stdout }) 10 | const logStream = boleStream({ level: 'debug' }) 11 | 12 | const server = http.createServer(function (req, res) { 13 | const httpLogger = httpNdjson(req, res) 14 | httpLogger.pipe(logStream, { end: false }) 15 | 16 | const size = sizeStream() 17 | size.once('size', size => httpLogger.setContentLength(size)) 18 | 19 | const sink = pumpify(size, res) 20 | sink.end('some very long response') 21 | }).listen(8080) 22 | 23 | http.get('http://localhost:8080', function (res) { 24 | server.close() 25 | }) 26 | 27 | // ! node 6.js | jq .contentLength 28 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ Logging and error │██ 5 | │ handling in Node.js │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2015-11-05 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | 16 | ## Hello, I'm Yosh 17 | - interfaces 18 | - unix 19 | - node 20 | - consulting 21 | 22 | --- 23 | 24 | ## Logging & error handling in 30 mins 25 | - How do Errors work in Node? 26 | - Error handling patterns 27 | - Healthy logging practices 28 | - {Unix,Node} tools 29 | - Gotchas 30 | 31 | --- 32 | 33 | ## Logging & error handling in 30 mins 34 | 1. Error occurs 35 | 2. Create error object 36 | 3. Format error into log line 37 | 4. Process logs on system 38 | 5. Packages 39 | 40 | --- 41 | 42 | ## 1. Errors 43 | Error causes 44 | - request errors 45 | - validation errors 46 | - permission errors 47 | - syntax errors 48 | - sync / async 49 | 50 | --- 51 | 52 | ## 1. Errors 53 | 2 types of errors 54 | - expected (user) errors 55 | - unexpected (programmer) errors 56 | 57 | --- 58 | 59 | ## 1. Errors 60 | - expected errors are handled gracefully 61 | - unexpected errors kill the process 62 | 63 | --- 64 | 65 | ## 1. Errors 66 | Note on try .. catch 67 | - does not work on async 68 | - only use on expected errors 69 | - don't wrap every function in it 70 | - don't use promises 71 | - use cluster to prevent downtime 72 | - or try async_wrap for unexpected errors 73 | 74 | --- 75 | 76 | ## 2. Creating errors 77 | - Class:Error 78 | - global 79 | - exist in both Node & browser 80 | - errors were made for throwin' 81 | - .stack contains stack trace 82 | - .message contains message 83 | - don't use strings, use Error 84 | 85 | --- 86 | 87 | ## 2. Creating errors 88 | Creating a new error: 89 | ```js 90 | const err = new Error('oh my, something went wrong') 91 | console.log(err.stack) 92 | console.log(err.message) 93 | err.foo = 'bar' 94 | throw err 95 | ``` 96 | 97 | --- 98 | 99 | ## 2. Creating errors 100 | Demo 1 101 | 102 | --- 103 | 104 | ## 2. Creating errors 105 | Expected errors: 106 | ```js 107 | const value = { foo: 'bar' } 108 | validate(value, function (err, res) { 109 | if (err) return console.error(err) 110 | console.log(res) 111 | }) 112 | 113 | // (obj, fn(err?, val?)) -> null 114 | function validate (obj, cb) { 115 | if (!obj.baz) { 116 | const err = new Error('No baz property') 117 | return cb(err) 118 | } 119 | cb(null, 'success!') 120 | } 121 | ``` 122 | 123 | --- 124 | 125 | ## 2. Creating errors 126 | Demo 2 127 | 128 | --- 129 | 130 | ## 2. Creating errors 131 | Unexpected error. Thrashes process 132 | ```js 133 | const assert = require('assert') 134 | 135 | const squared = square('definitely not a number') 136 | 137 | function square (num) { 138 | // compare and throw if false 139 | assert.equal(typeof num, 'number', 'num is number') 140 | return num * num 141 | } 142 | ``` 143 | 144 | --- 145 | 146 | ## 2. Creating errors 147 | Demo 3 148 | 149 | --- 150 | 151 | ## 3. Get errors into logs 152 | Logs need a log format: 153 | - convenient for JS 154 | - contain timestamp 155 | - contain pid 156 | - contain all other information 157 | 158 | --- 159 | 160 | ## 3. Get errors into logs 161 | NDJSON: Newline Delimited JSON (ndjson.org) 162 | 163 | 1. Line separator is '\n' 164 | 2. Each line is a valid JSON value 165 | 166 | ```js 167 | console.log(JSON.stringify({ foo: 'bar' }) + '\n') 168 | ``` 169 | 170 | --- 171 | 172 | ## 3. Get errors into logs 173 | `bole` logger: 174 | - decentralized 175 | - single global config 176 | - streaming 177 | - tiny api surface 178 | - large ecosystem 179 | 180 | --- 181 | 182 | ## 3. Get errors into logs 183 | Logging expected errors: 184 | ```js 185 | const bole = require('bole') 186 | bole.output({ level: 'info', stream: process.stdout }) 187 | 188 | const log = bole('mymodule') 189 | log.info('hello') 190 | log.error(new Error('world')) 191 | ``` 192 | 193 | --- 194 | 195 | ## 3. Get errors into logs 196 | Log output: 197 | ```txt 198 | $ node index.js 199 | {"time":"2014-05-18T23:47:06.545Z","hostname":"tweedy","pid":27374,"level":"info","name":"mymodule","message":"hello"} 200 | {"time":"2014-05-18T23:47:06.545Z","hostname":"tweedy","pid":27374,"level":"info","name":"mymodule", "err": { "message": "world", "stack": (...)}} 201 | ``` 202 | 203 | --- 204 | 205 | ## 3. Get errors into logs 206 | Logging unexpected errors: 207 | ```js 208 | const bole = require('bole') 209 | const log = bole() 210 | process.on('uncaughtException', function (err) { 211 | log.error(err) 212 | throw err 213 | }) 214 | ``` 215 | 216 | --- 217 | 218 | ## 4. Process logs 219 | - logs should always go to stdout 220 | - logs should be written to /var/log/ 221 | - rotate logs using logrotate(1) 222 | 223 | --- 224 | 225 | ## 4. Process logs 226 | std{out,err} -> /var/log/ 227 | ```sh 228 | $ node . 2>&1 /var/log/my-app.log 229 | ``` 230 | 231 | --- 232 | 233 | ## 4. Process logs 234 | Write to file + console: 235 | ```sh 236 | $ node . | tee 2>&1 /var/log/my-app.log 237 | ``` 238 | 239 | --- 240 | 241 | ## 5. Packages 242 | - error: error constructor / wrapper 243 | - source-map-support: fix transpile stack traces 244 | - http-ndjson: log http req / res 245 | - size-stream: get http res size 246 | - bole-stream: log ndjson into bole 247 | - stdout-stream: non-blocking stdout 248 | - server-summary: log base server info 249 | - garnish: prettify bole output 250 | 251 | --- 252 | 253 | ## 5. Packages 254 | Fix stack traces after transpilation: 255 | ```js 256 | require('source-map-support/register') 257 | ``` 258 | 259 | --- 260 | 261 | ## 5. Packages 262 | Error constructors using `error`: 263 | ```js 264 | const typedError = require('error/typed') 265 | const badRequestError = typedError({ 266 | type: 'server.4xx', 267 | message: {message}, 268 | statusCode: 400 269 | }) 270 | const err = badRequestError({ message: 'whoops' }) 271 | ``` 272 | 273 | --- 274 | 275 | ## 5. Packages 276 | Use `stdout-stream`. 277 | 278 | Stdout blocks, `end` never prints: 279 | ``` js 280 | console.error('start'); 281 | process.stdout.write(new Buffer(1024*1024)); 282 | console.error('end'); 283 | ``` 284 | 285 | ```sh 286 | $ node example.js | sleep 1000 287 | ``` 288 | 289 | --- 290 | 291 | ## 5. Packages 292 | Log base server info on start: 293 | ```js 294 | const summary = require('server-summary') 295 | const http = require('http') 296 | 297 | const server = http.createServer(function (req, res) { 298 | // logic goes here 299 | }) 300 | server.listen(8080, summary(server)) 301 | ``` 302 | 303 | --- 304 | 305 | ## 5. Packages 306 | Demo 4 307 | 308 | --- 309 | 310 | ## 5. Packages 311 | Log http req,res: 312 | ```js 313 | const boleStream = require('bole-stream') 314 | const httpNdjson = require('http-ndjson') 315 | 316 | const logStream = boleStream({ level: 'debug' }) 317 | http.createServer(function (req, res) { 318 | const httpLogger = httpNdjson(req, res) 319 | httpLogger.pipe(logStream, { end: false }) 320 | }).listen() 321 | ``` 322 | 323 | --- 324 | 325 | ## 5. Packages 326 | Demo 5 327 | 328 | --- 329 | 330 | ## 5. Packages 331 | Log res size: 332 | ```js 333 | const boleStream = require('bole-stream') 334 | const httpNdjson = require('http-ndjson') 335 | const sizeStream = require('size-stream') 336 | const app = require('./app')() 337 | 338 | const logStream = boleStream({ level: 'debug' }) 339 | http.createServer(function (req, res) { 340 | const httpLogger = httpNdjson(req, res) 341 | httpLogger.pipe(logStream, { end: false }) 342 | 343 | const size = sizeStream() 344 | size.once('size', size => httpLogger.setContentLength(size)) 345 | 346 | app(req, res).pipe(size).pipe(res) 347 | }).listen() 348 | ``` 349 | 350 | --- 351 | 352 | ## 5. Packages 353 | Demo 6 354 | 355 | --- 356 | 357 | ## Recap 358 | - all errors should inherit from Error 359 | - errbacks are for expected errors 360 | - throw is for unexpected errors 361 | - node logs in ndjson 362 | - logs should always go to stdout 363 | - logs should be written to /var/log/ 364 | - rotate logs with logrotate(1) 365 | 366 | --- 367 | 368 | ## log.info('Thank you!') 369 | - twitter.com/yoshuawuyts 370 | - github.com/yoshuawuyts 371 | 372 | Slides available on: 373 | - https://github.com/yoshuawuyts/talks/2015-11-errors-and-logs 374 | - npm i -g tslide to view the slides 375 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2015-11-errors-and-logs", 3 | "version": "1.0.0", 4 | "description": "``` ┌─────────────────────────┐ │ │██ │ Logging and error │██ │ handling in Node.js │██ │ │██ │ Yoshua Wuyts │██ │ 2015-11-05 │██ │ │██ └─────────────────────────┘██ ███████████████████████████ ```", 5 | "main": "1.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Yoshua Wuyts ", 10 | "license": "ISC", 11 | "dependencies": { 12 | "bole": "^2.0.0", 13 | "bole-stream": "^2.1.0", 14 | "http-ndjson": "^2.3.3", 15 | "pump": "^1.0.1", 16 | "pumpify": "^1.3.3", 17 | "server-summary": "^4.0.1", 18 | "size-stream": "^1.0.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/proposal.md: -------------------------------------------------------------------------------- 1 | # Logs and error handling in Node.js 2 | You cannot fix what you don't know is broken. Keeping logs and handling errors 3 | is crucial for any application in production. In this talk yosh will show you 4 | how to sustainably approach logs and error handling for applications on any 5 | scale. 6 | 7 | --- 8 | ## For organizers only 9 | Though errors and logging might not seem to be the most exciting of subjects, 10 | there exists a great deal of confusion and ad-hoc solutions to this in the Node 11 | community. In this talk I'll explain the basic principles and gotchas behind 12 | logging in Node. It's going to be a combination of unix tools, data formats, 13 | npm packages and architecture. 14 | 15 | Hopefully I'll be able to nudge people in the right direction so they can 16 | continue learning on their own. 17 | -------------------------------------------------------------------------------- /2015-11-nodeninjas/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | nvim -p ./*.js 4 | -------------------------------------------------------------------------------- /2015-11-sydjs/1.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | fs.createReadStream(__filename) 4 | .pipe(fs.createWriteStream('./other-file')) 5 | -------------------------------------------------------------------------------- /2015-11-sydjs/2.js: -------------------------------------------------------------------------------- 1 | const stream = require('stream') 2 | 3 | // primitive .pipe() 4 | const stream1 = new stream.PassThrough() 5 | const stream2 = new stream.PassThrough() 6 | 7 | process.stdin.pipe(stream1) 8 | 9 | stream1.on('readable', function () { 10 | stream1.on('data', function (data) { 11 | stream2.write(String(data).toUpperCase()) 12 | }) 13 | stream1.on('end', function () { 14 | stream2.end() 15 | }) 16 | }) 17 | 18 | stream2.pipe(process.stdout) 19 | -------------------------------------------------------------------------------- /2015-11-sydjs/3.js: -------------------------------------------------------------------------------- 1 | const through = require('through2') 2 | 3 | const rs = process.stdin 4 | const ts = grep(/foo/) 5 | const ws = process.stdout 6 | rs.pipe(ts).pipe(ws) 7 | 8 | function grep (regex) { 9 | return through(function (chunk, enc, cb) { 10 | const str = String(chunk) 11 | if (regex.test(chunk)) this.push(str.toUpperCase()) 12 | cb() 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /2015-11-sydjs/4.js: -------------------------------------------------------------------------------- 1 | const http = require('http') 2 | 3 | http.createServer(function (req, res) { 4 | res.setHeader('Content-Type', 'text/css') 5 | res.end('.foo { color: rebecca-purple }') 6 | }).listen(8080) 7 | -------------------------------------------------------------------------------- /2015-11-sydjs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ pipe, emit, │██ 5 | │ stream, listen │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2015-11-18 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello, I'm Yosh 16 | - interfaces 17 | - unix 18 | - node 19 | - consulting 20 | 21 | --- 22 | ## How to learn streams? 23 | - star all of @mafintosh's modules 24 | - write an article on how to use streams 25 | - write a bunch of stream modules 26 | - include streams training in consulting offer 27 | - give a talk on streams 28 | 29 | --- 30 | ## Streams in 20 mins 31 | - why streams? 32 | - how do streams work? 33 | - modules 34 | - cool things 35 | 36 | --- 37 | ## Why streams? 38 | - _extremely_ fast 39 | - composable 40 | - clear purpose 41 | - neat syntax 42 | - based on events (observables!) 43 | 44 | --- 45 | ## Basics 46 | Streams originate from the unix shell 47 | ```sh 48 | $ cat ./my-file > ./other-file 49 | ``` 50 | ```js 51 | const fs = require('fs') 52 | 53 | fs.createReadStream('./my-file') 54 | .pipe(fs.createWriteStream('./other-file')) 55 | ``` 56 | 57 | --- 58 | ## Basics 59 | [ Demo 1 ] 60 | 61 | --- 62 | ## Basics 63 | 4 types of streams 64 | - read: data can be read from 65 | - write: data can be written to 66 | - duplex: data can be read from and written to 67 | - transform: data can be written to, 68 | transformed and then read from 69 | 70 | --- 71 | ## Basics 72 | 2 stream modes 73 | - default: operate on buffers and strings 74 | - objectMode: operate on anything 75 | 76 | --- 77 | ## Basics 78 | buffers! 79 | - binary data (octet) 80 | - allocated on the heap 81 | - different garbage collection 82 | - performant 83 | 84 | --- 85 | ## Basics 86 | Streams use events under the hood 87 | ```js 88 | const stream = require('readable-stream') 89 | 90 | // primitive .pipe() 91 | const stream1 = new stream.PassThrough() 92 | const stream2 = new stream.PassThrough() 93 | 94 | stream1.on('readable', function () { 95 | stream1.on('data', function (data) { 96 | stream2.write(data) 97 | }) 98 | stream1.on('end', function () { 99 | stream2.end() 100 | }) 101 | }) 102 | ``` 103 | 104 | --- 105 | ## Basics 106 | [ Demo 2 ] 107 | 108 | --- 109 | ## Basics 110 | Read -> transform -> write 111 | ```sh 112 | $ cat ./my-file | grep 'foo' 113 | ``` 114 | ```js 115 | const through = require('through2') 116 | const fs = require('fs') 117 | 118 | const rs = fs.createReadStream('./my-file') 119 | const ts = grep(/foo/) 120 | const ws = process.stdout 121 | rs.pipe(ts).pipe(ws) 122 | 123 | function grep (regex) { 124 | return through(function (chunk, enc, cb) { 125 | if (regex.test(String(chunk))) this.push(chunk) 126 | cb() 127 | }) 128 | } 129 | ``` 130 | 131 | --- 132 | ## Basics 133 | [ Demo 3 ] 134 | 135 | --- 136 | ## Async 137 | Deferred streams (performant promise alternative) 138 | ```js 139 | const stream = require('stream') 140 | const fs = require('fs') 141 | 142 | function myAsyncFn () { 143 | const pts = new stream.PassThrough() 144 | 145 | process.nextTick(function () { 146 | const rs = fs.createReadStream('foobar.jpg') 147 | rs.pipe(pts) 148 | }) 149 | 150 | return pts 151 | } 152 | ``` 153 | 154 | --- 155 | ## Modules 156 | Event handling is cumbersome, modules make it better 157 | ```js 158 | // lets do a simple file copy 159 | const fs = require('fs') 160 | 161 | const rs = fs.createReadStream('./original.txt') 162 | const ws = fs.createWriteStream('./copy.txt') 163 | 164 | // use pump instead of rs.pipe(ws) 165 | pump(rs, ws, function (err) { 166 | if (err) return console.error('Copy error!', err) 167 | console.log('Copied successfully') 168 | }) 169 | ``` 170 | 171 | --- 172 | ## Modules 173 | HTTP servers! Write a file to the client 174 | ```js 175 | const http = require('http') 176 | const fs = require('fs') 177 | 178 | http.createServer((req, res) => { 179 | res.setHeader('Content-Type', 'text/css') 180 | fs.createReadStream().pipe(res) 181 | }).listen() 182 | ``` 183 | 184 | --- 185 | ## Modules 186 | [ Demo 4 ] 187 | 188 | --- 189 | ## Modules 190 | Databases! Scan a full db on each request 191 | ```js 192 | const level = require('level') 193 | const http = require('http') 194 | 195 | const db = level('/tmp/demo-db') 196 | 197 | http.createServer((req, res) => { 198 | db.createReadStream().pipe(res) 199 | }).listen() 200 | ``` 201 | 202 | --- 203 | ## Modules 204 | HTML templates! 205 | ```js 206 | const hyperstream = require('hyperstream') 207 | const http = require('http') 208 | 209 | http.createServer((req, res) => { 210 | const rs = fs.createReadStream('./index.html') 211 | const ts = hyperstream({ 212 | body: { _append: '

Hello World

' } 213 | }) 214 | rs.pipe(ts).pipe(res) 215 | }).listen() 216 | ``` 217 | 218 | --- 219 | ## Modules 220 | Torrents! 221 | ```js 222 | const torrentStream = require('torrent-stream') 223 | const path = require('path') 224 | const fs = require('fs') 225 | 226 | const engine = torrentStream('magnet:my-magnet-link') 227 | 228 | engine.on('ready', () => engine.files.forEach(file => { 229 | const outFile = path.join(__dirname, file.name) 230 | const rs = file.createReadStream() 231 | const ws = fs.createWriteStream(outFile) 232 | rs.pipe(ws) 233 | })) 234 | ``` 235 | 236 | --- 237 | ## Modules 238 | And much much more! 239 | - tar-stream (handle tar archives) 240 | - ssejson (server sent events) 241 | - pbs (protocol buffers) 242 | - response-stream (http) 243 | - tape (tests) 244 | - airswarm (local mesh networking) 245 | 246 | --- 247 | ## Recap 248 | - 4 types of streams 249 | - communicate using events 250 | - everything-as-a-stream 251 | - userland makes streams nice 252 | - there's a (stream) package for that 253 | 254 | --- 255 | ## Thank.pipe(you)! 256 | - twitter.com/yoshuawuyts 257 | - github.com/yoshuawuyts 258 | 259 | Slides available on 260 | - https://github.com/yoshuawuyts/talks/2015-10-pipe-stream-emit-listen 261 | - npm i -g tslide to view the slides 262 | -------------------------------------------------------------------------------- /2015-11-sydjs/proposal.md: -------------------------------------------------------------------------------- 1 | # pipe-emit-stream-listen 2 | Streams are a control flow abstraction native to node to read, transform and 3 | write data. Streams are composable, efficient and easy! Yes, really. In this 4 | talk Yosh will show you the exciting world of streams, and show you how you can 5 | include them in your next project. 6 | 7 | For organizers only: 8 | -------------------- 9 | Streams are one of Node's features developers are least familiar with, and 10 | that's sad because most of Node core's development is done with streams in 11 | mind. 12 | 13 | I'll mix introductory material with demo's (possibly WebRTC / LevelDB stuff) to 14 | keep it interesting for the full range of attendees. 15 | Hopefully it'll be enough to get people both excited for streams and enable 16 | them to continue on their own. 17 | -------------------------------------------------------------------------------- /2015-11-sydjs/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | nvim -p ./*.js 4 | -------------------------------------------------------------------------------- /2016-02-melb-nodejs/01_http.js: -------------------------------------------------------------------------------- 1 | const summary = require('server-summary') 2 | const toJson = require('body/json') 3 | const nano = require('nanomsg') 4 | const http = require('http') 5 | const pbuf = require('pbs') 6 | 7 | const addr = 'tcp://127.0.0.1:5556' 8 | 9 | const msg = pbuf(` 10 | message Climate { 11 | repeated Weather weather = 1; 12 | 13 | message Weather { 14 | required string city = 1; 15 | required uint32 temperature = 2; 16 | required string unit = 3; 17 | } 18 | } 19 | `) 20 | 21 | // encode / publish 22 | const encoder = msg.Climate.encode() 23 | const pub = nano.socket('pub') 24 | pub.bind(addr) 25 | encoder.pipe(pub) 26 | 27 | // decode / subscribe 28 | const decoder = msg.Climate.decode() 29 | const sub = nano.socket('sub') 30 | sub.connect(addr) 31 | sub.pipe(decoder) 32 | 33 | // worker function 34 | decoder.weather(function (w, cb) { 35 | const msg = 'Temperature in ' + w.city + 36 | ' is ' + w.temperature + ' degrees ' + w.unit 37 | console.log(msg) 38 | cb() 39 | }) 40 | 41 | // server 42 | const server = http.createServer(function (req, res) { 43 | toJson(req, res, function (err, data) { 44 | if (err) { 45 | res.statusCode = 404 46 | return res.end('Error: invalid JSON') 47 | } 48 | try { 49 | encoder.weather(data) 50 | res.end() 51 | } catch (e) { 52 | res.end(e.message) 53 | } 54 | }) 55 | }) 56 | server.listen('1337', summary(server, process.stdout)) 57 | -------------------------------------------------------------------------------- /2016-02-melb-nodejs/02_worker.js: -------------------------------------------------------------------------------- 1 | const nano = require('nanomsg') 2 | const pbuf = require('pbs') 3 | 4 | const addr = 'tcp://127.0.0.1:5556' 5 | 6 | const msg = pbuf(` 7 | message Climate { 8 | repeated Weather weather = 1; 9 | 10 | message Weather { 11 | required string city = 1; 12 | required uint32 temperature = 2; 13 | required string unit = 3; 14 | } 15 | } 16 | `) 17 | 18 | // decode / subscribe 19 | const decoder = msg.Climate.decode() 20 | const sub = nano.socket('sub') 21 | sub.connect(addr) 22 | sub.pipe(decoder) 23 | 24 | // worker function 25 | decoder.weather(function (w, cb) { 26 | const msg = 'Temperature in ' + w.city + 27 | ' is ' + w.temperature + ' degrees ' + w.unit 28 | console.log(msg) 29 | cb() 30 | }) 31 | -------------------------------------------------------------------------------- /2016-02-melb-nodejs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ a thousand tiny │██ 5 | │ messages │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-02-25 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello, I'm Yosh 16 | - unix 17 | - node 18 | - consulting 19 | - grumpy old man 20 | 21 | --- 22 | ## Building a distributed system 23 | - ye olde monolith architecture 24 | - shiny monolith architecture 25 | - protobufs 26 | - nanomsg 27 | - scalability patterns 28 | - demo time 29 | 30 | --- 31 | ## Ye olde monolith 32 | ```txt 33 | ┌─────────────────────────────┐ 34 | │ Client │ 35 | └────────┬────────────▲───────┘ 36 | ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ 37 | ┌────────▼────────────┴───────┐ 38 | │ JS blob │ 39 | └────────┬────────────▲───────┘ 40 | │ │ 41 | ┌────────▼────────────┴───────┐ 42 | │ DB │ 43 | └─────────────────────────────┘ 44 | ``` 45 | 46 | --- 47 | ## Ye olde monolith 48 | - works pretty well for small things 49 | - fast to build 50 | - internals are loosely defined 51 | - integration tests are easy 52 | - testing logic in isolation is hard 53 | - pretty rough to maintain (in JS) 54 | - pretty rough to split up (in JS) 55 | 56 | --- 57 | ## Shiny monolith 58 | ```txt 59 | ┌───────────────────────────────┐ 60 | │ Client │ 61 | └────────┬────────────▲─────────┘ 62 | ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ 63 | ┌────────▼────────────┴─────────┐ 64 | │ Public API │ 65 | └──┬───▲─────┬────▲──────┬───▲──┘ 66 | │ │ │ │ │ │ 67 | ┌──▼───┴──┐┌─▼────┴──┐┌──▼───┴──┐ 68 | │ Service ││ Service ││ Service │ 69 | └─────────┘└─────────┘└─────────┘ 70 | ``` 71 | 72 | --- 73 | ## Shiny monolith 74 | - internal RPC over TCP or Unix sockets 75 | - statically typed data through protobufs 76 | - easy to refactor 77 | - easy to split up 78 | 79 | --- 80 | ## Protobufs 81 | - way of encoding data 82 | - versioned 83 | - statically typed 84 | - fast 85 | - small 86 | - supports binary 87 | 88 | --- 89 | ## Protobufs 90 | ```proto 91 | message Company { 92 | required string name = 1; 93 | repeated Employee employees = 2; 94 | optional string country = 3; 95 | 96 | message Employee { 97 | required string name = 1; 98 | required uint32 age = 2; 99 | } 100 | } 101 | ``` 102 | 103 | --- 104 | ## Protobufs 105 | ```js 106 | const pbs = require('pbs') 107 | const fs = require('fs') 108 | 109 | const buf = fs.readFileSync(__dirname + 'company.proto') 110 | const messages = pbs(proto) 111 | 112 | const encoder = messages.Company.encode() 113 | const decoder = messages.Company.decode() 114 | ``` 115 | 116 | --- 117 | ## Nanomsg 118 | - way of transporting data 119 | - different scalability strategies 120 | - TCP / Unix socket / Websocket 121 | - complexity in patterns, not code 122 | - C lib - bindings to any lang 123 | - ~10Mb/s throughput for Node 124 | 125 | --- 126 | ## Nanomsg 127 | Client 128 | ```js 129 | const nano = require('nanomsg') 130 | 131 | const sub = nano.socket('sub') 132 | const addr = 'tcp://127.0.0.1:7789' 133 | sub.connect(addr) 134 | 135 | sub.pipe(process.stdout) 136 | ``` 137 | 138 | --- 139 | ## Nanomsg 140 | Server 141 | ```js 142 | const nano = require('nanomsg') 143 | 144 | const pub = nano.socket('pub') 145 | const addr = 'tcp://127.0.0.1:7789' 146 | pub.bind(addr) 147 | 148 | pub.send('Hello from nanomsg') 149 | ``` 150 | 151 | --- 152 | ## Scalability patterns 153 | All relationships ever: 154 | - one to one 155 | - many to one 156 | - one to many 157 | - many to many 158 | 159 | --- 160 | ## Scalability patterns 161 | - pair (1:1) 162 | - req-res (n:1) 163 | - pub-sub (1:n) 164 | - pipeline, push-pull (1:n) 165 | - bus (n:n) 166 | - surveyor-respondent (1:n) 167 | 168 | --- 169 | ## Scalability patterns 170 | Sync pub-sub 171 | ```txt 172 | ┌───────────┐ 173 | │ Publisher │ 174 | ├─────┬─────┤ 175 | │ REP │ PUB │ 176 | └▲──┬─┴──┬──┘ 177 | 1 2 3 178 | ┌┴──▼─┬──▼──┐ 179 | │ REQ │ SUB │ 180 | ├─────┴─────┤ 181 | │Subscriber │ 182 | └───────────┘ 183 | ``` 184 | 185 | --- 186 | ## Scalability patterns 187 | Required reading(!) 188 | - http://zguide.zeromq.org/page:all 189 | 190 | --- 191 | ## Demo time 192 | [ demo time ] 193 | 194 | --- 195 | ## message Thank { required string You = 1; } 196 | - twitter.com/yoshuawuyts 197 | - github.com/yoshuawuyts 198 | 199 | - zguide.zeromq.org/page:all 200 | - github.com/mafintosh/pbs 201 | - github.com/nickdesaulniers/node-nanomsg 202 | 203 | Slides available on 204 | - github.com/yoshuawuyts/talks/2016-02-melb-nodejs 205 | - npm i -g tslide to view the slides 206 | -------------------------------------------------------------------------------- /2016-02-melb-nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2016-02-melb-nodejs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "01_http.js", 6 | "scripts": { 7 | "start": "node 01_http | garnish", 8 | "worker": "node 02_worker" 9 | }, 10 | "author": "Yoshua Wuyts ", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body": "^5.1.0", 14 | "garnish": "^5.0.1", 15 | "nanomsg": "^3.1.0", 16 | "pbs": "^1.3.2", 17 | "server-summary": "^5.0.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /2016-02-melbjs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ virtual-what? │██ 5 | │ │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-02-10 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello, I'm Yosh 16 | - unix 17 | - node 18 | - consulting 19 | - grumpy old man 20 | 21 | --- 22 | ## Another stack 23 | - state of the stack 24 | - why something else 25 | - concepts 26 | - components 27 | - stuff it doesn't do 28 | 29 | --- 30 | ## State of the stack 31 | - react 32 | - redux 33 | - react-router 34 | - redux router 35 | - history.js 36 | - postcss 37 | - css-modules 38 | - webpack 39 | 40 | --- 41 | ## Why something else 42 | - control 43 | - file size 44 | - integration 45 | - opinions 46 | 47 | --- 48 | ## Concepts 49 | MVC 50 | - separation of data, logic and representation 51 | - can be interpreted in different ways 52 | - minimum viable separation 53 | 54 | --- 55 | ## Concepts 56 | ```txt 57 | ┌───────┐ ┌──────────┐ ┌──────┐ 58 | │ │ │ │ │ │ 59 | │ │ │ │ │ │ 60 | │ │ │ │ │ │ 61 | │ ◀──│Controller│◀──┤ │ 62 | │ │ │ │ │ │ ┌────┐ 63 | │ Model │ │ │ │ View │◀──▶│User│ 64 | │ │ │ │ │ │ └────┘ 65 | │ │ └──────────┘ │ │ 66 | │ │ │ │ 67 | │ ├─────────────────▶ │ 68 | │ │ │ │ 69 | └───────┘ └──────┘ 70 | ``` 71 | 72 | --- 73 | ## Concepts 74 | View 75 | - representation of what the user sees 76 | - hooks to said interface 77 | - responds to change in state 78 | - no logic! 79 | - no state! 80 | 81 | --- 82 | ## Concepts 83 | ```txt 84 | ┌───────┐ ┌──────────┐ ┌──────┐ 85 | │ │ │ │ │ │ 86 | │ │ │ │ │ │ 87 | │ │ │ │ │ │ 88 | │ ◀──│Controller│◀──┤ │ 89 | │ │ │ │ │ │ ┌────┐ 90 | │ Model │ │ │ │ View │◀──▶│User│ 91 | │ │ │ │ │ │ └────┘ 92 | │ │ └──────────┘ │ │ 93 | │ │ │ │ 94 | │ ├─────────────────▶ │ 95 | │ │ │ │ 96 | └───────┘ └──────┘ 97 | ``` 98 | 99 | --- 100 | ## Concepts 101 | Model 102 | - holds all state 103 | - representation of data 104 | - no state anywhere else, ever\* 105 | - is modified by controllers 106 | - no logic! 107 | 108 | --- 109 | ## Concepts 110 | ```txt 111 | ┌───────┐ ┌──────────┐ ┌──────┐ 112 | │ │ │ │ │ │ 113 | │ │ │ │ │ │ 114 | │ │ │ │ │ │ 115 | │ ◀──│Controller│◀──┤ │ 116 | │ │ │ │ │ │ ┌────┐ 117 | │ Model │ │ │ │ View │◀──▶│User│ 118 | │ │ │ │ │ │ └────┘ 119 | │ │ └──────────┘ │ │ 120 | │ │ │ │ 121 | │ ├─────────────────▶ │ 122 | │ │ │ │ 123 | └───────┘ └──────┘ 124 | ``` 125 | 126 | --- 127 | ## Concepts 128 | Controllers 129 | - stateless 130 | - jus' modifies state 131 | - responds to events from view 132 | - no state! 133 | 134 | --- 135 | ## Concepts 136 | ```txt 137 | ┌───────┐ ┌──────────┐ ┌──────┐ 138 | │ │ │ │ │ │ 139 | │ │ │ │ │ │ 140 | │ │ │ │ │ │ 141 | │ ◀──│Controller│◀──┤ │ 142 | │ │ │ │ │ │ ┌────┐ 143 | │ Model │ │ │ │ View │◀──▶│User│ 144 | │ │ │ │ │ │ └────┘ 145 | │ │ └──────────┘ │ │ 146 | │ │ │ │ 147 | │ ├─────────────────▶ │ 148 | │ │ │ │ 149 | └───────┘ └──────┘ 150 | ``` 151 | 152 | --- 153 | ## Components 154 | - virtual-app 155 | - hyperx 156 | - sheetify 157 | - sheet-router 158 | - xtend 159 | - browserify 160 | 161 | --- 162 | ## Components 163 | [ ~~ demo ~~ ] 164 | 165 | --- 166 | ## Components 167 | Views 168 | - inline styles (like css) 169 | - inline templates (like html) 170 | - bindings to the controllers 171 | 172 | --- 173 | ## Components 174 | ```js 175 | function errMain (params, app, state) { 176 | const prefix = sf` 177 | span { color: red } 178 | ` 179 | 180 | return hx` 181 | 184 | ` 185 | } 186 | ``` 187 | 188 | --- 189 | ## Components 190 | [ note to self: show sheetify v4 README ] 191 | 192 | --- 193 | ## Components 194 | Model 195 | - virtual-app 196 | - xtend 197 | 198 | --- 199 | ## Components 200 | Model 201 | ```js 202 | function modifyState (action, state) { 203 | if (action.type === 'increment') { 204 | return xtend(state, { count: state.count + 1 }) 205 | } 206 | if (action.type === 'decrement') { 207 | return xtend(state, { count: state.count - 1 }) 208 | } 209 | } 210 | ``` 211 | 212 | --- 213 | ## Stuff it doesn't do 214 | - no animations 215 | - no config-to-code 216 | - not newcomer friendly 217 | - not popular (yet?) 218 | 219 | --- 220 | ## Recap 221 | - there is a parallel universe 222 | - build your own is cool 223 | - unix is hard tho 224 | - it's all about tradeoffs 225 | 226 | --- 227 | ## h('thank.you', '!') 228 | - twitter.com/yoshuawuyts 229 | - github.com/yoshuawuyts 230 | 231 | Slides available on 232 | - https://github.com/yoshuawuyts/talks/2015-02-2016-02-melbjs 233 | - npm i -g tslide to view the slides 234 | -------------------------------------------------------------------------------- /2016-03-melbcss/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ modular stylesheets │██ 5 | │ with sheetify │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-02-25 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello, I'm Yosh 16 | - unix 17 | - node 18 | - consulting 19 | - grumpy old man 20 | 21 | --- 22 | ## Sheetify 23 | Today in practical sheetify: 24 | - design goals 25 | - lil overview 26 | - problem showcase 27 | - sheetify vs other software 28 | 29 | --- 30 | ## Design goals 31 | - leverage npm for stylesheets 32 | - don't break the CSS spec 33 | - simplify OOCSS 34 | - flexibility through plugins 35 | 36 | --- 37 | ## Lil overview 38 | ```js 39 | const hx = require('hyperx')(require('virtual-dom').h) 40 | const sf = require('sheetify') 41 | 42 | const prefix = sf` 43 | h1 { 44 | text-align: center; 45 | } 46 | ` 47 | const tree = hx` 48 |
49 |

My beautiful, centered title

50 |
51 | ` 52 | ``` 53 | 54 | --- 55 | ## Lil overview 56 | ```sh 57 | $ browserify -t sheetify/transform index.js > bundle.js 58 | ``` 59 | 60 | --- 61 | ## Lil overview 62 | ```css 63 | ._60ed23e .h1 { text-align: center; } 64 | ``` 65 | ```html 66 |
67 |

My beautiful, centered title

68 |
69 | ``` 70 | 71 | --- 72 | ## Lil overview 73 | ```sh 74 | $ browserify index.js \ 75 | -t [ sheetify/transform -o bundle.css ] \ 76 | > bundle.js 77 | ``` 78 | 79 | --- 80 | ## Demos 81 | - Q: How do I style host elements? 82 | - A: [demo 1] 83 | 84 | --- 85 | ## Demos 86 | - Q: How do I reuse styles from npm? 87 | - A: [demo 2] 88 | 89 | --- 90 | ## Demos 91 | - Q: How do I define global styles? 92 | - A: [demo 3] 93 | 94 | --- 95 | ## Sheetify vs SASS 96 | - whole different language 97 | - compiled output is quite big 98 | - gap between components and styles 99 | - no npm support 100 | 101 | --- 102 | ## Sheetify vs CSS-Modules 103 | - external files vs inline 104 | - both use namespaces 105 | - both based on PostCSS 106 | - introduces new syntax 107 | - slightly different philosophy 108 | 109 | --- 110 | ## Sheetify vs React Styles 111 | - both inline 112 | - objects vs CSS 113 | - sets properties on elements 114 | - camelcasing breaks the spec 115 | - kinda locked in hey 116 | 117 | --- 118 | ## Future 119 | e.g. next 2 weeksish 120 | - incremental rebuilds 121 | - async plugin support 122 | - variable passing 123 | - debug mode? 124 | - bugfixes! 125 | 126 | --- 127 | ## Recap 128 | - quick inline styles 129 | - externalizes to file or stream 130 | - quite flexible 131 | - plays ball with npm 132 | 133 | --- 134 | ## .thank { content: 'you'; } 135 | - twitter.com/yoshuawuyts 136 | - github.com/yoshuawuyts 137 | 138 | - github.com/sheetify/sheetify 139 | 140 | Slides available on 141 | - github.com/yoshuawuyts/talks/2016-03-melbcss 142 | - npm i -g tslide to view the slides 143 | -------------------------------------------------------------------------------- /2016-03-melbcss/demo-1.js: -------------------------------------------------------------------------------- 1 | const vdom = require('virtual-dom') 2 | const hyperx = require('hyperx') 3 | const sf = require('sheetify') 4 | 5 | const hx = hyperx(vdom.h) 6 | 7 | const prefix = sf` 8 | :host { 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | height: 100vh; 13 | width: 100vw; 14 | } 15 | 16 | h1 { 17 | font-family: sans-serif; 18 | } 19 | ` 20 | const tree = hx` 21 |
22 |

My beautiful, centered title

23 |
24 | ` 25 | document.body.appendChild(vdom.create(tree)) 26 | -------------------------------------------------------------------------------- /2016-03-melbcss/demo-2.js: -------------------------------------------------------------------------------- 1 | const vdom = require('virtual-dom') 2 | const hyperx = require('hyperx') 3 | const sf = require('sheetify') 4 | 5 | const hx = hyperx(vdom.h) 6 | 7 | sf('css-wipe') 8 | sf('css-type-base') 9 | 10 | const prefix = sf` 11 | :host { 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | height: 100vh; 16 | width: 100vw; 17 | } 18 | 19 | h1 { 20 | font-family: sans-serif; 21 | } 22 | ` 23 | 24 | const tree = hx` 25 |
26 |

My beautiful, centered title

27 |
28 | ` 29 | 30 | document.body.appendChild(vdom.create(tree)) 31 | -------------------------------------------------------------------------------- /2016-03-melbcss/demo-3.css: -------------------------------------------------------------------------------- 1 | section { 2 | background-color: grey; 3 | } 4 | -------------------------------------------------------------------------------- /2016-03-melbcss/demo-3.js: -------------------------------------------------------------------------------- 1 | const vdom = require('virtual-dom') 2 | const hyperx = require('hyperx') 3 | const sf = require('sheetify') 4 | 5 | const hx = hyperx(vdom.h) 6 | 7 | // section { background-color: grey; } 8 | const prefix = sf('./demo-3.css', { global: true }) 9 | 10 | const tree = hx` 11 |
12 |

My beautiful, centered title

13 |
14 | ` 15 | 16 | document.body.appendChild(vdom.create(tree)) 17 | -------------------------------------------------------------------------------- /2016-03-melbcss/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2016-03-melbcss", 3 | "version": "1.0.0", 4 | "description": "``` ┌─────────────────────────┐ │ │██ │ modular stylesheets │██ │ with sheetify │██ │ │██ │ Yoshua Wuyts │██ │ 2016-02-25 │██ │ │██ └─────────────────────────┘██ ███████████████████████████ ```", 5 | "main": "demo-1.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Yoshua Wuyts ", 10 | "license": "ISC", 11 | "browserify": { 12 | "transform": [ 13 | [ 14 | "sheetify/transform", 15 | { 16 | "use": [ ["sheetify-cssnext", { "sourcemap": false }] ] 17 | } 18 | ], 19 | "hyperxify" 20 | ] 21 | }, 22 | "dependencies": { 23 | "budo": "^8.0.4", 24 | "css-type-base": "^1.0.2", 25 | "css-wipe": "^4.1.2", 26 | "hyperx": "^1.3.1", 27 | "hyperxify": "^1.2.1", 28 | "insert-css": "^0.2.0", 29 | "sheetify": "^4.0.7", 30 | "sheetify-cssnext": "^1.0.7", 31 | "virtual-dom": "^2.1.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /2016-03-melbcss/proposal.md: -------------------------------------------------------------------------------- 1 | ## Talk title (even working-title so we can promote at the prior meetup) 2 | Modular stylesheets using Sheetify 3 | 4 | ## Talk description (1 paragraph about what people can expected to learn) 5 | Maintaining Stylesheets can be tricky. In this talk Yosh will show off what 6 | sheetify is, and how it helps solve some common problems in writing CSS. 7 | 8 | ## Talk estimated length 9 | 20 mins 10 | 11 | ## Company / job position (if you would like it listed) 12 | Contractor 13 | -------------------------------------------------------------------------------- /2016-04-pivotal-labs/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ Virtual no more │██ 5 | │ │██ 6 | │ Yoshua Wuyts │██ 7 | │ 2016-04-26 │██ 8 | │ │██ 9 | └─────────────────────────┘██ 10 | ███████████████████████████ 11 | ``` 12 | 13 | --- 14 | ## Hello, I'm Yosh 15 | - unix 16 | - node 17 | - consulting 18 | - grumpy old man 19 | 20 | --- 21 | ## Virtual no more 22 | - State of the stack 23 | - React, the good parts 24 | - What's next? 25 | 26 | --- 27 | ## State of the stack 28 | - jQuery 29 | - Backbone 30 | - Angular 31 | - React 32 | 33 | --- 34 | ## State of the stack 35 | - react 36 | - redux 37 | - react-router 38 | - webpack 39 | - bunch of boilerplate 40 | 41 | --- 42 | ## State of the stack 43 | > "What are all these words?" 44 | (Me, looking at every new JS framework) 45 | 46 | --- 47 | ## React, the good parts 48 | ```txt 49 | ┌───────┐ ┌─────────┐ ┌──────┐ 50 | │ │ │ │ │ │ 51 | │ │ │ │ │ │ 52 | │ │ │ │ │ │ 53 | │ ◀──│ Logic │◀──┤ │ 54 | │ │ │ │ │ │ ┌────┐ 55 | │ State │ │ │ │ View │◀──▶│User│ 56 | │ │ │ │ │ │ └────┘ 57 | │ │ └─────────┘ │ │ 58 | │ │ │ │ 59 | │ ├────────────────▶ │ 60 | │ │ │ │ 61 | └───────┘ └──────┘ 62 | ``` 63 | 64 | --- 65 | ## React, the good parts 66 | - unidirectional data flow 67 | - event-driven 68 | - data down, events up 69 | - renders on server and client 70 | 71 | --- 72 | ## What's next? 73 | - Keep React's good parts 74 | - Never be tied to a framework again 75 | 76 | --- 77 | ## What's next? 78 | Google (plus) 60kb challenge 79 | - < 60kb html 80 | - < 60kb css 81 | - < 60kb js 82 | 83 | --- 84 | ## What's next? 85 | - global 86 | - hyperx 87 | - morphdom 88 | - bel 89 | - yo-yo 90 | 91 | --- 92 | ## What's next? 93 | ```js 94 | const document = require('global/document') 95 | const el = document.createElement('div') 96 | // look ma, no browser 97 | ``` 98 | 99 | --- 100 | ## What's next? 101 | ```js 102 | const yo = require('yo-yo') 103 | const el = yo`
` 104 | // still no browser required, no es6 even 105 | ``` 106 | 107 | --- 108 | ## What's next? 109 | ```js 110 | const yo = require('yo-yo') 111 | const el = yo`
` 112 | 113 | function hc (ev) { 114 | // handle click 115 | } 116 | ``` 117 | 118 | --- 119 | ## What's next? 120 | ```js 121 | const tree = yo.update(oldNode, newNode) 122 | document.appendChild(tree) 123 | ``` 124 | 125 | --- 126 | ## What's next? 127 | - just DOM elements 128 | - works on the server 129 | - arbitrary architectures 130 | - not bound to any framework 131 | - be fast, be light 132 | 133 | --- 134 | ## 135 | - twitter.com/yoshuawuyts 136 | - github.com/yoshuawuyts 137 | 138 | Slides available on 139 | - https://github.com/yoshuawuyts/talks/2016-04-pivotal-labs 140 | - npm i -g tslide to view the slides 141 | -------------------------------------------------------------------------------- /2016-05-nodeconf-london/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-05-nodeconf-london/README.md -------------------------------------------------------------------------------- /2016-05-nodeconf-london/proposal.md: -------------------------------------------------------------------------------- 1 | # [build] pull-stream: the little module that could 2 | Node Streams are cool, but also hard to grok. Between all the different events, 3 | stream types, and modes, most devs get confused pretty easily. And that's a 4 | shame, because when streams are done right they provide seemless composition 5 | and great performance. 6 | 7 | What if we could keep the performance and composition, but make the interface 8 | simpler? That's what `pull-stream` is, and in this talk we'll work over how a 9 | tiny package can help you write code that lazily fetches data, provides robust 10 | error handling and frictionless composition at a fraction of the complexity of 11 | Node streams. 12 | 13 | ## A little bit more 14 | `pull-stream`s were thought up by Dominic Tarr who contributed majorly to early 15 | streams code. It's an implementation of the Node streams v2/v3 pull paradigm, 16 | optimized for simplicity (26loc!). In this talk we'll go over how Node streams 17 | came to be, the issues Node streams is currently facing and very hands-on 18 | knowledge on how to integrate `pull-stream` in projects. 19 | 20 | ## About me 21 | I'm a freelance software engineer who's been an active member of the Node.js 22 | community for the last years. I help maintain [numerous packages][npm], do a 23 | [fair amount of public speaking][talks] and have been involved with numerous 24 | [nodeschool][nodeschool] events across the world :herb: 25 | 26 | In recent times I've helped optimize `pull-stream`, created packages for the 27 | ecosystem and written about [streams][blog-streams] and 28 | [pull-stream][blog-pull]. 29 | 30 | - [twitter](https://twitter.com/yoshuawuyts) 31 | - [github](http://github.com/yoshuawuyts/) 32 | - [email](mailto:yoshuawuyts@gmail.com) 33 | 34 | [npm]: https://www.npmjs.com/~yoshuawuyts 35 | [blog-streams]: https://github.com/yoshuawuyts/knowledge/blob/master/js/streams.md 36 | [blog-pull]: https://medium.com/@yoshuawuyts/streams-in-node-ab9f13e15d5 37 | 38 | --- 39 | 40 | # [build] the anatomy of a Node server 41 | Modularity is the beating heart of Unix. By creating tiny composable tools, 42 | bigger things can be achieved. Discovering these tools is no trivial task 43 | though. As is the case in Node: if you're building servers without using 44 | frameworks, which packages should you use? 45 | 46 | Luckily there's a strong community of authors building, and maintaining 47 | packages that work around the common interface of `require('http')`. In this 48 | talk we'll work through the cream of the crop of what npm has to offer so you 49 | too can move away from big frameworks toward an assortment of packages 50 | optimized for your needs. 51 | 52 | ## A little bit more 53 | Unix is hard - it takes most people years to feel comfortable in the massive 54 | npm ecosystem. In this talk I want to provide people with the right handles so 55 | they too can transition away from large frameworks with confidence. In the talk 56 | we'll cover solutions for common use cases (domain composition, generic object 57 | storage, fail proof error handling, etc.) and alternative packages built for 58 | different trade-offs. 59 | 60 | ## About me 61 | I'm a freelance software engineer who's been an active member of the Node.js 62 | community for the last years. I help maintain [numerous packages][npm], do a 63 | [fair amount of public speaking][talks] and have been involved with numerous 64 | [nodeschool][nodeschool] events across the world :herb: 65 | 66 | I also curate a [big list of npm packages][packages]. 67 | 68 | - [twitter](https://twitter.com/yoshuawuyts) 69 | - [github](http://github.com/yoshuawuyts/) 70 | - [email](mailto:yoshuawuyts@gmail.com) 71 | 72 | [packages]: https://github.com/yoshuawuyts/knowledge/blob/master/js/packages.md 73 | 74 | --- 75 | 76 | [talks]: https://github.com/yoshuawuyts/talks 77 | [nodeschool]: http://nodeschool.io/ 78 | -------------------------------------------------------------------------------- /2016-05-nodeschool-tokyo/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ Choo - │██ 5 | │ The little framework │██ 6 | │ That Could │██ 7 | │ │██ 8 | │ Yoshua Wuyts │██ 9 | │ 2016-04-26 │██ 10 | │ │██ 11 | └─────────────────────────┘██ 12 | ███████████████████████████ 13 | ``` 14 | 15 | --- 16 | ## Hello, I'm Yosh 17 | - unix 18 | - node 19 | - consulting 20 | - grumpy old man 21 | 22 | --- 23 | ## Choo 24 | - State of the stack 25 | - Features 26 | - Usage 27 | - Concepts 28 | - What's next? 29 | 30 | --- 31 | ## State of the stack 32 | - React 33 | - Preact 34 | - Angular 35 | - Angular2 36 | 37 | --- 38 | ## State of the stack 39 | - React: 43kb + deps + JSX 40 | - Preact: 3kb + deps + JSX 41 | - Angular: 55.35kb + deps 42 | - Angular2: 135kb + deps + RxJS + typescript 43 | 44 | --- 45 | ## State of the stack 46 | And that's not even 47 | considering API surface 48 | 49 | --- 50 | ## Features 51 | Choo 🚂 🚋🚋🚋🚋🚋🚋 52 | - fun! 53 | - small bundle size (7kb) 54 | - small api surface 55 | - ELM architecture 56 | - built on prior tech 57 | - ship with everything you need 58 | 59 | --- 60 | ## Usage 61 | ```js 62 | const choo = require('choo') 63 | const app = choo() 64 | choo.router((route) => [ 65 | route('/', () => choo.view`

Hello Tokyo!

`) 66 | ]) 67 | document.body.appendChild(app.start()) 68 | ``` 69 | 70 | --- 71 | ## Usage 72 | Or in 140 characters: 73 | https://twitter.com/yoshuawuyts/status/733937424531750912 74 | ```js 75 | var c = require('choo') 76 | var a = choo() 77 | a.router(r => [ 78 | r('/', () => c.view`

Hello Tokyo!

`) 79 | ]) 80 | document.body.appendChild(a.start()) 81 | ``` 82 | 83 | --- 84 | ## Concepts 85 | ```txt 86 | ┌───────────────────────────┐ ┌────────┐ 87 | │ ┌─────────────────┐ │ │ User │ 88 | ├────│ Subscriptions │ │ └────────┘ 89 | │ ├─────────────────┤ │ │ 90 | └────│ Effects │◀───┤ ▼ 91 | ├─────────────────┤ Actions ┌────────┐ 92 | │ Reducers │◀───┴─────│ DOM │ 93 | Models──────────────┘ └────────┘ 94 | │ ▲ 95 | State DOM│tree 96 | ▼ │ 97 | ┌────────┐ ┌────────┐ 98 | │ Router │─────State ───▶│ Views │ 99 | └────────┘ └────────┘ 100 | ``` 101 | 102 | --- 103 | ## Concepts 104 | - view: inline HTML with click handlers 105 | - model: perform actions on data 106 | - action: object with a name and data 107 | - reducers: modify state 108 | - state: single object with all state 109 | 110 | --- 111 | ## Concepts 112 | Views 113 | ```js 114 | const attr = 'kawaiii' 115 | const view = choo.view` 116 |

You're super ${attr}

117 | ` 118 | ``` 119 | 120 | --- 121 | ## Concepts 122 | Models 123 | ```js 124 | const app = choo() 125 | app.model('api', { 126 | state: { count: 0 } 127 | reducers: { 128 | increment: function (state, action) { 129 | return { count: count += 1 } 130 | } 131 | } 132 | }) 133 | // then `send('api:increment')` 134 | ``` 135 | 136 | --- 137 | ## Concepts 138 | Sending data 139 | ```js 140 | app.router((route) => [ 141 | route('/', (params, state, send) choo.view` 142 | send('api:increment')}> 143 | Click me 144 | 145 | `) 146 | ]) 147 | app.start() 148 | ``` 149 | 150 | --- 151 | ## Concepts 152 | For async: 153 | - use effects to do perform side effects 154 | - side effects are things like HTTP requests 155 | - use subscriptions to listen to data 156 | - like listening to keyboard events 157 | - or listening to websockets 158 | 159 | --- 160 | ## Demos! 161 | [ mailbox ] 162 | 163 | --- 164 | ## What's next? 165 | - server side rendering (today!) 166 | - optional packages (websockets, SSE, markdown) 167 | - unit tests? 168 | - more examples! 169 | 170 | --- 171 | ## thank you! 172 | - twitter.com/yoshuawuyts 173 | - github.com/yoshuawuyts 174 | 175 | Slides available on 176 | - https://github.com/yoshuawuyts/talks/2016-05-nodeschool-tokyo 177 | - npm i -g tslide to view the slides 178 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ Tiny messages for │██ 5 | │ big architectures │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-06-05 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello, I'm Yosh 16 | - unix 17 | - node 18 | - consulting 19 | - mad engineering 20 | 21 | --- 22 | ## Tiny messages for big architectures 23 | - Let's chat about big systems 24 | - , what makes them complex 25 | - , and how to make them un-complex 26 | 27 | --- 28 | ## What makes systems complex? 29 | So what's a big system? 30 | - several people working together 31 | - on a bunch of processes that continously 32 | exchange data 33 | - that may or may not live on the same machine 34 | 35 | --- 36 | ## What makes systems complex? 37 | Macro scale understanding: 38 | - be aware of all moving parts of a system 39 | - know what they do 40 | - and know how they connect to each other 41 | 42 | --- 43 | ## What makes systems complex? 44 | Black box programming: 45 | - the interface of a program is known 46 | - implementation details don't leak 47 | - like the good packages in Node 48 | - which reduces cognitive overhead 49 | 50 | --- 51 | ## What makes systems complex? 52 | Homogenic interfaces: 53 | - the interface is the same regardless of situation 54 | - like plan9 files everywhere 55 | - sometimes less than ideal fit 56 | - but introduces shared terminology 57 | - and moves programs closer to lego 58 | 59 | --- 60 | ## What makes systems complex? 61 | - services are getting smaller 62 | - team size / composition morphs 63 | - everything is written in dynamic langs 64 | - technical debt for the sake of progress 65 | 66 | --- 67 | ## What makes systems complex? 68 | ```txt 69 | ┌─────────────────────────────────┐ 70 | │ Everyone knows that debugging │ 71 | │ is twice as hard as writing a │ 72 | │ program in the first place. │ 73 | │ │ 74 | │ So if you're as clever as you │ 75 | │ can be when you write it, how │ 76 | │ will you ever debug it? │ 77 | └─────────────────────────────────┘ 78 | - Brian Kernighan 79 | ``` 80 | 81 | --- 82 | ## What makes systems complex? 83 | ```txt 84 | ┌──────────────────────────┐ 85 | │ Reverse engineering is │ 86 | │ the root of all dev │ 87 | │ time consumption │ 88 | └──────────────────────────┘ 89 | ``` 90 | 91 | --- 92 | ## What is making systems complex? 93 | Ye olde monolith: 94 | ```txt 95 | ┌─────────────────────────────┐ 96 | │ Client │ 97 | └────────┬────────────▲───────┘ 98 | ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ 99 | ┌────────▼────────────┴───────┐ 100 | │ JS blob │ 101 | └────────┬────────────▲───────┘ 102 | │ │ 103 | ┌────────▼────────────┴───────┐ 104 | │ DB │ 105 | └─────────────────────────────┘ 106 | ``` 107 | 108 | --- 109 | ## What is making systems complex? 110 | Old monolith architecture: 111 | - fast to build 112 | - implicit internal interfaces 113 | - testing logic in isolation is hard 114 | - rough to split up and maintain 115 | 116 | --- 117 | ## Uncomplexify 118 | Shiny monolith: 119 | ```txt 120 | ┌───────────────────────────────┐ 121 | │ Client │ 122 | └────────┬────────────▲─────────┘ 123 | ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ 124 | ┌────────▼────────────┴─────────┐ 125 | │ Public API │ 126 | └──┬───▲─────┬────▲──────┬───▲──┘ 127 | │ │ │ │ │ │ 128 | ┌──▼───┴──┐┌─▼────┴──┐┌──▼───┴──┐ 129 | │ Service ││ Service ││ Service │ 130 | └─────────┘└─────────┘└─────────┘ 131 | ``` 132 | 133 | --- 134 | ## Uncomplexify 135 | Shiny monolith: 136 | - internal RPC over TCP 137 | - statically typed data through protobufs 138 | - easy to refactor 139 | - easy to split up 140 | 141 | --- 142 | ## Uncomplexify 143 | So how do we combat system complexity? 144 | - define common patterns for connecting systems 145 | - statically typed data between systems 146 | - RPC over TCP\* 147 | 148 | --- 149 | ## Uncomplexify 150 | So what are the patterns to connect our systems? 151 | - RPC (n:1) 152 | - Message queue (1:n) 153 | - PubSub (1:n) 154 | 155 | --- 156 | ## Uncomplexify 157 | Request - Reply (n:1) 158 | ```txt 159 | ┌──────────┐ 160 | │ Client │ 161 | ├──────────┤ 162 | │ REQ │ 163 | └──┬────▲──┘ 164 | │ │ 165 | Hello │ │ World 166 | │ │ 167 | ┌──▼────┴──┐ 168 | │ REP │ 169 | ├──────────┤ 170 | │ Server │ 171 | └──────────┘ 172 | ``` 173 | 174 | --- 175 | ## Uncomplexify 176 | Push - Pull (1:n) 177 | ```txt 178 | ┌──────────┐ 179 | │ Push │ 180 | └──────────┘ 181 | Tasks 182 | ┌──────────────┼──────────────┐ 183 | │ │ │ 184 | ┌─────▼────┐ ┌─────▼────┐ ┌─────▼────┐ 185 | │ PULL │ │ PULL │ │ PULL │ 186 | └──────────┘ └──────────┘ └──────────┘ 187 | ``` 188 | 189 | --- 190 | ## Uncomplexify 191 | Push - Pull (1:n:1) 192 | ```txt 193 | ┌──────────┐ 194 | │ Push │ 195 | └──────────┘ 196 | Tasks 197 | ┌──────────────┼──────────────┐ 198 | │ │ │ 199 | ┌─────▼────┐ ┌─────▼────┐ ┌─────▼────┐ 200 | │ PULL │ │ PULL │ │ PULL │ 201 | ├──────────┤ ├──────────┤ ├──────────┤ 202 | │ PUSH │ │ PUSH │ │ PUSH │ 203 | └──────────┘ └──────────┘ └──────────┘ 204 | │ │ │ 205 | └──────────────┼───────────────┘ 206 | Results 207 | ┌─────▼────┐ 208 | │ PULL │ 209 | └──────────┘ 210 | ``` 211 | 212 | --- 213 | ## Uncomplexify 214 | Pubblish - Subscribe (1:n) 215 | ```txt 216 | ┌──────────┐ 217 | │ PUB │ 218 | └──────────┘ 219 | │ 220 | ┌──────────────┼──────────────┐ 221 | │ │ │ 222 | ┌─────▼────┐ ┌─────▼────┐ ┌─────▼────┐ 223 | │ SUB │ │ SUB │ │ SUB │ 224 | └──────────┘ └──────────┘ └──────────┘ 225 | ``` 226 | 227 | --- 228 | ## Uncomplexify 229 | But there's more, less used ones too 230 | - req-res (n:1) 231 | - pub-sub (1:n) 232 | - push-pull (1:n) 233 | - pair (1:1) 234 | - bus (n:n) 235 | - surveyor-respondent (1:n) 236 | 237 | --- 238 | ## Uncomplexify 239 | So what about protocols? 240 | 241 | --- 242 | ## Uncomplexify 243 | JSON over HTTP 244 | - human-readable 245 | - native to JS 246 | - very debuggable 247 | - dynamic 248 | - kinda big 249 | - non-versioned 250 | 251 | --- 252 | ## Uncomplexify 253 | Protobuf (and derivatives) over HTTP2 254 | - binary 255 | - C / C++ 256 | - hah, debugging 257 | - statically typed(!) 258 | - oh yeah it's small alright 259 | - versioned(!) 260 | 261 | --- 262 | ## Uncomplexify 263 | ```protobuf 264 | enum FOO { 265 | BAR = 1; 266 | } 267 | 268 | message Test { 269 | required float num = 1; 270 | required string payload = 2; 271 | } 272 | 273 | message AnotherOne { 274 | repeated FOO list = 1; 275 | } 276 | ``` 277 | 278 | --- 279 | ## Uncomplexify 280 | - FOO is an enumeration of possible values 281 | - AnotherOne holds many FOO 282 | - Test has a num and payload 283 | 284 | --- 285 | ## Uncomplexify 286 | Upgrading Protobuf goes like: 287 | ```protobuf 288 | enum FOO { 289 | BAR = 1; 290 | } 291 | ``` 292 | ```protobuf 293 | enum FOO { 294 | BEEP = 2; 295 | } 296 | ``` 297 | 298 | --- 299 | ## Uncomplexify 300 | RPC Server 301 | ```js 302 | const http = require('http') 303 | const pump = require('pump') 304 | const pbs = require('pbs') 305 | const fs = require('fs') 306 | 307 | const schema = pbs(fs.readFileSync('./schema.proto')) 308 | http.createServer(function (req, res) { 309 | const decoder = schema.Test.decoder(console.log) 310 | pump(req, decoder, () => res.end()) 311 | }).listen(8080) 312 | ``` 313 | 314 | --- 315 | ## Uncomplexify 316 | RPC Client 317 | ```js 318 | const http = require('http') 319 | const pump = require('pump') 320 | const pbs = require('pbs') 321 | const fs = require('fs') 322 | 323 | const schema = pbs(fs.readFileSync('./schema.proto')) 324 | const encoder = schema.Test.encoder() 325 | 326 | const msg = encoder({ num: 2, payload: 'hey there' }) 327 | const req = http.request('http://localhost:8080', (err, res) => { 328 | console.log(`statusCode: ${res.statusCode}`) 329 | }) 330 | pump(msg, req) 331 | ``` 332 | 333 | --- 334 | ## Uncomplexify 335 | gRPC over HTTP2 336 | - like protobuf over HTTP2 337 | - custom status codes 338 | - helper methods 339 | - boilerplate generation 340 | - it's what Google does™ 341 | 342 | --- 343 | ## Uncomplexify 344 | Drawbacks of GRPC 345 | - constraints! 346 | - RPC not protocols 347 | - Node RPC interface / docs are not pleasant 348 | - non-http status code system 349 | - (but it's still kinda cool hey) 350 | 351 | --- 352 | ## Uncomplexify 353 | [ demo time? ] 354 | 355 | --- 356 | ## Uncomplexify 357 | Also: 358 | - json-schema is pretty good for JSON 359 | - There are no silver bullets 360 | 361 | --- 362 | ## Uncomplexify 363 | So how do we deploy this puppy? 364 | - shared repo just for schemas 365 | - `$ npm install -S ` 366 | - sprinkle semver on top 367 | - and greenkeeper! (<3) 368 | 369 | --- 370 | ## Uncomplexify 371 | Summary: 372 | - well-defined network topologies 373 | - static data structures 374 | - bounded systems 375 | 376 | --- 377 | ## message Thank { required string You = 1; } 378 | - twitter.com/yoshuawuyts 379 | - github.com/yoshuawuyts 380 | 381 | - zguide.zeromq.org/page:all 382 | - github.com/mafintosh/pbs 383 | - github.com/mafintosh/protocol-buffers 384 | 385 | Workshop on Sunday! 386 | 387 | Slides available on 388 | - github.com/yoshuawuyts/talks/2016-06-nodeconf-oslo 389 | - npm i -g tslide to view the slides 390 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/demo/client.js: -------------------------------------------------------------------------------- 1 | const http = require('http') 2 | const pbuf = require('protocol-buffers') 3 | const fs = require('fs') 4 | 5 | const schema = pbuf(fs.readFileSync('./schema.proto')) 6 | 7 | const req = http.request('http://localhost:8080') 8 | const message = schema.Test.encode({ 9 | num: 42, 10 | payload: 'Hello World' 11 | }) 12 | 13 | req.write(message) 14 | req.end() 15 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "client.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "Yoshua Wuyts ", 12 | "license": "ISC", 13 | "dependencies": { 14 | "pbs": "^1.3.2", 15 | "protocol-buffers": "^3.1.6", 16 | "pump": "^1.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/demo/schema.proto: -------------------------------------------------------------------------------- 1 | enum FOO { 2 | BAR = 1; 3 | } 4 | 5 | message Test { 6 | required float num = 1; 7 | required string payload = 2; 8 | } 9 | 10 | message AnotherOne { 11 | repeated FOO list = 1; 12 | } 13 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/demo/server.js: -------------------------------------------------------------------------------- 1 | const http = require('http') 2 | const pump = require('pump') 3 | const pbs = require('pbs') 4 | const fs = require('fs') 5 | 6 | const port = 8080 7 | const messages = pbs(fs.readFileSync('./schema.proto')) 8 | 9 | http.createServer(function (req, res) { 10 | const decoder = messages.Test.decode(function (msg) { 11 | console.log('msg: ', msg) 12 | }) 13 | pump(req, decoder) 14 | res.end() 15 | }).listen(port, () => console.log(`listening on port ${port}`)) 16 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/outline.md: -------------------------------------------------------------------------------- 1 | ## Goal of the talk 2 | We want to highlight the importance of statically defined data structures. It 3 | allows for code generation, but also provides us with the much-valued black-box 4 | analogy where we only have to care about interfaces. 5 | 6 | Patterns introduce well-defined constraints for applications. Zeromq / nanomsg 7 | introduced the concept of scalability patterns, which provide a set of common 8 | terminology to view the world through. By using the abstractions they 9 | introduce, it becomes possible to separate concerns in a distributed system, 10 | providing a system that can be understood on a macro scale. 11 | 12 | ## Questions 13 | 1. Why are big systems hard? (macro scale understanding, lack of black box, 14 | lack of homogenic interfaces) 15 | 2. Why should this be addressed right now? (microservices, docker, big systems 16 | using dynamic languages) 17 | 3. What do we want to do? (be able to seemlessly change parts of the 18 | application without influencing any of the other parts; black box 19 | programming) 20 | 4. solution is scalability patterns and statically typed SHOW OFF SCALABILITY 21 | PATTERNS 22 | 5. demo time - RPC using http2 and streaming protocol buffers, message queue 23 | using disqueue, perhaps gRPC? 24 | 25 | ## Answers 26 | 1. Loosely typed data and inter-system relations don't provide macro scale 27 | understanding for development teams - it encites reverse engineering on all 28 | fronts, and introduces high overhead for teams. 29 | 2. We're at the point where Node's getting into large production systems, with 30 | bigger and bigger teams and lots of micro services - massively relying on 31 | JSON / HTTP. Scaling is an afterthought, not something and often introducing 32 | scale as an afterthought, not as an initial design concern 33 | 3. Integration at the flick of a switch; scale by default; interfaces work as 34 | guarantees and can be tested against; rearchitecting and refactoring without 35 | any hurdles 36 | 4. Upfront complexity results in loss of speed; 37 | 38 | ## Sections 39 | 1. name the enemy 40 | 2. answer "why now?" 41 | 3. show the promised land before explaining how you'll get there 42 | 4. Identify obstacles—then explain how you’ll overcome them 43 | 5. Present evidence that you’re not just blowing hot air 44 | 45 | ## Overview 46 | - development in general 47 | - patterns 48 | - protocols 49 | - and how to apply this stuff for production 50 | - ITERATIVE DEVELOPMENT 51 | -------------------------------------------------------------------------------- /2016-06-nodeconf-oslo/proposal.md: -------------------------------------------------------------------------------- 1 | # tiny messages for big architectures 2 | Imagine a world where upgrading applications is seamless; where there are no 3 | gaps between the architecture that serves your first few users to the system 4 | that powers a million. 5 | 6 | Using `nanomsg`'s scalability protocols, seamless architecture becomes reality. 7 | In his talk Yosh will explain the philosophy of `nanomsg` and the patterns it 8 | employs to reliably architect software that scales. 9 | 10 | ----------------- 11 | ## A little bit more 12 | As a contractor most projects I've encountered have been built as monoliths, 13 | requiring great effort to refactor and unwrap into different services. I found 14 | there is usually a great divide between the initial (JS) application and the 15 | system that must be run on a cluster. Based on my experience I would like to 16 | talk about how, from the start of a project, scaling issues like this can be 17 | avoided. 18 | 19 | In this talk I'll demonstrate how the nanomsg sockets can be integrated into 20 | Node.js for both in-process and (networked) inter-process communication. At the 21 | end of the talk the audience should have a good understanding of the ideas 22 | underlying nanomsg, an overview of staple architecture patterns and the right 23 | resources to investigate further. 24 | 25 | ## About 26 | I'm a freelance software engineer who's been an active member of the Node.js 27 | community for a while. Apart from in-house training I've done a [fair amount of 28 | public speaking](https://github.com/yoshuawuyts/talks) and been involved with 29 | numerous [nodeschool](https://github.com/nodeschool) events in multiple 30 | cities :herb: 31 | 32 | - [twitter](https://twitter.com/yoshuawuyts) 33 | - [github](http://github.com/yoshuawuyts/) 34 | - [email](mailto:yoshuawuyts@gmail.com) 35 | -------------------------------------------------------------------------------- /2016-07-react-hamburg/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ Choo choo choo │██ 5 | │ │██ 6 | │ Yoshua Wuyts │██ 7 | │ 2016-07-14 │██ 8 | │ │██ 9 | └─────────────────────────┘██ 10 | ███████████████████████████ 11 | ``` 12 | 13 | --- 14 | ## Hello, I'm Yosh 15 | - unix 16 | - node 17 | - consulting 18 | - grumpy old man 👴 19 | 20 | --- 21 | ## Choo choo choo 22 | - what is choo? 23 | - trouble in framework land 24 | - featuring features 25 | - demos 26 | 27 | --- 28 | ## What is choo? 29 | - 5kb 30 | - batteries included 🔋 31 | - opinions for efficiency 32 | 33 | --- 34 | ## Trouble in framework land 35 | - upgrading aka peer dependencies 36 | 37 | --- 38 | ## Trouble in framework land 39 | - incarceration aka lock in 🔒 40 | 41 | --- 42 | ## Trouble in framework land 43 | - mom's spaghetti aka spaghetti 🍝 44 | 45 | --- 46 | ## Featuring features 47 | - perfedy perf 🎉 48 | 49 | --- 50 | ## Featuring features 51 | - views 👀 52 | 53 | --- 54 | ## Featuring features 55 | - models 💁 56 | 57 | --- 58 | ## Featuring features 59 | - namespaces & higher order effects 🎬 60 | 61 | --- 62 | ## Demo time 63 | [ only applicable if we've got internet ] 64 | - show the mailbox example 65 | - ehhh, show server side rendering because it's fast 66 | 67 | --- 68 | ## 69 | - twitter.com/yoshuawuyts 70 | - github.com/yoshuawuyts 71 | 72 | Slides available on 73 | - https://github.com/yoshuawuyts/talks/2016-07-react-hamburg 74 | - npm i -g tslide to view the slides 75 | -------------------------------------------------------------------------------- /2016-07-remote-meetup/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ Choo choo choo │██ 5 | │ │██ 6 | │ Yoshua Wuyts │██ 7 | │ 2016-07-19 │██ 8 | │ │██ 9 | └─────────────────────────┘██ 10 | ███████████████████████████ 11 | ``` 12 | 13 | --- 14 | ## Hello, I'm Yosh 15 | - unix 16 | - node 17 | - consulting 18 | - grumpy old man 👴 19 | 20 | --- 21 | ## Choo choo choo 22 | - what is choo? 23 | - trouble in framework land 24 | - featuring features 25 | - demos 26 | 27 | --- 28 | ## What is choo? 29 | - 5kb 30 | - batteries included 🔋 31 | - opinions for efficiency 32 | 33 | --- 34 | ## Trouble in framework land 35 | - upgrading aka peer dependencies 36 | 37 | --- 38 | ## Trouble in framework land 39 | - incarceration aka lock in 🔒 40 | 41 | --- 42 | ## Trouble in framework land 43 | - mom's spaghetti code 🍝 44 | 45 | --- 46 | ## Featuring features 47 | - perfedy perf 🎉 48 | 49 | --- 50 | ## Featuring features 51 | - views 👀 52 | 53 | --- 54 | ## Featuring features 55 | - models 💁 56 | 57 | --- 58 | ## Featuring features 59 | - namespaces & higher order effects 🎬 60 | 61 | --- 62 | ## Demo time 63 | [ only applicable if we've got time ] 64 | - show the mailbox example 65 | - ehhh, show server side rendering because it's fast 66 | 67 | --- 68 | ## 69 | - twitter.com/yoshuawuyts 70 | - github.com/yoshuawuyts 71 | 72 | Slides available on 73 | - https://github.com/yoshuawuyts/talks/2016-07-react-hamburg 74 | - npm i -g tslide to view the slides 75 | -------------------------------------------------------------------------------- /2016-07-remote-meetup/index.js: -------------------------------------------------------------------------------- 1 | const choo = require('choo') 2 | const html = require('choo/html') 3 | 4 | const app = choo() 5 | 6 | app.model({ 7 | state: { 8 | counter: 0 9 | }, 10 | reducers: { 11 | incr: (data, state) => ({ counter: state.counter + 1 }), 12 | decr: (data, state) => ({ counter: state.counter - 1 }) 13 | } 14 | }) 15 | 16 | // router 17 | app.router((route) => [ 18 | route('/', button) 19 | ]) 20 | 21 | const tree = app.start() 22 | document.body.appendChild(tree) 23 | 24 | // our v cute view 25 | function button (state, prev, send) { 26 | const counter = state.counter 27 | return html` 28 |
29 |

counter is ${counter}

30 | 31 | 32 |
33 | ` 34 | } 35 | 36 | -------------------------------------------------------------------------------- /2016-08-cascadiafest/proposal.md: -------------------------------------------------------------------------------- 1 | ### Talk Title 2 | pull-stream: the little module that could 3 | 4 | ### Description/Abstract 5 | Node Streams are cool, but hard to grok. Between all the different events, 6 | stream types, and modes, most devs get confused pretty easily. And that's a 7 | shame, because when streams are done right they provide seemless composition 8 | and great performance. 9 | 10 | What if we could keep the performance and composition, but make the interface 11 | simpler? That's what `pull-stream` does, and in this talk we'll go over how a 12 | tiny package can help you write code that lazily fetches data, provides robust 13 | error handling and frictionless composition at a fraction of the complexity of 14 | Node streams. 15 | 16 | ### Best Day 17 | Node Day 18 | 19 | ### Additional Talk Information 20 | Pull streams were thought up by Dominic Tarr who contributed majorly to early 21 | streams code. It's an implementation of the Node streams v2/v3 pull paradigm, 22 | optimized for simplicity (26loc!). In this talk we'll go over how Node streams 23 | came to be, the issues Node streams is currently facing and very hands-on 24 | knowledge on how to integrate `pull-stream` in projects. 25 | 26 | I've recently [helped refactor pull-stream][ps-refactor] to make it more 27 | efficient, have written guides on both [node streams][node-blog] and 28 | [pull-stream][ps-blog]. 29 | 30 | [ps-refactor]: https://github.com/dominictarr/pull-stream/commit/a2add3dd4addfb7ed5cd30977b8dd9bbfbbd86bf 31 | [node-blog]: https://github.com/yoshuawuyts/knowledge/blob/master/js/streams.md 32 | [ps-blog]: https://medium.com/@yoshuawuyts/streams-in-node-ab9f13e15d5 33 | 34 | --- 35 | ### Talk Title 36 | The anatomy of a Node server 37 | 38 | ### Description/Abstract 39 | Modularity is the beating heart of Unix. By creating tiny composable tools, 40 | bigger things can be achieved. Discovering these tools is no trivial task 41 | though. As is the case in Node: if you're building servers without using 42 | frameworks, which packages should you use? 43 | 44 | Luckily there's a strong community of authors building, and maintaining 45 | packages that work around the common interface of `require('http')`. In this 46 | talk we'll cover the aspects that make for a strong Node application and 47 | the packages that will help you achieve that. 48 | 49 | ### Best Day 50 | Node Day 51 | 52 | ### Additional Talk Information 53 | The goals of this talk are two-fold: first off I want to provide people with 54 | the right handles so they too can transition away from large frameworks with 55 | confidence. Secondly I want to highlight some of the lesser covered aspects of 56 | servers - such as (strongly typed) RPC, worker queues, discovery and 57 | documentation generation - and show people how this can be done elegantly and 58 | added to existing applications with little cost. 59 | 60 | In the past I've lead efforts to optimize one of the largest Node deployments 61 | of Australia, helping them move away from deeply coupled services to light 62 | services that were easy to profile and maintain. 63 | 64 | --- 65 | ### Talk Title 66 | virtual no more 67 | 68 | ### Description/Abstract 69 | The virtual-dom is everywhere. Originating from the game dev world and 70 | popularized by React, it's greatly impacted frontend development everywhere. 71 | But is it actually any good? In recent times arguments against using 72 | virtual-doms have grown. In this talk Yosh will walk you through the history of 73 | the virtual-dom, the patterns that underpin it and show what lies at the end of 74 | the road of frameworks. 75 | 76 | ### Best Day 77 | Browser Day 78 | 79 | ### Additional Talk Information 80 | In the last decade framework popularity started at jQuery, progressed through 81 | Backbone and Angular and arrived at React. Every iteration, everything has 82 | been rebuilt and existing logic has been thrown out with the bath water. It's 83 | not odd some people [express being fatigued][jsf]. 84 | 85 | Wouldn't it be nice if change was instigated not because we're pressured into 86 | it, but because we choose to? That is exactly what [bel][bae], [yo-yo][yo] and 87 | [morphdom][md] propose we do - by treating DOM nodes as the interface, we can 88 | finally liberate ourselves from frameworks and start creating the components we 89 | want, using the very best practices we've gathered over the years. 90 | 91 | I've been an early adopter of React, have a reasonable number of [virtual-dom 92 | components][avd], have been involved with the precursors of `yo-yo` 93 | ([base-element][be], [vel][vel]) and have [given talks][vw] about `virtual-dom` 94 | in the past. 95 | 96 | To my knowledge no prior talks about `yo-yo` and `bel` have been given at 97 | conferences before. 98 | 99 | [avd]: https://github.com/sethvincent/awesome-virtual-dom 100 | [vw]: https://github.com/yoshuawuyts/talks/blob/master/2016-02-melbjs/README.md 101 | [be]: https://github.com/shama/base-element 102 | [bae]: https://github.com/shama/bel 103 | [vel]: https://github.com/yoshuawuyts/vel 104 | [md]: https://github.com/patrick-steele-idem/morphdom 105 | [yo]: https://github.com/maxogden/yo-yo 106 | [jsf]: https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4 107 | [hx]: https://github.com/substack/hyperx 108 | -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/01_vanilla.js: -------------------------------------------------------------------------------- 1 | // bankai start --entry=01_vanilla.js 2 | const html = require('bel') 3 | 4 | const el = html` 5 |

6 | hello humans 7 |

8 | ` 9 | 10 | document.body.appendChild(el) 11 | -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/02_css.js: -------------------------------------------------------------------------------- 1 | // bankai start --entry=02_css.js 2 | const css = require('sheetify') 3 | const html = require('bel') 4 | 5 | const prefix = css` 6 | :host { 7 | font-size: 200px; 8 | } 9 | ` 10 | 11 | const el = html` 12 |

13 | hello you 14 |

15 | ` 16 | 17 | document.body.appendChild(el) 18 | -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ browserify │██ 5 | │ deep dive │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-09-16 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello I'm Yosh 16 | - heaps of npm packages 17 | - does JS for a living 18 | - computer opinions 19 | - 🚂🚃🚃🚃🚃🚃🚃 20 | - artisenal local human 21 | 22 | --- 23 | ## Browserify deep dive 24 | - yay browserify 25 | 26 | --- 27 | ## Browserify deep dive 28 | - YAY BROWSERIFY 29 | 30 | --- 31 | ## Browserify deep dive 32 | - intro 33 | - internals 34 | - ecosystem 35 | - wraps 36 | 37 | --- 38 | ## Intro 39 | ```txt 40 | ┌────────────────────────┐ 41 | │ │ 42 | │ Browserify is a │ 43 | │ (modular) javascript │ 44 | │ compiler │ 45 | │ │ 46 | └────────────────────────┘ 47 | ``` 48 | 49 | --- 50 | ## Intro 51 | But why talk about compilers? 52 | 53 | --- 54 | ## Intro 55 | ```txt 56 | ┌────────────────────────────┐ 57 | │ │ 58 | │ WE WILL KEEP COMPILING OUR │ 59 | │ CODE FOREVER │ 60 | │ (yay!) │ 61 | │ │ 62 | └────────────────────────────┘ 63 | ``` 64 | 65 | --- 66 | ## Intro 67 | ```txt 68 | ┌────────────────────────┐ 69 | │ │ 70 | │ Browserify is a │ 71 | │ (modular) javascript │ 72 | │ compiler │ 73 | │ │ 74 | └────────────────────────┘ 75 | ``` 76 | 77 | --- 78 | ## Intro 79 | - modular 80 | - pluggable with transforms and plugins 81 | - compiler because x -> y 82 | - super stable (unless you let me patch stuff) 83 | 84 | --- 85 | ## Intro 86 | ```sh 87 | $ browserify index.js > bundle.js 88 | ``` 89 | 90 | --- 91 | ## Intro 92 | ```js 93 | const browserify = require('browserify') 94 | browserify('./index.js') 95 | .bundle() 96 | .pipe(process.stdout) 97 | ``` 98 | 99 | --- 100 | ## Demo time 101 | [ browserify vanilla demo ] 102 | 103 | --- 104 | ## Internals 105 | - STREAMS EVERYWHERE 106 | 107 | --- 108 | ## Internals 109 | - create AST 110 | - apply local transform 111 | - apply global transforms 112 | - register require() calls 113 | - plugins can hook into any step 114 | 115 | --- 116 | ## Internals 117 | Registering a plugin into the pipeline 118 | ```js 119 | // run before the "label" step in browserify pipeline 120 | bundle.pipeline 121 | .get('label') 122 | .unshift(extractStream) 123 | ``` 124 | 125 | --- 126 | ## Internals 127 | Transforms v plugins 128 | - transforms operate on pieces of code 129 | - plugins operate on browserify itself 130 | 131 | --- 132 | ## Ecosystem 133 | ```txt 134 | ┌──────────────────────┐ 135 | │ │ 136 | │ There's a transform │ 137 | │ for that™ │ 138 | │ │ 139 | └──────────────────────┘ 140 | ``` 141 | 142 | --- 143 | ## Ecosystem 144 | E_TOO_MANY_THINGS 145 | - https://github.com/substack/node-browserify/wiki/list-of-transforms 146 | 147 | --- 148 | ## Ecosystem 149 | Optimizing 150 | - uglifyify 151 | - bundle-collapser 152 | - unassertify 153 | - exorcist 154 | 155 | --- 156 | ## Ecosystem 157 | Cool things 158 | - sheetify 159 | - brfs 160 | - bulkify 161 | - watchify 162 | - css-extract 163 | 164 | --- 165 | ## Wraps 166 | Development 167 | - budo 168 | - beefy 169 | - wzrd 170 | 171 | --- 172 | ## Wraps 173 | Optimizing 174 | - bundleify 175 | 176 | --- 177 | ## Wraps 178 | All of the above + deployment 179 | - bankai 180 | 181 | --- 182 | ## Demo time 183 | [ bankai demo ] 184 | (start and build) 185 | 186 | --- 187 | ## Bonus round 188 | Bankai! 189 | - code over configuration 190 | - dev mode for development 191 | - optimize mode for production 192 | - as a node module 193 | - as a CLI tool 194 | 195 | --- 196 | ## $ browserify thank.js > you.js 197 | - twitter.com/yoshuawuyts 198 | - github.com/yoshuawuyts 199 | 200 | Slides available on 201 | - https://github.com/yoshuawuyts/talks/2016-09-16-node-interactive-eu 202 | - npm i -g tslide to view the slides 203 | -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/dist/bundle.css: -------------------------------------------------------------------------------- 1 | ._3828f358 { 2 | font-size: 200px; 3 | } -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2016-09-node-interactive-eu", 3 | "version": "1.0.0", 4 | "description": "``` ┌─────────────────────────┐ │ │██ │ browserify │██ │ deep dive │██ │ │██ │ Yoshua Wuyts │██ │ 2016-09-16 │██ │ │██ └─────────────────────────┘██ ███████████████████████████ ```", 5 | "main": "01_vanilla.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "Yoshua Wuyts ", 11 | "license": "MIT", 12 | "dependencies": { 13 | "bel": "^4.4.3", 14 | "insert-css": "^1.0.0", 15 | "sheetify": "^5.1.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /2016-09-node-interactive-eu/proposal.md: -------------------------------------------------------------------------------- 1 | ## Diving deep into browserify 2 | Browserify has been one of the staple tools for packaging javascript and 3 | shipping it to the browser. In this talk Yosh will explain browserify's 4 | internals, the current state of tooling and the path that's currently set for 5 | the future. 6 | 7 | ## About Yosh 8 | Yosh is a freelance software developer who's always been fascinated by 9 | computers. He loves hacking and talking about shiny new computer things, riding 10 | his bike to places, writing stuff and buying clothes. 11 | 12 | - Name: Yoshua Wuyts 13 | -------------------------------------------------------------------------------- /2016-09-nodejs-berlin/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ browserify │██ 5 | │ deep dive │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-09-06 │██ 9 | │ │██ 10 | └─────────────────────────┘██ 11 | ███████████████████████████ 12 | ``` 13 | 14 | --- 15 | ## Hello I'm Yosh 16 | - tons of npm packages 17 | - does JS for a living 18 | - computer opinions 19 | - 🚂🚃🚃🚃🚃🚃🚃 20 | - not from here™ 21 | 22 | --- 23 | ## Browserify deep dive 24 | - yay browserify 25 | 26 | --- 27 | ## Browserify deep dive 28 | - YAY BROWSERIFY 29 | 30 | --- 31 | ## Browserify deep dive 32 | - intro 33 | - internals 34 | - ecosystem 35 | - wraps 36 | 37 | --- 38 | ## Intro 39 | ``` 40 | ┌────────────────────────┐ 41 | │ │ 42 | │ Browserify is a │ 43 | │ (modular) javascript │ 44 | │ compiler │ 45 | │ │ 46 | └────────────────────────┘ 47 | ``` 48 | 49 | --- 50 | ## Intro 51 | - modular 52 | - pluggable with transforms and plugins 53 | - compiler because x -> y 54 | - super stable (unless you let me patch stuff) 55 | 56 | --- 57 | ## Internals 58 | - STREAMS EVERYWHERE 59 | 60 | --- 61 | ## Internals 62 | - create AST 63 | - apply local transform 64 | - ueh, apply global transforms? 65 | - register require() calls 66 | - plugins can hook into any step 67 | 68 | --- 69 | ## Internals 70 | Transforms v plugins 71 | - transforms operate on pieces of code 72 | - plugins operate on browserify itself 73 | 74 | --- 75 | ## Ecosystem 76 | ``` 77 | ┌──────────────────────┐ 78 | │ │ 79 | │ There's a transform │ 80 | │ for that™ │ 81 | │ │ 82 | └──────────────────────┘ 83 | ``` 84 | 85 | --- 86 | ## Ecosystem 87 | E_TOO_MANY_THINGS 88 | - https://github.com/substack/node-browserify/wiki/list-of-transforms 89 | 90 | --- 91 | ## Ecosystem 92 | Optimizing 93 | - uglifyify 94 | - bundle-collapser 95 | - unassertify 96 | - exorcist 97 | 98 | --- 99 | ## Ecosystem 100 | Cool things 101 | - sheetify 102 | - brfs 103 | - bulkify 104 | - watchify 105 | 106 | --- 107 | ## Wraps 108 | Development 109 | - budo 110 | - beefy 111 | - wzrd 112 | 113 | --- 114 | ## Wraps 115 | Optimizing 116 | - bundleify 117 | 118 | --- 119 | ## Wraps 120 | All of the above + deployment 121 | - bankai 122 | 123 | --- 124 | ## Bonus round 125 | Bankai! 126 | - code over configuration 127 | - dev mode for development 128 | - optimize mode for production 129 | - as a node module 130 | - as a CLI tool 131 | 132 | --- 133 | ## browserify thank.js > you.js 134 | - twitter.com/yoshuawuyts 135 | - github.com/yoshuawuyts 136 | 137 | Slides available on 138 | - https://github.com/yoshuawuyts/talks/2016-09-nodejs-berlin 139 | - npm i -g tslide to view the slides 140 | -------------------------------------------------------------------------------- /2016-09-nodejs-berlin/proposal.md: -------------------------------------------------------------------------------- 1 | # diving deep into browserify 2 | Browserify has been one of the staple tools for packaging javascript and 3 | shipping it to the browser. In this talk Yosh will explain browserify's 4 | internals, the current state of tooling and the path that's currently set for 5 | the future. 6 | -------------------------------------------------------------------------------- /2016-10-nodeconf-eu/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ┌─────────────────────────┐ 3 | │ │██ 4 | │ towards a faster, │██ 5 | │ smaller web │██ 6 | │ │██ 7 | │ Yoshua Wuyts │██ 8 | │ 2016-10-19 │██ 9 | │ │██ 10 | │ [ epilepsia proof ] │██ 11 | │ │██ 12 | └─────────────────────────┘██ 13 | ███████████████████████████ 14 | ``` 15 | 16 | --- 17 | ## Hello I'm Yosh 18 | 19 | - heaps of npm packages 20 | - computer opinions 21 | - 🚂🚃🚃🚃🚃🚃🚃 22 | - workin on @dat_project 23 | - not a morning person 24 | 25 | --- 26 | ## So what we talkin 'bout today? 27 | 28 | - the web anno now 29 | - the pieces of perf 30 | - speeding it up 31 | 32 | --- 33 | ## So what we talkin 'bout today? 34 | 35 | - Warning ahead: The conclusions posted are 36 | subjective and not exact science™. It's 37 | cool if you take my word for things but 38 | always do your own research 39 | 40 | --- 41 | ``` 42 | ┌─────────────────────────┐ 43 | │ │██ 44 | │ The web anno now │██ 45 | │ │██ 46 | └─────────────────────────┘██ 47 | ███████████████████████████ 48 | ``` 49 | 50 | --- 51 | ## The web anno now 52 | 53 | This month in the web (10/2016): 54 | ``` 55 | Item | Avg Size | Avg call count 56 | ────────────────────────────────── 57 | HTML | 53kB | 10 calls 58 | CSS | 76kB | 7 calls 59 | JS | 410kB | 23 calls 60 | Fonts | 85kB | 3 calls 61 | Images | 1650kB | 57 calls 62 | Total | 2552kB | 107 calls 63 | ────────────────────────────────── 64 | ``` 65 | - [ source: http://httparchive.org/trends.php ] 66 | 67 | --- 68 | ## The web anno now 69 | 70 | This month in the web (10/2016): 71 | ``` 72 | Item | site % 73 | ──────────────────────────── 74 | HTML hosted on CDN | 20% 75 | HTTPS enabled | 34% 76 | Using compression | 75% 77 | Using custom fonts | 64% 78 | Cacheable resources | 47% 79 | ──────────────────────────── 80 | ``` 81 | - [ source: http://httparchive.org/trends.php ] 82 | 83 | --- 84 | ## The web anno now 85 | 86 | This month in the web (10/2016): 87 | ``` 88 | ┌─────────────────────────┐ 89 | │ 37 TCP connections │ 90 | │ on average │ 91 | └─────────────────────────┘ 92 | ``` 93 | 94 | --- 95 | ## The web anno now 96 | 97 | CSS of popular sites per 10/2016: 98 | ``` 99 | Site | Size | Rules | Selectors 100 | ──────────────────────────────────── 101 | Github | 647kB | 8153 | 9215 102 | Twitter | 643kB | 6990 | 9542 103 | Medium | 629kB | 3470 | 4484 104 | Facebook | 173kB | 2313 | 2875 105 | Tachyons | 71kB | 1810 | 1994 106 | Basscss | 14kB | 287 | 347 107 | ──────────────────────────────────── 108 | ``` 109 | - [ source: cssstats.com ] 110 | 111 | --- 112 | ## The web anno now 113 | ``` 114 | ┌─────────────────────────┐ 115 | │ │ 116 | │ The total size of the │ 117 | │ CSS language is about │ 118 | │ 20kB │ 119 | │ │ 120 | └─────────────────────────┘ 121 | ``` 122 | - [ Source: Adam Morse - Things I’ve Learned About CSS ] 123 | 124 | --- 125 | ## The web anno now 126 | ``` 127 | ┌──────────────────┐ 128 | │ Google AMP │ 129 | └──────────────────┘ 130 | ``` 131 | - instantly loaded, across the globe 132 | - "meh" UX but oh wow it's fast 133 | - also very much evil (!) 134 | - and that's cool, we probably need it 135 | 136 | --- 137 | ## The web anno now 138 | ``` 139 | ┌─────────────────────────┐ 140 | │ │ 141 | │ Google AMP exists │ 142 | │ because Goog couldn't │ 143 | │ get people to write │ 144 | │ fast things* │ 145 | │ │ 146 | └─────────────────────────┘ 147 | ``` 148 | * free interpretation of interactions 149 | with humans that work on AMP 150 | 151 | --- 152 | ``` 153 | ┌─────────────────────────┐ 154 | │ │██ 155 | │ The pieces of perf │██ 156 | │ │██ 157 | └─────────────────────────┘██ 158 | ███████████████████████████ 159 | ``` 160 | 161 | --- 162 | ## The pieces of perf 163 | ``` 164 | ┌──────────────────────────────┐ 165 | │ The next billion users │ 166 | └──────────────────────────────┘ 167 | 168 | - mostly running Android 169 | - have decent specs (1GB RAM, quad-core processors) 170 | - have an evergreen browser and WebView (Android 5+) 171 | - no reliable internet connection 172 | ``` 173 | - [ source: nolanlawson.com ] 174 | 175 | --- 176 | ## The pieces of perf 177 | ``` 178 | ┌────────────────────────────────┐ 179 | │ What are the pieces of perf? │ 180 | └────────────────────────────────┘ 181 | ``` 182 | 1. time spent on the network 183 | 2. time spent booting up 184 | 3. amount of tasks performed 185 | 4. distribution & priotization of tasks 186 | 5. perception of the processes above 187 | 188 | --- 189 | ## The pieces of perf 190 | ``` 191 | ┌────────────────────────────────┐ 192 | │ What are the pieces of perf │ 193 | │ on a per-resource basis? │ 194 | └────────────────────────────────┘ 195 | ``` 196 | 1. time spent on the network 197 | 2. time spent interpreting 198 | 3. time spent executing 199 | 200 | --- 201 | ## The pieces of perf 202 | ``` 203 | ┌────────────────────────────────┐ 204 | │ What are the pieces of perf? │ 205 | └────────────────────────────────┘ 206 | ``` 207 | - setup 208 | - main loop 209 | - perceived perf 210 | 211 | --- 212 | ## The pieces of perf 213 | ``` 214 | ┌────────────────────────────────┐ 215 | │ What are the pieces of perf? │ 216 | └────────────────────────────────┘ 217 | ``` 218 | - setup 219 | - network latency 220 | - asset size 221 | - caching 222 | - main loop 223 | - operation count 224 | - parallelism 225 | - task distribution 226 | - perceived perf 227 | - design 228 | - psychological trickery 229 | 230 | --- 231 | ## The pieces of perf 232 | ``` 233 | ┌────────────────────────────┐ 234 | │ Setup/network: Key Metrics │ 235 | └────────────────────────────┘ 236 | 237 | Item | Value 238 | ─────────────────────────── 239 | Speed of light | 3x10^8 240 | Ethernet packet | 1kb 241 | First TCP segment | 4kb 242 | TCP frame data cap | 60kb 243 | ``` 244 | - [ source: lots of googling ] 245 | 246 | --- 247 | ``` 248 | ┌─────────────────────────┐ 249 | │ │██ 250 | │ Speeding it up │██ 251 | │ │██ 252 | └─────────────────────────┘██ 253 | ███████████████████████████ 254 | ``` 255 | 256 | --- 257 | ## Speeding it up 258 | ``` 259 | ┌────────────────────────────┐ 260 | │ Setup/caching │ 261 | └────────────────────────────┘ 262 | ``` 263 | - Content Distribution Networks!! 264 | - put servers close to users 265 | - web 3.0 P2P apps will be 🆒 266 | - leverage browser caching (IDB, SvcWrk.) 267 | 268 | --- 269 | ## Speeding it up 270 | ``` 271 | ┌────────────────────────────┐ 272 | | Setup/assets: Styling │ 273 | └────────────────────────────┘ 274 | ``` 275 | - use new wave OOCSS (e.g. tachyons) 276 | - don't use custom fonts (e.g. 50kb / 3 req) 277 | - remember CSS, the language™ is 20kB 278 | - interpreting old, boring CSS is fast 279 | 280 | --- 281 | ## Speeding it up 282 | ``` 283 | ┌────────────────────────────┐ 284 | | Setup/assets: Images │ 285 | └────────────────────────────┘ 286 | ``` 287 | 1. don't use images 288 | 2. ??? (not my domain) 289 | 290 | --- 291 | ## Speeding it up 292 | ``` 293 | ┌─────────────────────────────┐ 294 | │ Setup/network: Bundles │ 295 | └─────────────────────────────┘ 296 | ``` 297 | - complete CSS spec is 20kb 298 | - zopfli is DEFLATE compat and ~10% smaller 299 | - brotli is new, ok supported and ~30% smaller 300 | - IE8+ targets have viable 5kb frameworks now 301 | - don't bundle in node core modules 302 | 303 | --- 304 | ## Speeding it up 305 | ``` 306 | ┌─────────────────────────────┐ 307 | │ Setup/network: Takewaways │ 308 | └─────────────────────────────┘ 309 | ``` 310 | - aim to render ASAP (1st packet perhaps?) 311 | - CSS/HTML/JS should be under 60kb (TCP cap) 312 | - HTTP2 provides header encoding 313 | - bandwidth and latency restraints always apply 314 | - hitting the network is a last resort 315 | 316 | --- 317 | ## Speeding it up 318 | ``` 319 | ┌─────────────────────────────┐ 320 | │ Setup: Javascript │ 321 | └─────────────────────────────┘ 322 | ``` 323 | - network 324 | - interpreting 325 | - execution (but we can minimize this) 326 | 327 | --- 328 | ## Speeding it up 329 | ``` 330 | ┌─────────────────────────────┐ 331 | │ Setup: Javascript │ 332 | └─────────────────────────────┘ 333 | ``` 334 | ```js 335 | // boring.js 336 | var foo = 3 + 2 337 | 338 | // with static-eval magic 339 | var foo = 5 340 | ``` 341 | 342 | --- 343 | ## Speeding it up 344 | ``` 345 | ┌─────────────────────────────┐ 346 | │ Setup: Javascript │ 347 | └─────────────────────────────┘ 348 | ``` 349 | - requires manual tailoring 350 | - it's basically macros 351 | - I wish we had macros 352 | - Babel team has done work for generic solution 353 | 354 | --- 355 | ## Speeding it up 356 | ``` 357 | ┌──────────────────────────────┐ 358 | │ Main loop: Operation count │ 359 | └──────────────────────────────┘ 360 | ``` 361 | - Garbage Collection pauses 😰 362 | - GC pauses 😰 363 | - GC 😰 364 | 365 | --- 366 | ## Speeding it up 367 | ``` 368 | ┌──────────────────────────────┐ 369 | │ Main loop: Operation count │ 370 | └──────────────────────────────┘ 371 | ``` 372 | - mutable > immutable 373 | - creating new Objects is expensive (!!!) 374 | - less operations is better 375 | - ES3 has quite predictable perf results 376 | - boring code is probably fast code 377 | 378 | --- 379 | ## Speeding it up 380 | ``` 381 | ┌──────────────────────────────┐ 382 | │ Main loop: Parallelism │ 383 | └──────────────────────────────┘ 384 | ``` 385 | - an average phone has 6-8 cores 386 | - JS by default uses 1 thread on 1 core 387 | - 60fps can be hard 388 | 389 | --- 390 | ## Speeding it up 391 | ``` 392 | ┌──────────────────────────────┐ 393 | │ Main loop: Parallelism │ 394 | └──────────────────────────────┘ 395 | ``` 396 | - offload work from the UI thread 397 | - use all the cores 398 | - not all objects can cross thread boundries 399 | - pretty experimental stuff, still 400 | - don't forget about the battery 401 | 402 | --- 403 | ## Speeding it up 404 | ``` 405 | ┌──────────────────────────────┐ 406 | │ Main loop: Others │ 407 | └──────────────────────────────┘ 408 | ``` 409 | - RequestAnimationFrame is amazing 410 | - debounce is like RAF but localized 411 | 412 | --- 413 | ``` 414 | ┌─────────────────────────┐ 415 | │ │██ 416 | │ Summary │██ 417 | │ │██ 418 | └─────────────────────────┘██ 419 | ███████████████████████████ 420 | ``` 421 | 422 | --- 423 | ## Summary 424 | 425 | - sites are pretty big today 426 | - we can make radical optimizations 427 | - hard constraints exist 428 | - almost every step can be optimized 429 | - GC pauses 😰 430 | 431 | --- 432 | ## Thanks y'all! 433 | 434 | - twitter.com/yoshuawuyts 435 | - github.com/yoshuawuyts 436 | 437 | Slides available on: 438 | - https://github.com/yoshuawuyts/talks/2016-10-nodeconf-eu 439 | - npm i -g tslide to view the slides 440 | -------------------------------------------------------------------------------- /2016-10-nodeconf-eu/notes.md: -------------------------------------------------------------------------------- 1 | ## topics 2 | - wire transfer cutoff points (tcp size, etc.) 3 | - https://github.com/davidmarkclements/does-it-fit 4 | 5 | - time to boot 6 | - mention sebmckg's work on inlining boot properties 7 | - mention shama's work on inlining hyperx 8 | 9 | - render thread / blocking non-blocking code 10 | - mention samccone's tweet about dumping on ui thread 11 | - mention nolawson's UI thread stuff 12 | -------------------------------------------------------------------------------- /2016-10-upfront/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-10-upfront/README.md -------------------------------------------------------------------------------- /2016-10-upfront/proposal.md: -------------------------------------------------------------------------------- 1 | # getting started with choo 2 | 3 | ## Summary 4 | "Performant" and "easy" are not mutually exclusive. In this talk yosh will 5 | explain how to go from writing plain HTML and CSS to running a clean 6 | unidirectional JavaScript app. No heavy frontend skills are needed, just a bit 7 | of knowledge on HTML, CSS and JS 🐝 8 | 9 | ## Bio 10 | Yosh is a creative engineer who loves all things computer, but loves hanging 11 | out even more. Current obsession is Rust and distributed systems, but he tends 12 | to do JS from time to time too. 13 | -------------------------------------------------------------------------------- /2016-11-dapphack/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/README.md -------------------------------------------------------------------------------- /2016-11-dapphack/dat.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #293648; 3 | font-family: 'Source Sans Pro', 'Helvetica Neue', 'Lucida Grande', Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #35B44F; 8 | text-decoration: none; 9 | } 10 | 11 | a:hover, 12 | a:focus { 13 | color: #24943A; 14 | } -------------------------------------------------------------------------------- /2016-11-dapphack/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2016-11-dapphack/in.js: -------------------------------------------------------------------------------- 1 | const normcore = require('normcore') 2 | 3 | const feed = normcore('hei') 4 | console.log(feed.key.toString('hex')) 5 | feed.append('hello') 6 | -------------------------------------------------------------------------------- /2016-11-dapphack/index.js: -------------------------------------------------------------------------------- 1 | const html = require('choo/html') 2 | const css = require('sheetify') 3 | 4 | css('tachyons') 5 | css('./dat.css') 6 | 7 | const slides = [ 8 | html` 9 |
10 |

11 | DAT 12 |

13 |

14 | Hyper technology 15 |

16 |

17 | [ @dat_project / @yoshuawuyts ] 18 |

19 |
20 | `, 21 | html` 22 |
23 |

24 | HYPER TECHNOLOGY 25 |

26 |
27 | `, 28 | html` 29 |
30 |

31 | HYPER TECHNOLOGY !!!! 32 |

33 |
34 | `, 35 | html` 36 |
37 |

38 | [ freestyle ] 39 |

40 |
41 | `, 42 | html` 43 |
44 |

45 | [ demos et al ] 46 |

47 |
48 | `, 49 | html` 50 |
51 |

52 | Thank you! 53 |

54 |

55 | Twitter / yoshuawuyts 56 |

57 |

58 | GitHub / yoshuawuyts 59 |

60 |
61 | ` 62 | ] 63 | 64 | require('./slider')(slides) 65 | -------------------------------------------------------------------------------- /2016-11-dapphack/out.js: -------------------------------------------------------------------------------- 1 | const normcore = require('normcore') 2 | 3 | const feed2 = normcore(process.env.key, { live: true }) 4 | feed2.createReadStream().on('data', function (data) { 5 | console.log('feed2: ' + data.toString()) 6 | }) 7 | -------------------------------------------------------------------------------- /2016-11-dapphack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2016-11-dapphack", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "Yoshua Wuyts ", 11 | "license": "MIT", 12 | "dependencies": { 13 | "choo": "^4.0.0-6", 14 | "choo-log": "^3.0.0", 15 | "normcore": "^1.0.3", 16 | "split2": "^2.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /2016-11-dapphack/proposal.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/proposal.md -------------------------------------------------------------------------------- /2016-11-dapphack/slider.js: -------------------------------------------------------------------------------- 1 | const mount = require('choo/mount') 2 | const html = require('choo/html') 3 | const css = require('sheetify') 4 | const log = require('choo-log') 5 | const choo = require('choo') 6 | 7 | module.exports = function (slides) { 8 | const app = choo() 9 | app.use(log()) 10 | 11 | app.model({ 12 | namespace: 'slides', 13 | state: { 14 | slide: (function () { 15 | const loc = window.location.hash.replace('#', '') 16 | return (!loc) ? 0 : Number(loc.replace('slide-', '')) 17 | })(), 18 | max: slides.length - 1 19 | }, 20 | reducers: { 21 | set: function (state, data) { 22 | return { slide: data } 23 | } 24 | }, 25 | effects: { 26 | left: function (state, data, send, done) { 27 | const num = state.slide - 1 28 | const uri = (num <= 0) ? '/' : '#slide-' + num 29 | if (!(num < 0)) { 30 | send('slides:set', num, function () { 31 | send('location:set', uri, done) 32 | }) 33 | } 34 | }, 35 | right: function (state, data, send, done) { 36 | const num = state.slide + 1 37 | const uri = '#slide-' + num 38 | if (!(num > state.max)) { 39 | send('slides:set', num, function () { 40 | send('location:set', uri, done) 41 | }) 42 | } 43 | } 44 | }, 45 | subscriptions: { 46 | keydown: (send, done) => { 47 | document.body.addEventListener('keydown', function (e) { 48 | if (e.key === 'ArrowLeft' || e.key === 'h') send('slides:left', done) 49 | if (e.key === 'ArrowRight' || e.key === 'l') send('slides:right', done) 50 | }) 51 | } 52 | } 53 | }) 54 | 55 | app.router(slides.map((slide, i) => { 56 | const index = (!i) ? '/' : 'slide-' + i 57 | return [index, wrap(slide)] 58 | 59 | function wrap (slide) { 60 | return function () { 61 | // we gotta deep clone nodes or else vdom mutation 62 | // comes to ruin the party 63 | return html` 64 | 67 | ${slide.cloneNode(true)} 68 | 69 | ` 70 | } 71 | } 72 | })) 73 | 74 | mount('body', app.start()) 75 | } 76 | -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/000072.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/000072.ldb -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/000073.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/000073.ldb -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/000074.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/000074.log -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/000075.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/000075.ldb -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/000076.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/000076.ldb -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/000077.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/000077.ldb -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000002 2 | -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/LOCK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/LOCK -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/LOG: -------------------------------------------------------------------------------- 1 | 2016/11/27-17:19:59.776894 700000bae000 Delete type=3 #1 2 | 2016/11/27-17:20:02.218904 70000243a000 Level-0 table #5: started 3 | 2016/11/27-17:20:02.256197 70000243a000 Level-0 table #5: 1100456 bytes OK 4 | 2016/11/27-17:20:02.256798 70000243a000 Delete type=0 #3 5 | 2016/11/27-17:20:02.948019 70000243a000 Level-0 table #7: started 6 | 2016/11/27-17:20:02.994944 70000243a000 Level-0 table #7: 1456841 bytes OK 7 | 2016/11/27-17:20:02.997395 70000243a000 Delete type=0 #4 8 | 2016/11/27-17:20:03.239204 70000243a000 Compacting 1@1 + 1@2 files 9 | 2016/11/27-17:20:03.275136 70000243a000 Generated table #8@1: 8791 keys, 481380 bytes 10 | 2016/11/27-17:20:03.275178 70000243a000 Compacted 1@1 + 1@2 files => 481380 bytes 11 | 2016/11/27-17:20:03.275445 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 12 | 2016/11/27-17:20:03.275621 70000243a000 Delete type=2 #5 13 | 2016/11/27-17:20:03.276028 70000243a000 Delete type=2 #7 14 | 2016/11/27-17:20:03.577416 70000243a000 Level-0 table #10: started 15 | 2016/11/27-17:20:03.621244 70000243a000 Level-0 table #10: 1618690 bytes OK 16 | 2016/11/27-17:20:03.621891 70000243a000 Delete type=0 #6 17 | 2016/11/27-17:20:03.793282 70000243a000 Compacting 1@1 + 1@2 files 18 | 2016/11/27-17:20:03.834610 70000243a000 Generated table #11@1: 11828 keys, 646634 bytes 19 | 2016/11/27-17:20:03.834635 70000243a000 Compacted 1@1 + 1@2 files => 646634 bytes 20 | 2016/11/27-17:20:03.834795 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 21 | 2016/11/27-17:20:03.834921 70000243a000 Delete type=2 #8 22 | 2016/11/27-17:20:03.835240 70000243a000 Delete type=2 #10 23 | 2016/11/27-17:20:04.112099 70000243a000 Level-0 table #13: started 24 | 2016/11/27-17:20:04.158346 70000243a000 Level-0 table #13: 1708791 bytes OK 25 | 2016/11/27-17:20:04.158991 70000243a000 Delete type=0 #9 26 | 2016/11/27-17:20:04.271959 70000243a000 Compacting 1@1 + 1@2 files 27 | 2016/11/27-17:20:04.321529 70000243a000 Generated table #14@1: 14278 keys, 781189 bytes 28 | 2016/11/27-17:20:04.321558 70000243a000 Compacted 1@1 + 1@2 files => 781189 bytes 29 | 2016/11/27-17:20:04.321807 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 30 | 2016/11/27-17:20:04.321942 70000243a000 Delete type=2 #11 31 | 2016/11/27-17:20:04.322184 70000243a000 Delete type=2 #13 32 | 2016/11/27-17:20:04.673612 70000243a000 Level-0 table #16: started 33 | 2016/11/27-17:20:04.713271 70000243a000 Level-0 table #16: 1755852 bytes OK 34 | 2016/11/27-17:20:04.714107 70000243a000 Delete type=0 #12 35 | 2016/11/27-17:20:04.841801 70000243a000 Compacting 1@1 + 1@2 files 36 | 2016/11/27-17:20:04.894965 70000243a000 Generated table #17@1: 16645 keys, 911371 bytes 37 | 2016/11/27-17:20:04.894993 70000243a000 Compacted 1@1 + 1@2 files => 911371 bytes 38 | 2016/11/27-17:20:04.895264 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 39 | 2016/11/27-17:20:04.895436 70000243a000 Delete type=2 #14 40 | 2016/11/27-17:20:04.895793 70000243a000 Delete type=2 #16 41 | 2016/11/27-17:20:05.232356 70000243a000 Level-0 table #19: started 42 | 2016/11/27-17:20:05.273042 70000243a000 Level-0 table #19: 1783046 bytes OK 43 | 2016/11/27-17:20:05.273730 70000243a000 Delete type=0 #15 44 | 2016/11/27-17:20:05.457438 70000243a000 Compacting 1@1 + 1@2 files 45 | 2016/11/27-17:20:05.523268 70000243a000 Generated table #20@1: 18638 keys, 1022240 bytes 46 | 2016/11/27-17:20:05.523295 70000243a000 Compacted 1@1 + 1@2 files => 1022240 bytes 47 | 2016/11/27-17:20:05.523592 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 48 | 2016/11/27-17:20:05.523754 70000243a000 Delete type=2 #17 49 | 2016/11/27-17:20:05.524127 70000243a000 Delete type=2 #19 50 | 2016/11/27-17:20:05.838334 70000243a000 Level-0 table #22: started 51 | 2016/11/27-17:20:05.887481 70000243a000 Level-0 table #22: 1791543 bytes OK 52 | 2016/11/27-17:20:05.888321 70000243a000 Delete type=0 #18 53 | 2016/11/27-17:20:06.010242 70000243a000 Compacting 1@1 + 1@2 files 54 | 2016/11/27-17:20:06.155756 70000243a000 Generated table #23@1: 20513 keys, 1126496 bytes 55 | 2016/11/27-17:20:06.155785 70000243a000 Compacted 1@1 + 1@2 files => 1126496 bytes 56 | 2016/11/27-17:20:06.156019 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 57 | 2016/11/27-17:20:06.156182 70000243a000 Delete type=2 #20 58 | 2016/11/27-17:20:06.156768 70000243a000 Delete type=2 #22 59 | 2016/11/27-17:20:06.257350 70000243a000 Level-0 table #25: started 60 | 2016/11/27-17:20:06.331641 70000243a000 Level-0 table #25: 1803750 bytes OK 61 | 2016/11/27-17:20:06.332310 70000243a000 Delete type=0 #21 62 | 2016/11/27-17:20:06.427320 70000243a000 Compacting 1@1 + 1@2 files 63 | 2016/11/27-17:20:06.538856 70000243a000 Generated table #26@1: 22279 keys, 1224885 bytes 64 | 2016/11/27-17:20:06.538882 70000243a000 Compacted 1@1 + 1@2 files => 1224885 bytes 65 | 2016/11/27-17:20:06.539638 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 66 | 2016/11/27-17:20:06.539819 70000243a000 Delete type=2 #23 67 | 2016/11/27-17:20:06.540215 70000243a000 Delete type=2 #25 68 | 2016/11/27-17:20:07.015186 70000243a000 Level-0 table #28: started 69 | 2016/11/27-17:20:07.057915 70000243a000 Level-0 table #28: 1803322 bytes OK 70 | 2016/11/27-17:20:07.058839 70000243a000 Delete type=0 #24 71 | 2016/11/27-17:20:07.146441 70000243a000 Compacting 1@1 + 1@2 files 72 | 2016/11/27-17:20:07.219448 70000243a000 Generated table #29@1: 23855 keys, 1313413 bytes 73 | 2016/11/27-17:20:07.219476 70000243a000 Compacted 1@1 + 1@2 files => 1313413 bytes 74 | 2016/11/27-17:20:07.219701 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 75 | 2016/11/27-17:20:07.219888 70000243a000 Delete type=2 #26 76 | 2016/11/27-17:20:07.220296 70000243a000 Delete type=2 #28 77 | 2016/11/27-17:20:07.451408 70000243a000 Level-0 table #31: started 78 | 2016/11/27-17:20:07.504611 70000243a000 Level-0 table #31: 1795529 bytes OK 79 | 2016/11/27-17:20:07.505347 70000243a000 Delete type=0 #27 80 | 2016/11/27-17:20:07.582592 70000243a000 Compacting 1@1 + 1@2 files 81 | 2016/11/27-17:20:07.670840 70000243a000 Generated table #32@1: 25373 keys, 1398704 bytes 82 | 2016/11/27-17:20:07.670863 70000243a000 Compacted 1@1 + 1@2 files => 1398704 bytes 83 | 2016/11/27-17:20:07.672732 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 84 | 2016/11/27-17:20:07.672908 70000243a000 Delete type=2 #29 85 | 2016/11/27-17:20:07.673302 70000243a000 Delete type=2 #31 86 | 2016/11/27-17:20:09.079874 70000243a000 Level-0 table #34: started 87 | 2016/11/27-17:20:09.124866 70000243a000 Level-0 table #34: 1789180 bytes OK 88 | 2016/11/27-17:20:09.125942 70000243a000 Delete type=0 #30 89 | 2016/11/27-17:20:09.247366 70000243a000 Compacting 1@1 + 1@2 files 90 | 2016/11/27-17:20:09.371972 70000243a000 Generated table #35@1: 26804 keys, 1478946 bytes 91 | 2016/11/27-17:20:09.372001 70000243a000 Compacted 1@1 + 1@2 files => 1478946 bytes 92 | 2016/11/27-17:20:09.372174 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 93 | 2016/11/27-17:20:09.372310 70000243a000 Delete type=2 #32 94 | 2016/11/27-17:20:09.372733 70000243a000 Delete type=2 #34 95 | 2016/11/27-17:20:09.502246 70000243a000 Level-0 table #37: started 96 | 2016/11/27-17:20:09.549393 70000243a000 Level-0 table #37: 1770383 bytes OK 97 | 2016/11/27-17:20:09.550090 70000243a000 Delete type=0 #33 98 | 2016/11/27-17:20:09.631584 70000243a000 Compacting 1@1 + 1@2 files 99 | 2016/11/27-17:20:09.721209 70000243a000 Generated table #38@1: 28226 keys, 1559424 bytes 100 | 2016/11/27-17:20:09.721234 70000243a000 Compacted 1@1 + 1@2 files => 1559424 bytes 101 | 2016/11/27-17:20:09.721550 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 102 | 2016/11/27-17:20:09.721790 70000243a000 Delete type=2 #35 103 | 2016/11/27-17:20:09.722391 70000243a000 Delete type=2 #37 104 | 2016/11/27-17:20:09.941313 70000243a000 Level-0 table #40: started 105 | 2016/11/27-17:20:09.983191 70000243a000 Level-0 table #40: 1770977 bytes OK 106 | 2016/11/27-17:20:09.984007 70000243a000 Delete type=0 #36 107 | 2016/11/27-17:20:10.063434 70000243a000 Compacting 1@1 + 1@2 files 108 | 2016/11/27-17:20:10.153908 70000243a000 Generated table #41@1: 29625 keys, 1639679 bytes 109 | 2016/11/27-17:20:10.153936 70000243a000 Compacted 1@1 + 1@2 files => 1639679 bytes 110 | 2016/11/27-17:20:10.154252 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 111 | 2016/11/27-17:20:10.154480 70000243a000 Delete type=2 #38 112 | 2016/11/27-17:20:10.154962 70000243a000 Delete type=2 #40 113 | 2016/11/27-17:20:10.346077 70000243a000 Level-0 table #43: started 114 | 2016/11/27-17:20:10.388710 70000243a000 Level-0 table #43: 1740963 bytes OK 115 | 2016/11/27-17:20:10.389461 70000243a000 Delete type=0 #39 116 | 2016/11/27-17:20:10.465818 70000243a000 Compacting 1@1 + 1@2 files 117 | 2016/11/27-17:20:10.560833 70000243a000 Generated table #44@1: 30873 keys, 1711440 bytes 118 | 2016/11/27-17:20:10.560859 70000243a000 Compacted 1@1 + 1@2 files => 1711440 bytes 119 | 2016/11/27-17:20:10.561143 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 120 | 2016/11/27-17:20:10.561357 70000243a000 Delete type=2 #41 121 | 2016/11/27-17:20:10.561795 70000243a000 Delete type=2 #43 122 | 2016/11/27-17:20:10.749886 70000243a000 Level-0 table #46: started 123 | 2016/11/27-17:20:10.789862 70000243a000 Level-0 table #46: 1704566 bytes OK 124 | 2016/11/27-17:20:10.790519 70000243a000 Delete type=0 #42 125 | 2016/11/27-17:20:10.883116 70000243a000 Compacting 1@1 + 1@2 files 126 | 2016/11/27-17:20:10.977539 70000243a000 Generated table #47@1: 32135 keys, 1784073 bytes 127 | 2016/11/27-17:20:10.977567 70000243a000 Compacted 1@1 + 1@2 files => 1784073 bytes 128 | 2016/11/27-17:20:10.977729 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 129 | 2016/11/27-17:20:10.977901 70000243a000 Delete type=2 #44 130 | 2016/11/27-17:20:10.978253 70000243a000 Delete type=2 #46 131 | 2016/11/27-17:20:11.137329 70000243a000 Level-0 table #49: started 132 | 2016/11/27-17:20:11.179944 70000243a000 Level-0 table #49: 1660983 bytes OK 133 | 2016/11/27-17:20:11.180892 70000243a000 Delete type=0 #45 134 | 2016/11/27-17:20:11.227132 70000243a000 Compacting 1@1 + 1@2 files 135 | 2016/11/27-17:20:11.349611 70000243a000 Generated table #50@1: 33333 keys, 1852055 bytes 136 | 2016/11/27-17:20:11.350114 70000243a000 Compacted 1@1 + 1@2 files => 1852055 bytes 137 | 2016/11/27-17:20:11.351238 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 138 | 2016/11/27-17:20:11.351477 70000243a000 Delete type=2 #47 139 | 2016/11/27-17:20:11.352214 70000243a000 Delete type=2 #49 140 | 2016/11/27-17:20:11.487428 70000243a000 Level-0 table #52: started 141 | 2016/11/27-17:20:11.583281 70000243a000 Level-0 table #52: 1591271 bytes OK 142 | 2016/11/27-17:20:11.583857 70000243a000 Delete type=0 #48 143 | 2016/11/27-17:20:11.672156 70000243a000 Compacting 1@1 + 1@2 files 144 | 2016/11/27-17:20:11.834078 70000243a000 Generated table #53@1: 34466 keys, 1918303 bytes 145 | 2016/11/27-17:20:11.834104 70000243a000 Compacted 1@1 + 1@2 files => 1918303 bytes 146 | 2016/11/27-17:20:11.834451 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 147 | 2016/11/27-17:20:11.834635 70000243a000 Delete type=2 #50 148 | 2016/11/27-17:20:11.835042 70000243a000 Delete type=2 #52 149 | 2016/11/27-17:20:11.889118 70000243a000 Level-0 table #55: started 150 | 2016/11/27-17:20:11.936806 70000243a000 Level-0 table #55: 1514230 bytes OK 151 | 2016/11/27-17:20:11.937965 70000243a000 Delete type=0 #51 152 | 2016/11/27-17:20:12.025670 70000243a000 Compacting 1@1 + 1@2 files 153 | 2016/11/27-17:20:12.234028 70000243a000 Generated table #56@1: 35589 keys, 1984542 bytes 154 | 2016/11/27-17:20:12.234052 70000243a000 Compacted 1@1 + 1@2 files => 1984542 bytes 155 | 2016/11/27-17:20:12.235346 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 156 | 2016/11/27-17:20:12.235575 70000243a000 Delete type=2 #53 157 | 2016/11/27-17:20:12.235966 70000243a000 Delete type=2 #55 158 | 2016/11/27-17:20:12.307906 70000243a000 Level-0 table #58: started 159 | 2016/11/27-17:20:12.383268 70000243a000 Level-0 table #58: 1405424 bytes OK 160 | 2016/11/27-17:20:12.383922 70000243a000 Delete type=0 #54 161 | 2016/11/27-17:20:12.460996 70000243a000 Compacting 1@1 + 1@2 files 162 | 2016/11/27-17:20:12.605725 70000243a000 Generated table #59@1: 36660 keys, 2048444 bytes 163 | 2016/11/27-17:20:12.605745 70000243a000 Compacted 1@1 + 1@2 files => 2048444 bytes 164 | 2016/11/27-17:20:12.609590 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 165 | 2016/11/27-17:20:12.609754 70000243a000 Delete type=2 #56 166 | 2016/11/27-17:20:12.610145 70000243a000 Delete type=2 #58 167 | 2016/11/27-17:20:12.686919 70000243a000 Level-0 table #61: started 168 | 2016/11/27-17:20:12.750226 70000243a000 Level-0 table #61: 1253307 bytes OK 169 | 2016/11/27-17:20:12.758420 70000243a000 Delete type=0 #57 170 | 2016/11/27-17:20:12.835249 70000243a000 Compacting 1@1 + 1@2 files 171 | 2016/11/27-17:20:12.967478 70000243a000 Generated table #62@1: 37651 keys, 2106746 bytes 172 | 2016/11/27-17:20:12.967506 70000243a000 Compacted 1@1 + 1@2 files => 2106746 bytes 173 | 2016/11/27-17:20:12.967945 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 174 | 2016/11/27-17:20:12.968395 70000243a000 Delete type=2 #59 175 | 2016/11/27-17:20:12.968815 70000243a000 Delete type=2 #61 176 | 2016/11/27-17:20:13.076077 70000243a000 Level-0 table #64: started 177 | 2016/11/27-17:20:13.134218 70000243a000 Level-0 table #64: 1063166 bytes OK 178 | 2016/11/27-17:20:13.135283 70000243a000 Delete type=0 #60 179 | 2016/11/27-17:20:13.214744 70000243a000 Compacting 1@1 + 1@2 files 180 | 2016/11/27-17:20:13.385561 70000243a000 Generated table #65@1: 38669 keys, 2166932 bytes 181 | 2016/11/27-17:20:13.385591 70000243a000 Compacted 1@1 + 1@2 files => 2166932 bytes 182 | 2016/11/27-17:20:13.385788 70000243a000 compacted to: files[ 0 0 1 0 0 0 0 ] 183 | 2016/11/27-17:20:13.386426 70000243a000 Delete type=2 #62 184 | 2016/11/27-17:20:13.387074 70000243a000 Delete type=2 #64 185 | 2016/11/27-17:20:13.905557 70000243a000 Level-0 table #67: started 186 | 2016/11/27-17:20:13.929832 70000243a000 Level-0 table #67: 871970 bytes OK 187 | 2016/11/27-17:20:13.930614 70000243a000 Delete type=0 #63 188 | 2016/11/27-17:20:14.039336 70000243a000 Compacting 1@1 + 1@2 files 189 | 2016/11/27-17:20:14.166602 70000243a000 Generated table #68@1: 38836 keys, 2181982 bytes 190 | 2016/11/27-17:20:14.171220 70000243a000 Generated table #69@1: 845 keys, 44413 bytes 191 | 2016/11/27-17:20:14.171246 70000243a000 Compacted 1@1 + 1@2 files => 2226395 bytes 192 | 2016/11/27-17:20:14.171451 70000243a000 compacted to: files[ 0 0 2 0 0 0 0 ] 193 | 2016/11/27-17:20:14.171718 70000243a000 Delete type=2 #65 194 | 2016/11/27-17:20:14.172321 70000243a000 Delete type=2 #67 195 | 2016/11/27-17:20:14.310042 70000243a000 Level-0 table #71: started 196 | 2016/11/27-17:20:14.343238 70000243a000 Level-0 table #71: 651734 bytes OK 197 | 2016/11/27-17:20:14.343856 70000243a000 Delete type=0 #66 198 | 2016/11/27-17:20:14.433228 70000243a000 Compacting 1@1 + 2@2 files 199 | 2016/11/27-17:20:14.612744 70000243a000 Generated table #72@1: 38734 keys, 2180454 bytes 200 | 2016/11/27-17:20:14.620364 70000243a000 Generated table #73@1: 1975 keys, 102032 bytes 201 | 2016/11/27-17:20:14.620385 70000243a000 Compacted 1@1 + 2@2 files => 2282486 bytes 202 | 2016/11/27-17:20:14.622654 70000243a000 compacted to: files[ 0 0 2 0 0 0 0 ] 203 | 2016/11/27-17:20:14.622813 70000243a000 Delete type=2 #68 204 | 2016/11/27-17:20:14.623148 70000243a000 Delete type=2 #69 205 | 2016/11/27-17:20:14.623379 70000243a000 Delete type=2 #71 206 | 2016/11/27-17:20:14.623571 70000243a000 Level-0 table #75: started 207 | 2016/11/27-17:20:14.643509 70000243a000 Level-0 table #75: 469822 bytes OK 208 | 2016/11/27-17:20:14.644173 70000243a000 Delete type=0 #70 209 | 2016/11/27-17:20:14.703654 70000243a000 Compacting 1@1 + 1@2 files 210 | 2016/11/27-17:20:14.825368 70000243a000 Generated table #76@1: 38655 keys, 2181904 bytes 211 | 2016/11/27-17:20:14.828464 70000243a000 Generated table #77@1: 1235 keys, 63503 bytes 212 | 2016/11/27-17:20:14.828489 70000243a000 Compacted 1@1 + 1@2 files => 2245407 bytes 213 | 2016/11/27-17:20:14.828775 70000243a000 compacted to: files[ 0 0 3 0 0 0 0 ] 214 | -------------------------------------------------------------------------------- /2016-11-dapphack/whatever/.dat/MANIFEST-000002: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-11-dapphack/whatever/.dat/MANIFEST-000002 -------------------------------------------------------------------------------- /2016-11-nodefest-jp/proposal.md: -------------------------------------------------------------------------------- 1 | # boarding the tiny framework train 2 | Three years ago the frontend community was introduced to the exciting potential 3 | of building completely functional user interfaces. We're now in a world where 4 | functional programming is gradually becoming the norm, and we're shifting to 5 | solve problems that we didn't think about years ago. 6 | 7 | In this talk Yosh will cover the bleeding edge of frontend development, and 8 | dive deep into Choo, a modular frontend framework designed specifically to 9 | solve today's challenges. 10 | -------------------------------------------------------------------------------- /2016-12-holyjs/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2016-12-holyjs/README.md -------------------------------------------------------------------------------- /2016-12-holyjs/proposal.md: -------------------------------------------------------------------------------- 1 | > http://holyjs.ru//en/callforpapers.html 2 | 3 | ## Bio 4 | > MAKE YOUR SPEAKER BIO AS INFORMATIVE AS YOUR TALK. LET PEOPLE LEARN MORE 5 | > ABOUT YOU AND EVALUATE YOUR TALK ALSO BY YOUR BACKGROUND. 6 | - Node streams working group member 7 | - Author of [choo](https://github.com/yoshuawuyts) 8 | - International Nodeschool mentor 9 | - JS consultant 10 | 11 | ## Speaker background 12 | - https://github.com/yoshuawuyts/speaking 13 | - https://medium.com/@yoshuawuyts 14 | 15 | ## Title 16 | THE FRONTEND RESISTANCE 17 | 18 | ## Description 19 | > INCLUDE ENOUGH DETAILS ABOUT YOUR TALK, BUT BE CONCISE AND CLEARLY STATE: 20 | > DESCRIBE TECHNOLOGIES THAT WILL BE COVERED, PURPOSE OF THE TALK (PROBLEM AND 21 | > ITS SOLUTIONS, ETC.), TARGET AUDIENCE, AUDIENCE TAKEAWAY. 22 | > DON'T MAKE YOUR TALK LIKE A SALES PITCH. WE'RE LOOKING FOR A TECHNICAL TALK 23 | > RATHER THAN A MARKETING. 24 | 25 | We all know that tomorrow's tech was built yesterday, only waiting to go big. 26 | Or perhaps now is not the time, and we'll take time 27 | Ever wondered who 28 | 29 | ## Audience takeaway 30 | The a 31 | 32 | ## Who is the target audience? 33 | Developers that want to build things for the browser, but have limited 34 | resources available. 35 | 36 | ## Short description 37 | -------------------------------------------------------------------------------- /2016-12-jsconf-au/proposal.md: -------------------------------------------------------------------------------- 1 | # itty bitty websites 2 | What if we could make sites that render fast on any machine; pushing the 3 | boundries of what's theoretically possible in browsers? What do fast websites 4 | look like under the hood? And how can we as an industry move towards a fast, 5 | smaller web that is ready for the protocols of tomorrow? We'll go over the 6 | theory on how to build fast sites - and hand out the tools needed to tune Unix, 7 | Node and the browser to exist in balanced harmony. 8 | 9 | ## Goals 10 | The goal of the presentation is for people to understand what makes websites 11 | fast, and how to apply that knowledge for their own production stacks. It'd be 12 | cool if people could walk away from the presentation knowing: 13 | - roughly how the browser TCP / HTTP network stack works 14 | - roughly how the different stages of browser rendering work 15 | - how caching works 16 | - how to make node serve assets as fast as possible 17 | - key network numbers for which to optimize (packet sizes, frames, etc) 18 | - how to inspect their own payloads 19 | - which Node tools to use to optimize their own payloads 20 | 21 | ## Bonus goals 22 | - show off how to compile these sites for delivery over traditionally 23 | slow, but interesting protocols (e.g. IPFS, noscript Tor) 24 | - go over some strategies to speed up JS 25 | - provide an overview of popular packages that don't perform well and show off 26 | alternatives that might be a better fit 27 | 28 | ## About 29 | Yosh is a creative engineer who loves all things computer. He's been an active 30 | member of the Node community for years and specializes in building tiny tools 31 | that achieve big things. 32 | -------------------------------------------------------------------------------- /2017-01-nodeconf-bp/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2017-01-nodeconf-bp/README.md -------------------------------------------------------------------------------- /2017-01-nodeconf-bp/proposal.md: -------------------------------------------------------------------------------- 1 | #### Title 2 | LETS BUILD A PEER TO PEER SYSTEM! 3 | 4 | #### Description 5 | Ever wondered how peer to peer systems are implemented? In this talk we'll go 6 | over how to implement a fully functional data exchange service from first 7 | principles custom tailored for people new to the field. We'll go from a tiny 8 | system with two nodes, up to something that can work at internet scale. We'll 9 | be touching on architecture, data structures, networking and more. At the end 10 | of it you'll feel good about you, your coding abilities and your ability to p2p 11 | in particular. 12 | 13 | #### Learning objectives 14 | - basic data structures used in p2p (mostly how kademlia works) 15 | - an idea of which protocols are used in p2p, and why 16 | - feel confident you can peer to peer too :v: 17 | 18 | #### City of residence 19 | Berlin 20 | 21 | --- 22 | 23 | #### Title 24 | DIY VIRTUAL DOM IN 20 MINUTES! 25 | 26 | #### Description 27 | Ever wondered what goes on inside today's framework engines? In this talk 28 | we'll got over how to implement a virtual DOM, from scratch. We'll start off 29 | with some of the basics around why DOM virtualization is useful; gently moving 30 | up to how to create nodes, how to implement diffing, array reordering and 31 | eventually dive into some of the less understood optimizations such as branch 32 | caching. All packaged up neatly into a 20 minute talk. 33 | 34 | #### Learning objectives 35 | - get an idea of why virtual DOMs are used 36 | - understand how node diffing works 37 | - understand which optimizations can be applied after basic diffing 38 | - basically we're going to demistify this whole vdom thing once and for all 39 | because it's definitely time we did. Everyone uses these things and so few 40 | people seem to understand how it works and that's not a good thing 41 | 42 | #### City of residence 43 | Berlin 44 | -------------------------------------------------------------------------------- /2017-05-jsconf-eu/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2017-05-jsconf-eu/README.md -------------------------------------------------------------------------------- /2017-05-jsconf-eu/proposal.md: -------------------------------------------------------------------------------- 1 | # Go! Go! Nanoframeworks! 2 | 3 | Ok, let's try a thing. Close your eyes for a bit. No peeking. Now I want you to 4 | imagine the last time you wrote some browser code. Perhaps a component of 5 | sorts. Remember what that was like? yeah. Ok. Now I want you to imagine that 6 | was the very last time you had to write that component. New framework in town? 7 | No problem, still works. Wouldn't that be nice? 8 | 9 | What if I told you that's possible today? That we have the means to create 10 | browser agnostic 100% native DOM elements. And an increasing array of 11 | frameworks that have all the conveniences you've come to expect but without 12 | locking you in. Sounds almost too good to be true right? It's real though; v. 13 | real. 14 | 15 | This talk will show how to code up a modern application framework using browser 16 | primitives. It'll show how to create native DOM diffing, building and 17 | optimizing a UI loop, creating a message bus, and explaining which APIs to use 18 | to optimize application booting. All of which should continue to work as long 19 | as we got browsers to run them on, which is most likely gonna be a whole while 20 | longer ✌️ 21 | 22 | Oh PS. Expect live coding. Or a workshop if you like. Maybs even both (: 23 | -------------------------------------------------------------------------------- /2017-05-jsday-it/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2017-05-jsday-it/README.md -------------------------------------------------------------------------------- /2017-05-jsday-it/proposal.md: -------------------------------------------------------------------------------- 1 | # Go! Go! Nanoframeworks! 2 | 3 | Ok, let's try a thing. Close your eyes for a bit. No peeking. Now I want you to 4 | imagine the last time you wrote some browser code. Perhaps a component of 5 | sorts. Remember what that was like? yeah. Ok. Now I want you to imagine that 6 | was the very last time you had to write that component. New framework in town? 7 | No problem, still works. Wouldn't that be nice? 8 | 9 | What if I told you that's possible today? That we have the means to create 10 | browser agnostic 100% native DOM elements. And an increasing array of 11 | frameworks that have all the conveniences you've come to expect but without 12 | locking you in. Sounds almost too good to be true right? It's real though; v. 13 | real. 14 | 15 | This talk will show how to code up a modern application framework using browser 16 | primitives. It'll show how to create native DOM diffing, building and 17 | optimizing a UI loop, creating a message bus, and explaining which APIs to use 18 | to optimize application booting. All of which should continue to work as long 19 | as we got browsers to run them on, which is most likely gonna be a whole while 20 | longer ✌️ 21 | 22 | Oh PS. Expect live coding. Or a workshop if you like. Maybs even both (: 23 | -------------------------------------------------------------------------------- /2017-06-fluent/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yoshuawuyts/speaking/617d649afa4dff9a9ab6cdfa096b06676507566d/2017-06-fluent/README.md -------------------------------------------------------------------------------- /2017-06-fluent/proposal.md: -------------------------------------------------------------------------------- 1 | # Go! Go! Nanoframeworks! 2 | 3 | Ok, let's try a thing. Close your eyes for a bit. No peeking. Now I want you to 4 | imagine the last time you wrote some browser code. Perhaps a component of 5 | sorts. Remember what that was like? yeah. Ok. Now I want you to imagine that 6 | was the very last time you had to write that component. New framework in town? 7 | No problem, still works. Wouldn't that be nice? 8 | 9 | What if I told you that's possible today? That we have the means to create 10 | browser agnostic 100% native DOM elements. And an increasing array of 11 | frameworks that have all the conveniences you've come to expect but without 12 | locking you in. Sounds almost too good to be true right? It's real though; v. 13 | real. 14 | 15 | This talk will show how to code up a modern application framework using browser 16 | primitives. It'll show how to create native DOM diffing, building and 17 | optimizing a UI loop, creating a message bus, and explaining which APIs to use 18 | to optimize application booting. All of which should continue to work as long 19 | as we got browsers to run them on, which is most likely gonna be a whole while 20 | longer ✌️ 21 | 22 | Oh PS. Expect live coding. Or a workshop if you like. Maybs even both (: 23 | -------------------------------------------------------------------------------- /2020-rust-latam.md: -------------------------------------------------------------------------------- 1 | # CFP Rust Latam 2 | 3 | - Title: Designing Tide & Surf 4 | - Tags: intermediate / advanced 5 | - Language: English, but could do Spanish if organizers can help prep (native 6 | speaker, but never done a talk in Spanish before) 7 | 8 | ## Abstract 9 | 10 | Rust is going through a meteoric rise - increasingly underpinning some of the 11 | largest infrastructure deployments in the world. Much of that has to do with 12 | networking, and is considered pretty advanced. But what if we told you that 13 | you too could be writing advanced networking code? 14 | 15 | In this talk Yosh will walk you through the design of Tide and Surf, an HTTP 16 | server and client pair. He'll explain how they work, and how the designs are 17 | uniquely enabled by the language, using these projects as case studies to 18 | discuss effective API design in Rust. 19 | 20 | ## Committee Details 21 | 22 | The talk will start stating the importance for Rust to have a web presence, 23 | drawing on numbers from the Rust and StackOverflow surveys. We'll then share 24 | the work we've been doing to solve this: Surf & Tide, a framework pairing of 25 | HTTP server and HTTP client. After a brief introduction we'll cover several 26 | unique features they provide, how they've been made possible by Rust. 27 | 28 | The purpose of this talk is to lift the covers on the design process that 29 | goes into building something as complex as a web framework in Rust. Rust's is 30 | a unique language, and sharing the process of something novel might prove to 31 | be insightful for many of aspirational Rust users. 32 | 33 | ## Committee Pitch 34 | 35 | Between 2018-2019 I was the co-lead of the Rust Net WG, which subsequently 36 | became the Rust Async Ecosystem WG. Much of the work we did was research ways 37 | to make asynchronous Rust more accessible to people. And async-std, tide, and 38 | surf are the products of much of the work that happened during that time. 39 | 40 | ## Why are you excited? 41 | 42 | Rust is at a turning point in adoption. Now that we have Rust 2018, 43 | async/await, and well-known production users, we're seeing an shift from 44 | enthusiasts to industry adoption. 45 | 46 | There's still a perception that "rust is hard" and especially "async rust is 47 | hard". We're here to show what *could be*. How through careful API design, 48 | documentation, and yielding Rust's strenghts we can actually produce 49 | something that's *easier* than the alternatives. 50 | 51 | I don't feel this is a take that many people bring to Rust; but it's such an 52 | important part of what makes the language work. I'd like to share that 53 | perspective with more people, empowering people to realize *they too* can 54 | make these things, and in turn help lower the barrier for everyone else. 55 | 56 | ## Previous speaking experience 57 | 58 | I've spoken at over 40 events in the past 4 years, helped out at workshops, 59 | and run livestreams. Highlights include: 60 | 61 | - NodeFest Japan 2016 62 | - NodeConf EU 2017 63 | - RustConf 2019 64 | 65 | ## Have you presented on this topic before? 66 | 67 | I've spoken at-length about JavaScript frameworks in the past. This would be 68 | the first time I present publicly about the work we've done on Tide, Surf, 69 | and our HTTP stack. 70 | 71 | ## Bio 72 | 73 | Yosh is a sofware engineer based in Berlin. He's previously co-led the Rust 74 | Async Ecosystem WG, and is the co-author of the async-std, tide, and surf 75 | crates. 76 | -------------------------------------------------------------------------------- /2020-rustlab.md: -------------------------------------------------------------------------------- 1 | # Designing Tide 2 | 3 | ## Elevator Pitch (300 chars) 4 | 5 | For the past two years I've been working on the Tide server framework. I'd 6 | love to do a talk on the design considerations, and place it in the larger 7 | context of design considerations that arise around async Rust. Design talks 8 | are rare, and I would love to give one. 9 | 10 | API design is both crucial and under-represented. The Tide webserver has been 11 | 12 | ## Description 13 | 14 | Async networking in Rust is taking off. But one challenge in particular is 15 | how to make async Rust available to existing and new Rustaceans alike. 16 | 17 | In this talk Yosh will walk you through the design of Tide, a friendly HTTP 18 | server — using it as a case study for effective async API design in Rust. 19 | 20 | ## Notes 21 | 22 | I'm the former co-lead of the Async Ecosystem WG, current member of the Async 23 | Foundations WG, co-designer of async-std, and co-designer of the Tide 24 | framework. Much of my work in the past few years has been focused on async 25 | Rust, and I would love to give a talk on API design in the context of Async 26 | Rust. 27 | 28 | ## Bio 29 | 30 | Yosh is a Rust engineer at [Prisma](https://prisma.io). Currently active as a 31 | member of the Rust Async Foundations WG and co-creator of Tide and async-std. 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Yoshua Wuyts 2 | 3 | Permission is hereby granted, free of charge, to any person ob- 4 | taining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without restric- 6 | tion, including without limitation the rights to use, copy, modi- 7 | fy, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is fur- 9 | nished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONIN- 17 | FRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Speaking 2 | Slides, proposals and more for talks I give. 3 | 4 | ## Talks 5 | ```txt 6 | [2015-03] accepted amsjs npm, local modules & you 7 | [2015-03] accepted ams-jsmvc modular frontend 8 | [2015-05] accepted ams-frontend unbundling the frontend 9 | [2015-10] accepted syd-nodeninjas 5 modules in 5 minutes 10 | [2015-10] accepted melb-nodejs pipe, emit, stream, listen 11 | [2015-10] accepted sydjs Node.js in 5 12 | [2015-11] accepted campjs-vi 11 rad packages 13 | [2015-11] accepted syd-nodeninjas logging and error handling in Node.js 14 | [2015-11] accepted sydjs pipe, emit, stream, listen 15 | [2016-02] accepted melb-nodejs a thousand tiny messages 16 | [2016-02] accepted melbjs virtual-what? 17 | [2016-03] accepted melbcss modular stylesheets with sheetify 18 | [2016-04] accepted pivotal-labs virtual no more 19 | [2016-05] denied nodeconf-london pull-stream: the little module that could 20 | [2016-05] denied nodeconf-london the anatomy of a node server 21 | [2016-05] accepted nodeschool-tokyo choo: the little framework that could 22 | [2016-06] accepted nodeconf-oslo tiny messages for big architectures 23 | [2016-07] accepted react-hamburg choo choo choo 24 | [2016-07] accepted remote-meetup choo choo choo 25 | [2016-08] denied cascadiafest pull-stream: the little module that could 26 | [2016-08] accepted cascadiafest the anatomy of a node server 27 | [2016-08] denied cascadiafest virtual no more 28 | [2016-09] accepted nodejs-berlin deep dive into browserify 29 | [2016-09] accepted node-interactive deep dive into browserify 30 | [2016-09] accepted nodeboat intro to choo 31 | [2016-10] accepted nodeconf-eu towards a faster, smaller web 32 | [2016-11] accepted nodefest-jp choo choo choo 33 | [2016-11] accepted dapphack hypertechnology 34 | [2016-12] aborted holyjs the frontend resistance 35 | [2016-12] accepted code europe boarding the tiny framework train 36 | [2016-12] denied jsconf-au itty bitty websites 37 | [2017-05] pending jsconf-eu Go! Go! Nanoframeworks! 38 | [2017-05] pending jsday-it Go! Go! Nanoframeworks! 39 | [2017-06] pending fluent Go! Go! Nanoframeworks! 40 | [2017-06] accepted amsterdamjs Browser Framework Fundamentals 41 | ``` 42 | 43 | ## Recordings 44 | - __\[2015-11\] sydjs:__ [pipe, emit, stream, listen](https://www.youtube.com/watch?v=QWtG_A0nihQ) 45 | - __\[2016-03\] melbcss:__ [modular stylesheets using sheetify](https://www.youtube.com/watch?v=LKie2UgUJgU) 46 | - __\[2016-06\] nodeconf-oslo:__ [tiny messages for big systems](https://opbeat.com/events/nodeconf-oslo-2016/#tiny-messages-for-big-architectures) 47 | - __\[2016-08\] remote-meetup:__ [choo choo choo](https://www.bigmarker.com/remote-meetup/Javascript-Remote-Meetup-Cycle-and-Choo) 48 | - __\[2016-09\] node-interactive:__ [deep dive into browserify](https://www.youtube.com/watch?v=-LCLeV7swkA) 49 | - __\[2016-11\] nodefest:__ [boarding the tiny framework train](https://www.youtube.com/watch?v=q0K9eMP5fwU) 50 | 51 | ## See Also 52 | - [mafintosh/slides](https://github.com/mafintosh/slides) 53 | - [watson/slides](https://github.com/watson/talks) 54 | - [watson/hacker-conferences](https://github.com/watson/hacker-conferences) 55 | 56 | ## License 57 | [MIT](https://tldrlegal.com/license/mit-license) 58 | --------------------------------------------------------------------------------