One code to rule them all

The short story about ultimate web app architecture

Dominik Lubański

14.02.2018

Fronted Architect at Shedul.

Web Components enthusiast

Author of some JS on GitHub

Ultimate App Architecture

simpleicon.com Collection Of Flat Icon, Symbols And Glyph Icons

Single Page App

React, Angular, Ember, etc.

Codebase in JavaScript

Native Mobile App

iOS / Android SDK

Codebase in Swift, Java, etc.

Native Mobile App

React Native, Angular + NativeScript, 

Codebase in JavaScript

Hybrid Mobile App

Cordova + React, Angular, Ember, etc.

Codebase in JavaScript

simpleicon.com Collection Of Flat Icon, Symbols And Glyph Icons

Single Page App + Hybrid App

React, Angular, Ember, etc.

Codebase in JavaScript

"When we built a cross-platform app"

react, react-isomorphic-render
redux, reselect, redux-form
webpack, universal-webpack, babel, eslint
cordova, cordova-plugin-*

Fresha development stack

Native feeling

Universal design

Touch feedback

Navigation control

UI transitions

Performance?

Universal design

iPhone

Nexus 6P

iPad

Universal design

Laptop 1280px

Laptop 425px

Touch feedback

Google Maps

Native Android App

Google Maps Go

PWA (JS, HTML, CSS)

CSS pseudo classes

.my-button {
  color: black;
}

.my-button:hover,
.my-button:active {
  color: red;
}

Action HOC

@Action // impl. touch and mouse events
class Button extends React.PureComponent {
  static propTypes = {
    isHover: PropTypes.bool,
    isActive: PropTypes.bool,
    ...
  }

  render() {
    const { isHover, isActive, ...props } = this.props;
    const classes = classNames({ isHover, isActive });

    return (
      <button className={classes} {...props}>
        ...
      </button>
    );
  }
}

Fresha

Hybrid App (JS, HTML, CSS)

Navigation control

Back button behavior

Google Maps Go

PWA (JS, HTML, CSS)

UI transitions

Fresha

Hybrid App (JS, HTML, CSS)

Twitter

Native App

Twitter Lite

PWA (JS, HTML, CSS)

Performance?

Helpful patterns

<Box> Model

@Action
export default class Button extends PureComponent {
  ...

  render() {
    ...

    return (
      <Ripple
        className={classes}
        {...props}
        hasAction
      >
        <Box
          className={style.content}
          as="span"
          flex="row"
          alignItems="center"
          justifyContent="center"
        >
          {isPending && ...}
          {children}
        </Box>
      </Ripple>
    );
  }
}

Views/Components separation

./components/

Allowed CSS, spread props,
no connection to the redux store 

./views/

Forbidden CSS,
composition of the components,
connected to the redux store 

Pros and cons

One codebase - faster development,
one team, etc.

The best possible mobile experience on web

Struggle with Web APIs
and cordova plugins

Thank you

Questions?

Made with Slides.com