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

From Hacker to Developer

From Hacker to Developer

Developing with Webpack, Babel, and React

Joseph Chiang

October 01, 2015
Tweet

More Decks by Joseph Chiang

Other Decks in Technology

Transcript

  1. FROM HACKER 

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

    View full-size slide

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

    View full-size slide

  3. Tag Soup in JS
    if (inlineTileOptions['show_sharing'] === "1") {
    // Inline Sharing Buttons
    var tileSharing = $('');
    tileSharing.append(tileShareButtons);
    item.append(tileSharing);
    !
    var shareText = t['share_text'] ? t['share_text'].replace(/["']/g, '\\$&') : '';
    !
    if (t['source'] != 'facebook') {
    tileShareButtons.append('!
    if (t['image']) {
    tileShareButtons.append('title="Share" onclick="Widget.googleShare(this)">title="Email a friend" onclick="Widget.emailShare(this)">!
    !
    }
    Difficult to read and maintain

    View full-size slide

  4. Tag Soup in View
    Difficult to read and maintain

    View full-size slide

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

    View full-size slide

  6. Environments
    Too many environments
    Feature Detection
    Browser Support
    Hacks
    Responsive

    View full-size slide

  7. 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

    View full-size slide

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

    View full-size slide

  9. 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.

    View full-size slide

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

    View full-size slide

  11. 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.”

    View full-size slide

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

    View full-size slide

  13. 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

    View full-size slide

  14. Universal Loader
    Foundation

    View full-size slide

  15. 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');

    View full-size slide

  16. Package Management
    CSS Preproccessors
    JS Module Loaders
    JS Transpiler
    Build Tools

    View full-size slide

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

    View full-size slide

  18. 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

    View full-size slide

  19. // 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/

    View full-size slide

  20. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  23. 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<br/>• The images inside will be converted to Data URIs.<br/>Define dependencies between JS and CSS<br/>

    View full-size slide

  24. Code Splitting
    fluid-embed.js

    (required) when layout = portrait or landscape
    Load extra assets conditionally
    lightbox.js

    (optional)

    View full-size slide

  25. Dev Server
    Incremental build instead of full build

    View full-size slide

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

    View full-size slide

  27. Using the future of JS, Today!
    Accelerator

    View full-size slide

  28. 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

    View full-size slide

  29. 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

    View full-size slide

  30. 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.

    View full-size slide

  31. 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

    View full-size slide

  32. `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/

    View full-size slide

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

    View full-size slide

  34. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  37. 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)

    View full-size slide

  38. App
    Build UI & APPs

    View full-size slide

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

    View full-size slide

  40. • 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?

    View full-size slide

  41. 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

    View full-size slide

  42. Abstraction
    size="medium" !
    solid>Delete
    Button
    New Way
    Using Class Names
    Using React.js
    Old Way
    Legible & Less Guessing

    View full-size slide

  43. 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

    View full-size slide

  44. 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 !
    kind={state.kind} !
    size={state.size} !
    solid={state.solid} !
    active={state.active}>!
    {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

    View full-size slide








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

    View full-size slide








  46. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  49. 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?

    View full-size slide

  50. 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

    View full-size slide

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

    View full-size slide






  52. Getting Better & Mature



    !
    !
    !

    View full-size slide






  53. 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

    View full-size slide

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

    View full-size slide