Slide 1

Slide 1 text

FROM HACKER 
 TO PROGRAMMER Developing with Webpack,Babel, and React @josephj6802 1 Oct 2015

Slide 2

Slide 2 text

Hacker? Probably Worse… Inefficient or dirty works Sadly especially for front-end code

Slide 4

Slide 4 text

Tag Soup in View Difficult to read and maintain

Slide 5

Slide 5 text

CSS/JS Tags Impossible to remove no longer used scripts No Dependency

Slide 6

Slide 6 text

Environments Too many environments Feature Detection Browser Support Hacks Responsive

Slide 7

Slide 7 text

Copy Paste fluid.js fluid-horizontal.js base_waterfall.js base_carousel.js auto.js main.js carousel.js slideshow.js base_billboard.js base_feed.js base_slideshow.js 80% duplicated code (~1500 lines) * 11 Widget Code Once we start, it’s difficult to refactor

Slide 8

Slide 8 text

Prototype-based Class Everyone has their own implementation Stackla.createClass(); Widget = (function () {})(); function StacklaWidgetNode() {}

Slide 9

Slide 9 text

Global Variables Global variables and function names are an incredibly bad idea. The reason is that every JavaScript file included in the page runs in the same scope. If you have global variables or functions in your code, scripts included after yours that contain the same variable and function names will overwrite your variables/functions.

Slide 10

Slide 10 text

Stoyan Stefanov The few man-hours spent writing the code initially end up in man-weeks spent reading it. Getting Worse

Slide 11

Slide 11 text

Eliminate the hacking As a developer, we always seek for good methodologies, patterns, or better technologies to make our code to be maintained easier. “A bug could be fixed within 10 mins by a newbie, but a good developer is willing spend 4 hours to make it better.”

Slide 12

Slide 12 text

Happy Developer! when using right tools & code become less messy

Slide 13

Slide 13 text

Universal loader for all static assets Ability to write next-generation JS Lead and change the world of front-end app development Foundation Accelerator App New Web Development Stacks

Slide 14

Slide 14 text

Universal Loader Foundation

Slide 15

Slide 15 text

JS Module Before Webpack AMD Make use of global variables Ease of define dependencies No dependencies Load modules asynchronously No compile needed by default Ease of define dependencies Always need to compile Synchronous loading by a single file (via global) define(['./a', './b'], function (a, b) {! }); var Acl = require('js/acl/acl.js');

Slide 16

Slide 16 text

Package Management CSS Preproccessors JS Module Loaders JS Transpiler Build Tools

Slide 17

Slide 17 text

https://www.flickr.com/photos/juhansonin/3141561416/ You’ll need… Not fun… A lot of plug-ins and some hacks..

Slide 18

Slide 18 text

Package Management CSS Preproccessors JS Module Loaders JS Transpiler Build Tools less-loader sass-loader coffee-loader ts-loader Support ALL JS STATIC 
 Modules Webpack Dev Server

Slide 19

Slide 19 text

// app/media/js/admin/terms/term-manage.jsx! ! 'use strict';! ! var React = require('react'),! $ = require('jquery'),! LogMixin = require('common/log-mixin'),! TermPanel = require('./term-panel'),! TermList = require('./term-list'),! History = require('exports?window.History!history.js/native.history'),! queryString = require('query-string'),! Cookies = require('js-cookie');! ! module.exports = {! // ...! }; Define Dependencies app/vendor/webpack/node_modules/ app/media/js/ app/media/components/

Slide 20

Slide 20 text

var History = require('exports?window.History!history.js/native.history');! ! History.Adapter.bind(window, 'statechange', that.handleHistoryChange); Global Module require('history.js/native.history');! ! window.History.Adapter.bind(window, 'statechange', that.handleHistoryChange); Not Good Better exports?window.History!history.js/native.history loader loader options (query) separator module path

Slide 21

Slide 21 text

JS Transpilers var Tagla = require('coffee!./tagla.coffee'); var Stepper = require('ts!./stepper.js');

Slide 22

Slide 22 text

CSS Preprocessors require('!style!css!sass!admin/acl/acl.scss'); require('!style!css!less!bootstrap/nav.less');

Slide 23

Slide 23 text

