slides-techsylvania-2016



slides-techsylvania-2016

0 0


slides-techsylvania-2016

Lightweight JS with Rollup, Riot and Redux (Techsylvania 2016)

On Github cbetta / slides-techsylvania-2016

Lightweight JS

with Rollup, Riot and Redux

Cristiano Betta

@cbetta | betta.io

Cristiano Betta

Hacker @ betta.io

@cbetta

Hire me!

2x @ Techsylvania!

former PayPal/Braintree

Ruby/JS Developer

Consultant @ Work Betta

Code Monkey @ punch.rocks

 

punch

  <script src="punch.js" charset="utf-8"></script>

  <div id='registration'></div>

  <script type="text/javascript">
    punch.setup({
      id: "19acb1ab...53fd459280d",
      type: 'popover',
      element: '#registration'
    });
  </script>
 
 

Problems

I am was not a hardcore JS Dev How to make a browser library? How to maintain state? How to update the UI? How to not go crazy while doing it?
 

This Talk

Learn some JS! Bundling State Management Libraries UI Management Libraries Occasional Cat Pictures

bundling

NodeJS dependencies in the bowser

browserify

Browserify lets you require('modules') in the browser by bundling up all of your dependencies.

Browserify.org

browserify main.js -o bundle.js

browserify

Older

JS Only

No ES6 import/export

Not the smallest result

Webpack

A bundler for javascript and friends.

webpack.github.io

webpack input.js output.js

Webpack

Newer

Handles many assets

No ES6 import/export

Not always smallest result

Not the simplest

Rollup

The next-generation JavaScript module bundler

rollupjs.org

rollup input.js --output output.js

Rollup

Newer

JS Only

No ES6 import/export

Tree shaking

Simple to use

Rollup

The next-generation JavaScript module bundler

Write ES6 (aka ES2015)

Bundle into single file

Smaller than Browserify and Webpack

Export to AMD, CommonJS, ES2015, Globals, UMD

Tree shaking!

ES6

import fs from 'fs';

class AwesomeSauce {
  constructor() {
    // some code
  }

  makeIt() {
    // some code
  }
}

export default AwesomeSauce;

ES6

import AwesomeSauce from 'awesome-sauce';

let sauce = new AwesomeSauce();
sauce.makeIt();

ES6

class AwesomeSauce {
  // 100 lines of code
}

class EnterpriseSauce {
  // 2000 lines of code
}

export EnterpriseSauce;
export default AwesomeSauce;

ES6

//import 2000 lines of code!
import { EnterpriseSauce } from 'awesome-sauce';

let sauce = new EnterpriseSauce();
sauce.makeItSecureButSlow();

Rollup Tree Shaking

// main.js
import { cube } from './maths.js';
console.log( cube( 5 ) );
// maths.js

// unused function
export function square ( x ) {
    return x * x;
}

// included function
export function cube ( x ) {
    return x * x * x;
}

Rollup Tree Shaking

function cube ( x ) {
    return x * x * x;
}

console.log( cube( 5 ) );

Rollup UMD

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (factory());
}(this, function () { 'use strict';
    function cube ( x ) {
        return x * x * x;
    }

    console.log( cube( 5 ) );
}));

npm

// package.json
{
  ...
  "scripts": {
    "dist:js": "rollup -c rollup/dist.js",
    ...
  }
}

npm

// rollup/dist.js

export default {
  entry: 'js/index.js',
  dest: 'dist/punch.js',
  format: 'umd',
  moduleName: 'punch',
  plugins: [
    riot(),
    npm({ browser: true }),
    commonjs(),
    babel(),
    uglify()
  ]
};

npm

// js/index.js

import Dropin from './dropin/main.js';

let dropin = new Dropin();

export var setup = dropin.setup; // punch.setup() from earlier!
export var destroyAll = dropin.destroyAll;
export var instances = dropin.instances;

