Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What's happening in frontend now?

koba04
August 20, 2015

What's happening in frontend now?

YAPC::Asia 2015 (08/21) @koba04

koba04

August 20, 2015
Tweet

More Decks by koba04

Other Decks in Programming

Transcript

  1. koba04 • Toru Kobayashi • Web application engineer • ≠

    Frontend engineer • Single Page Application • Backbone -> Angular -> React
  2. Good old web • Client requests HTML. • Server responses

    HTML. • Very simple • JavaScript doesn’t have to use. browser server GET /index.html index.html GET /about.html about.html
  3. Ajax! • Google Map • Asynchronous updates • We need

    JavaScript! • From Page to Application
  4. ECMAScript 5 (5.1) • “use strict”; • Object.create, Object.defineProperty •

    Array.prototype.(forEach, map, filter, reduce…) • JSON.parse, JSON.stringify • IE9ʙ 2009 2011(5.1)
  5. CoffeeScript • Jeremy Ashkenas • CoffeeScript is a little language

    that compiles into JavaScript • Brevity and readability. • Rails 3.1 CoffeeScript • Some features are in ECMAScript 2015 2010(1.0)
  6. class Parent class Hello extends Parent constructor: (@name) -> super()

    method: -> console.log @name hello = new Hello 'coffee' setTimeout( () => hello.method(), 1000 )
  7. jQuery • John Resig • DOM API is too low

    level • Browsers compatibility • jQuery Plugin • document.querySelector, Deferred(Promise)… 2006
  8. $button.on(‘click’, function() { $.ajax( method: ‘GET’, url: ‘/api/item_list’ ) .done(function(items)

    { $ul = $(‘<ul />’); $.each(items, function(index, value) { $ul.append($(‘<li>’ + value + ‘</li>’)); }); $(‘.items’).append($ul); }); }); });
  9. Backbone.js • Jeremy Ashkenas • JavaScript MVC framework • Observer

    pattern • Depend on jQuery & underscore.js 2010
  10. var View = Backbone.View.extend({ events: { 'change .text': 'change' },

    initialize: function() { this.listenTo(this.model, 'change', this.render); }, change: function() { this.model.set('text', this.$el.find('.text').val()); }, render: function() { this.$el.html( '<input type="text" class="text" /><div>' + this.model.get('text') + ‘</div>' ); return this; } }); $('#app').append( new View({ model: new Backbone.Model({text: ‘initial'}) }).render().$el );
  11. Node.js • Node.js is a platform built on V8 •

    npm (173,476 packages) • server & cli • Event loop is that it runs under a single thread • Stream 2009
  12. var http = require('http'); var fs = require('fs'); http.createServer(function(req, res)

    { fs.readFile('test.png', function(err, data) { if (err) return console.log(err); res.writeHead(200, {'Content-Type': 'image/png'}); res.end(data); }); }).listen(3000); // ↓ http.createServer(function(req, res) { fs.createReadStream('test.png').pipe(res); }).listen(3001); Stream!
  13. Grunt.js • The JavaScript Task Runner • Not a build

    tool • Configurable • Yeomanɺassemble • Last release is 2014 May… • npm scripts 2012
  14. module.exports = (grunt) -> watch: coffee: files: ["coffee/**/*.coffee"] tasks: ["js"]

    coffee: files: "static/js/app.js": [ "coffee/app.coffee" "coffee/model/*.coffee" "coffee/collection/*.coffee" "coffee/view/*.coffee" ] concat: dev: src: [ "bower_components/jquery/jquery.js" "bower_components/underscore/underscore.js" "bower_components/backbone/backbone.js" "static/js/app.js" ] dest: “static/js/all.js"
  15. Chrome • Fast! Fast! Fast! • Webkit (version 28ʙ Blink)

    • Google V8 JavaScript Engine • JavaScriptCore(Safari), Chakra(IE), SpiderMonkey(Firefox) • Just in Time (JIT) 2008
  16. TypeScript • Microsoft • Typed superset of JavaScript • Class,

    Interface, Generics, Modules… • IDE Support • DefinitelyTyped 2012
  17. class Greeter { greeting: string; constructor(message: string) { this.greeting =

    message; } greet(): string { return "Hello, " + this.greeting; } } var greeter = new Greeter("world");
  18. AST

  19. AST • Abstract Syntax Tree • SpiderMonkey Parser API •

    https://developer.mozilla.org/en-US/docs/ Mozilla/Projects/SpiderMonkey/Parser_API • Esprima, Espree, Acorn, Babylon • ESTree, ShiftAST
  20. { "type": "Program", "body": [ { "type": "VariableDeclaration", "declarations": [

    { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "answer" }, "init": { "type": "BinaryExpression", "operator": "*", "left": { "type": "Identifier", "name": "hoge" }, "right": { "type": "Literal", "value": 7, "raw": "7" } } } ], "kind": "var" } ] } var answer = hoge * 7; Parse by Esprima http://esprima.org/demo/parse.html
  21. Libraries using AST • Linter - ESLint • Analyzer -

    istanbul, plato • Test - power-assert • Transpiler - browserify, babel
  22. Isomorphic • Share the code between client and server •

    → For maintenance • Initial render executes on the server • → For SEO and Performance • Frameworks have different approaches • Meteor, Rendr…
  23. browser server HTML included contents GET app.js GET / Node.js

    You can see the contents! Start to run your JavaScript on the browser GET /other/page Route on the browser
  24. The requirements of SPA • Binding JSON data to DOM

    • Routing by the browser History API • Browser side template engine • Data management • Memory management
  25. Angular.js • Google • HTML enhanced for web apps. •

    2way Data binding • Full stack (ng-http, ng-router…) • Very simple? (initially) • Angular 2 is completely different. release:2009 1.0: 2012
  26. <div ng-app="MyApp"> <div ng-controller=“MyController as controller"> <ul> <li ng-repeat="name in

    controller.names”>{{name}}</li> </ul> </div> </div> <script> angular.module('MyApp', []) .controller('MyController', function() { this.names = ['john', 'bob']; }); </script>
  27. SPA is… • Many assets files • JavaScript, CSS, template…

    • Hard to manage concatenating with Grunt • Increase a build time…
  28. gulp • Stream base build system • Simple tasks pipe

    as stream • Programmable not configurable • Simple API • task, run, watch, src, dest 2014
  29. CoffeeScript Stream pipe Src files Stream pipe gulp.src coffee Stream

    pipe Stream pipe gulp.dest Files dest files
  30. var gulp = require('gulp'); var concat = require(‘gulp-concat'); var coffee

    = require('gulp-coffee'); var uglify = require('gulp-uglify'); var coffeeFiles = './src/**/*.coffee'; gulp.task('compile', function(){ gulp.src(coffeeFiles) ����.pipe(coffee()) .pipe(concat(‘app.js’)) .pipe(uglify()) .pipe(gulp.dest(‘dist’)); }); gulp.task(‘watch’, function() { gulp.watch(coffeeFiles, ['compile']); });
  31. browserify • substack • Browserify lets you require('modules') in the

    browser by bundling up all of your dependencies. • No more concatenating which is depending on the order • It makes possible to share code between the browser and server. 2013
  32. ECMAScript 2015 • ECMAScript 6 • JavaScript is more powerful.

    • Class, Modules, Arrow Function, Promise… • Destructuring assignment — • Browsers haven’t supported all features yet. 2015 June
  33. class Person { method(val=“default”) { console.log(val); } method2(...array) { return

    new Promise((resolve, reject) => { setTimeout(() => { resolve(array.map(val => val * 2)); }, 1000); }); } } const person = new Person(); person.method2(1, 2, 3).then(array => console.log(array)); // [2, 4, 6] const user = {name: ‘Jim’, age: 20}; const {name, age} = user;
  34. Babel • Sebastian McKenzie • JavaScript transpiler • Use next

    generation JavaScript, today. • We can use ECMAScript 2015 now! • Stage option (default is stage2) ʙ 5.x 2014
  35. TC39 • Technical Committee 39 • proposals into 4 stages

    • Stage 0 - Strawman • Stage 1 - Proposal • Stage 2 - Draft • Stage 3 - Candidate • Stage 4 - Finished
  36. Service Workers • JavaScript is more powerful. • Run independently

    of web pages. • Intercept Request • Offline / Cache • Background Sync • Push Notification • HTTPS Only
  37. // index.js if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js').then( sw =>

    console.log('success'), err => console.log('error', err) ); } // sw.js self.addEventListener('install', sw => console.log('oninstall')); self.addEventListener('fetch', ev => { if (ev.request.url.indexOf('test') !== -1) { ev.respondWith(new Response('Hello Service Worker')); } });
  38. Extensible Web • The Extensible Web Manifesto • https://extensiblewebmanifesto.org/ •

    New low-level capabilities • Virtuous cycle • Prioritize efforts • Web Components ➜ Polymer
  39. React.js • Facebook • Stateless Component • Mutability ➜ Complexity

    • Declarative programming • VIRTUAL DOM • Isomorphic! 2014
  40. class App extends React.Component { constructor(...args) { super(args); this.state =

    {count: 0}; } onClick() { this.setState({count: this.state.count + 1}); } render() { const {count} = this.state; return ( <div> <p>{count}</p> <button onClick={this.onClick.bind(this)}>click</button> </div> ); } } React.render(<App />, document.getElementById(‘app’));
  41. Functional Reactive Programming • Asynchronous data streams • A stream

    is a sequence of ongoing events ordered in time. • Mouse event, touch event, fetch response… • Observer and observable • Rx.js, Bacon.js, ECMAScript Observable(stage1)
  42. const $ = document.querySelector.bind(document); const plus = Rx.Observable.fromEvent($('#plus'), 'click'); const

    minus = Rx.Observable.fromEvent($('#minus'), 'click'); plus .map(1) .merge(minus.map(-1)) .scan((acc, value) => acc + value) .subscribe(value => sum.textContent = value) ;
  43. click plus click minus click minus click plus click plus

    plus.map(1) minus.map(-1) scan((acc, value) => acc + value) -1 1 -1 1 1 1 0 -1 0 1
  44. Redux • Inspired by Flux and Elm • Actions, A

    Store, Reducers • Reducers are pure functions • (state, action) => state • State is read-only • Single source of truth
  45. Reducer Component Reducer Component Store messages: [‘hello’] filter: ALL type:

    ADD_MESSAGE text: ‘hoge’ messages => messages.concat(action.text) filter => action.filter Action type: FILTER text: UNREAD Action Reduce Reduce subscribe
  46. import { createStore } from 'redux'; // Reducer function counter(state

    = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } } const store = createStore(counter); const unsubscribe = store.subscribe(() => console.log(store.getState())); store.dispatch({ type: 'INCREMENT' }); // 1 store.dispatch({ type: 'INCREMENT' }); // 2 store.dispatch({ type: 'DECREMENT' }); // 1 unsubscribe();
  47. Unix philosophy • Small is beautiful. • Make each program

    do one thing well. • Build a prototype as soon as possible. • Choose portability over efficiency. • Store data in flat text files. • Use software leverage to your advantage. • Use shell scripts to increase leverage and portability. • Avoid captive user interfaces. • Make every program a Filter.