CSS Preprocessors Wait! Are you writing CSS in JS? require('!style!css!sass!admin/acl/acl.scss'); app/media/js/admin/acl/acl.js • The stylesheet will be injected into HTML with tag • The images inside will be converted to Data URIs. Define dependencies between JS and CSS

Slide 24

Slide 24 text

Code Splitting fluid-embed.js
 (required) when layout = portrait or landscape Load extra assets conditionally lightbox.js
 (optional)

Slide 25

Slide 25 text

Dev Server Incremental build instead of full build

Slide 26

Slide 26 text

• Module Loader / Dependencies • Ability to load all kinds of assets • High performance • Often replaces grunt or gulp

Slide 27

Slide 27 text

Using the future of JS, Today! Accelerator

Slide 28

Slide 28 text

Package Management CSS Preproccessors JS Module Loaders JS Transpiler Build Tools sass-loader coffee-loader ts-loader Support ALL Modules Webpack Dev Server babel-loader less-loader

Slide 29

Slide 29 text

Why Babel? All transpilers are trying to *fix* JavaScript language These transpilers have obvious influence on the ES6/ES2015 standard. However browser support is not ready yet

Slide 30

Slide 30 text

Why Babel? Babel is another transpiler which let you to use latest JS Babel keeps sync with ECMAScript Ability to customise the stage or options you want use.

Slide 31

Slide 31 text