punch

  <script src="punch.js" charset="utf-8"></script>

  <div id='registration'></div>

  <script type="text/javascript">
    punch.setup({
      id: "19acb1ab...53fd459280d",
      type: 'popover',
      element: '#registration'
    });
  </script>
 

UI Management

Nothing can be said to be certain

except death and taxes

and JS frameworks

 

Angular JS

HTML enhanced for web apps!

angularjs.org

~50kb (compressed)

React JS

A Javascript Library for building user interfaces

facebook.github.io/react

~146kb (compressed)

Riot

A React-like user interface micro-library

riotjs.com

~9.18kb (compressed)

Riot

A React-like user interface micro-library

Riot

Custom Tags

Virtual Dom

Enjoyable Syntax

No IE8 support

Tiny Size!

Riot

<!-- index.html  -->
<div id='element'></div>
// dropin.js
import './tags/punch-dropin.tag';

import riot from 'riot';

riot.mount('#element', "punch-dropin");

Riot

<!-- punch-dropin.tag -->
<punch-dropin>
  <h1>Hello World</h1>
</punch-dropin>

Riot

<!-- punch-dropin.tag -->
<punch-dropin>
  <punch-loader></punch-loader>
  <punch-form></punch-form>
</punch-dropin>
 

State Management

There are two hard things in computer science: cache invalidation and naming things.

There are two hard things in computer science: cache invalidation and naming things and state management

There are three hard things in computer science: cache invalidation and naming things and state management

There are two hard things in computer science: cache invalidation, naming things and state management

 

Redux

Redux is a predictable state container for JavaScript apps.

github.com/reactjs/redux

2kb

Including dependencies!

Before uglifying/compression!!

Riot compatible!!!

Redux

npm install redux
// dropin.js
import './tags/punch-dropin.tag';

import riot from 'riot';
import { createStore } from 'redux';
import StoreMixin      from 'riot-redux-mixin';

let state = ...
let store = createStore(state);
riot.mixin('redux', new StoreMixin(store));

riot.mount('#element', "punch-dropin");

Redux

<!-- punch-dropin.tag -->
<punch-dropin>
  <h1>Counter: { state.count }</h1>

  <script type="text/javascript">
    this.mixin('redux');

    this.subscribe(function(state){
      this.state = state;
    }.bind(this))
  </script>
</punch-dropin>

Redux

// dropin.js

let state = function counter(count = 0, action) {
  switch (action) {
  case 'increment':
    return count + 1
  case 'decrement':
    return count - 1
  default:
    return count
}

Redux

<!-- punch-dropin.tag -->
<punch-dropin>
  <h1 onClick={ increment }>Counter: { state.count }</h1>

  <script type="text/javascript">
    this.mixin('redux');

    this.increment = function() {
      this.store.dispatch('increment');
    }

    this.subscribe(function(state){
      this.state = state;
    }.bind(this))
  </script>
</punch-dropin>

Demo

Demo

Rollup: 12k

WebPack 2: 13k

Comparison

All results in bytes, Gzipped

babel + browserify + uglify => 3915

webpack@2 + babel + uglify => 3632

babel + rollup + uglify => 3440

typescript + webpack => 3245

closure => 2890

Comparison

More results

github.com/samccone/The-cost-of-transpiling-es2015-in-2016

My results

source - 37,304 bytes

bundled => 180,345 bytes

uglified => 57,171 bytes

gzipped => 18,561 bytes

Conclusions

Most of these are personal opinion

ES6 is lovely

RiotJS is easy and really small

Riot+Redux makes apps easy to comprehend

Rollup + NPM scripts beats Gulp and Grunt

Notes

Some stuff isn't there yet

Rollup+Riot breaks sourcemaps

WebPack Chunks are awesome

Riot Routes needs to be added

Hard to scientifically compare sizes

Thank you

Cristiano Betta | @cbetta | betta.io

go.betta.io/lightweightjs

go.betta.io/lightweightjs-demo

Hire me!

Hire me?

work.betta.io

Hire me!
Lightweight JS with Rollup, Riot and Redux Cristiano Betta @cbetta | betta.io