var: Function-scoped Let & Const function f() {! var obj = {a: 1, b: 2, c: 3}; ! for (var i in obj) {! // okay! console.log(i); ! } ! // okay ! console.log(i);! }! f(); let: Block-scoped function f() {! var obj = {a: 1, b: 2, c: 3}; ! for (let i in obj) {! // okay! console.log(i); ! } ! // error - i is undefined ! console.log(i);! }! f(); const: Block-scoped function a() {! const DURATION = 100;! {! // output 100! console.log(DURATION);! }! }! ! function b() {! const DURATION = 100;! {! // error "DURATION" is read-only! DURATION = 200;! } ! }! ! function c() {! const DURATION = 100;! {! // ok ! const DURATION = 200;! console.log(DURATION); // output 200! } ! }! Single-assigment

Slide 32

Slide 32 text

`Template String` // This is what I prefer to do! var list = ['
    ',! '
  • Buy Milk
  • ',! '
  • Be kind to Pandas
  • ',! '
  • Forget about Dre
  • ',! '
'].join(''); ES5 // This doesn't work! var list = '
    !
  • Buy Milk
  • !
  • Be kind to Pandas
  • !
  • Forget about Dre
  • !
';! // This does, but urgh… ! var list = '
    \!
  • Buy Milk
  • \!
  • Be kind to Pandas
  • \!
  • Forget about Dre
  • \!
'; // This is the most common way, and urgh, too…! var list = '
    ' +! '
  • Buy Milk
  • ' +! '
  • Be kind to Pandas
  • ' +! '
  • Forget about Dre
  • ' +! '
'; ES6 // This works!! var list = `
    !
  • Buy Milk
  • !
  • Be kind to Pandas
  • !
  • Forget about Dre
  • !
`;! http://christianheilmann.com/2015/08/28/es6-for-now-template-strings/

Slide 33

Slide 33 text

`Template String` ES5 - String + Variables var avatar = ''; var avatar = ``; ES6 - String + Variables The ${} construct can take any JS expression that returns a value

Slide 34

Slide 34 text

class Widget extends Stackla.Base {! constructor(options) {! super(options);! ! this.domain = options.domain || null;! this.list_url = `/widget/api/${this.guid}! ?filter_id=${this.filter_id}! &domain=${this.domain}! &page=1! &ttl=1`; ! }! render(el) {! super.render();! }! static getInstances() {! // ...! }! } Classes ES6 - Single convenient declarative form

Slide 35

Slide 35 text

Module https://babeljs.io/docs/learn-es2015/#modules

Slide 36

Slide 36 text

Arrow https://babeljs.io/docs/learn-es2015/#arrows-and-lexical-this

Slide 37

Slide 37 text

Summary • Unlike CoffeeScript, it’s something you must learn and use in the future. • Just like PHP4 v.s. PHP5 • Makes my code more legible (ex. class) • develop much faster (ex. less vague, type safety)

Slide 38

Slide 38 text

App Build UI & APPs

Slide 39

Slide 39 text

Why so Popular? Google Trend http://reactkungfu.com/2015/07/big-names-using-react-js/ Big Brands using React.js

Slide 40

Slide 40 text

• Rethink best practices • JSX - Template in JavaScript? • CSS in JS - Inline style in JavaScript? • Easy to learn • Embracing Functional Programming • One-way data flow model • Impacting different areas • ImmutableJS, GraphQL Why so Popular?

Slide 41

Slide 41 text

Package Management CSS Preproccessors JS Module Loaders JS Transpiler Build Tools sass-loader Support ALL Modules Webpack Dev Server babel-loader less-loader built-in support for React JSX

Slide 42

Slide 42 text

Abstraction Delete Button New Way Using Class Names Using React.js Old Way Legible & Less Guessing

Slide 43

Slide 43 text

f Delete button.jsx exports default class Button extends React.Component {! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! }; this.props.size this.props.kind this.props.solid this.props.children Load CSS Just CSS class name manipulation render() is the only required method in React component import React from 'react';! import cx from 'classnames';! import 'stackla-uikit/scss/_button'; render() {! let that = this,! props = that.props,! className,! node;! ! className = cx('st-btn',`st-btn-${kind}`, {! 'st-btn-disabled': props.disabled,! 'st-btn-solid': props.solid,! 'st-btn-md': (props.size === 'medium'),! 'st-btn-sm': (props.size === 'small'),! 'st-active': props.active,! }, props.className);! ! return {props.children}! } The calculated class names Properties

Slide 44

Slide 44 text

f State import React from 'react';! import Button from './button';! const data = [! {text: 'Danger', kind: 'danger', size: 'large', solid: false, active: true},! {text: 'Success', kind: 'success', size: 'medium', disabled: true, solid: true},! {text: 'Info', kind: 'info', disabled: true, solid: true},! {text: 'Default', kind: 'default', size: 'large', disabled: true, active: false}! ];! exports default class App extends React.Component {! constructor() {! this.offset = 0;! }! componentDidMount() {! setInterval(() => {! this.offset = (data.length >= this.offset + 1) ? 0 : this.offset + 1;! this.setState(data[this.offset]);! }, 500);! }! render() {! let state = this.state;! return ! ! {state.text}! ;! }! }; app.jsx React.render(, document.getElementById('app')); Mockup Data Whenever the state changes, the render() will be invoked For Button component, whenever my property changes, the Button#render() will be invoked

Slide 45

Slide 45 text

Only outmost component is stateful Others are stateless, only accept properties

Slide 46

Slide 46 text

Only outmost component is stateful Others are stateless, only accept properties WidgetsNew StyleChooser StylePreview widgetTypes selectedWidget render() render() render() widgetTypes selectedWidget Top-down Rendering JSX diffs and apply changes to DOM

Slide 47

Slide 47 text

UI = f(state) Update UI by changing state object Philosophy

Slide 48

Slide 48 text

Sebastian Markbåge DOM as a Second-class Citizen https://www.youtube.com/watch?v=Zemce4Y1Y-A

Slide 49

Slide 49 text

A Tool to Build Our Toolbox Only ourselves knows what we want, picking up technologies for right abstraction is crucial. No single library can fulfil our need. Can we build an app without a single DOM element?

Slide 50

Slide 50 text

Abstraction for Different Targets • React.js in Browser • JSX ➡ DOM • react-canvas in Browser • JSX ➡ Canvas • react-isomorphics in Server • JSX ➡ HTML • react-native in iOS • JSX ➡ UIKit • react-native in Android • JSX ➡ android.view

Slide 51

Slide 51 text

Ambitious Abstraction In Browser, React/JSX relies on slow DOM API. Goal Ask WebGL/GPU to use React directly Now

Slide 52

Slide 52 text

➡ ➡ ➡ ➡ ➡ Getting Better & Mature ➡ ➡ ➡ ! ! !

Slide 53

Slide 53 text

➡ ➡ ➡ ➡ ➡ Getting Better & Mature ➡ ➡ ➡ ! ! ! Will these tools go out of fashion in the following 18 months? POSSIBLY! However, everything is becoming 
 more mature and future-compatible We developers just need to choose right tools to do improvements

Slide 54

Slide 54 text

Feel blessed with I feel much more solid to write UI now. Not a hacker but a programmer! $IFFST