First-Class Citizen on Your Device Now
Maxim Salnikov
@webmaxru
The Mobile Web 2.0
We need a mobile app
You: ???
Maxim Salnikov
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3667292/conf-pic.png)
Google Developer Expert in Angular
Mobile Oslo / Angular Oslo / PWA Oslo meetups organizer
Mobile Era conference organizer
Products from the future
UI Engineer at ForgeRock
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/2243060/DTC_Services_1h_hero_bg.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3667287/angular-gde-logo_2x.png)
MobileEra.Rocks
-
All kinds of native mobile development
-
Progressive Web Apps
-
Mobile Web: React Native, NativeScript, Ionic
20% off with code
October 5-6, Oslo
Mobile Users
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916766/USage.png)
2014
October, 2016
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916747/internet_usage_2009_2016_ww.png)
> 2 000 000 000
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916769/statistic_id330695_smartphone-users-worldwide-2014-2020.png)
60X Poland
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916781/Anonymous-Map-of-Poland.png)
Mobile Web
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916817/wap5-158530.gif)
Milestones of the Mobile Web
Hybrid
Web
RWD
Native
?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3910387/logo-jquery-mobile_2x.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3910447/nativescript-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911485/ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911497/react-native.png)
The biggest mistake we’ve made as a company is betting on HTML5 over native.
Mark Zuckerberg
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916824/bubbles.png)
?
Mobile Web 2.0
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Developer Experience
User Experience
Business Experience
How the things work
Ionic
One code base. Running everywhere.
-
Single code base for app stores and web
-
Web app in WebView
-
Powered by Angular
-
Built to native app with Cordova
-
Uses platform APIs via Cordova
Ionic
Open source framework for building truly native mobile apps
NativeScript
NativeScript
-
Uses Angular (not a requirement)
-
Uses JavaScript virtual machines to execute JavaScript commands
-
Direct access to native platform APIs
NativeScript
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3917743/nativescript.png)
React Native
Learn once, write anywhere
React Native
-
Uses "bridge" between JavaScript and native
-
Inspired by React (Virtual DOM, etc)
-
Can be a part of native app
-
Can include modules with native code
React Native
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3917954/scheme-react-native.png)
Progressive Web Apps
Reliable, Fast, Engaging
Progressive Web Apps
-
Takes the best parts from native and web
-
Framework-agnostic
-
Use the latest browser APIs
Progressive Web Apps
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3918093/sw.png)
Developer Experience
Installation, set up, scaffolding
-
Smooth NPM-based installation
-
CLI-based scaffolding
-
Tools to preview/emulate the app
-
Tools to share and deploy
Coding and UI
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Angular
TypeScript
"HTML"
Ionic
<ion-header>
<ion-navbar>
<ion-title>Ionic Blank</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding class="content">
<h2>Tap the button</h2>
<button primary>TAP</button>
<div class="message">16 taps left</div>
</ion-content>
Ionic
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3918917/ionic2-ui.png)
Writing a code
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Angular
TypeScript
"HTML"
Angular?
TypeScript
or
Javascript
XML
NativeScript
<ActionBar title="NativeScript Blank"></ActionBar>
<StackLayout>
<Label text="Tap the button" class="title"></Label>
<Button text="TAP"></Button>
<Label [text]="message" class="message"></Label>
</StackLayout>
NativeScript
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3918942/nativescript-ui.png)
Writing a code
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Angular
TypeScript
"HTML"
Angular?
TypeScript
or
Javascript
XML
React
ES6
JSX
React Native
import React, { Component } from 'react';
import { View, Button, Alert, AppRegistry } from 'react-native';
class MainApp extends Component {
_onPress() {
Alert.alert('I am so pressed!');
}
render() {
return (
<View>
<Button onPress={this._onPress} title="Press me" color="#841584" />
</View>
);
}
}
AppRegistry.registerComponent('MainApp', () => MainApp);
React Native
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919727/buttonExample_copy.png)
Action Bar / iOS
import React, { Component, PropTypes } from 'react';
import { NavigatorIOS, Text } from 'react-native';
export default class NavigatorIOSApp extends Component {
render() {
return (
<NavigatorIOS
initialRoute={{
component: MyScene,
title: 'My Initial Scene',
}}
style={{flex: 1}}
/>
);
}
}
Action Bar / Android
render: function() {
return (
<ToolbarAndroid
logo={require('./app_logo.png')}
title="AwesomeApp"
actions={[{title: 'Settings', icon: require('./icon.png')}]}
onActionSelected={this.onActionSelected} />
)
},
onActionSelected: function(position) {
if (position === 0) { // index of 'Settings'
showSettings();
}
}
Should be noted
-
There are iOS/Android specific limitations of ActionBar in NativeScript
-
There are cross-platform implementations of navigation in React Native (React Native Navigation)
Writing a code
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Angular
TypeScript
"HTML"
Angular?
TypeScript
or
Javascript
XML
React
ES6
JSX
Any framework
Whatever
transpiled to
Javascript
HTML
Progressive Web Apps
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/2781438/react.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919238/vue.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/1733282/shield-large.png)
...a new framework of the week
Hacker News PWA
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919287/hnpwa-logo.png)
-
A spiritual successor to TodoMVC
-
8 implementations at the moment
Progressive Web Apps
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/2297950/javascript-18-638.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/2298477/logo_small.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/2298475/js.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919279/flow-hero-logo.png)
Accessing hardware
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Ionic
Native
Ionic Native
$ ionic cordova plugin add cordova-plugin-camera
$ npm install --save @ionic-native/camera
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919341/ionicnative.gif)
Ionic Native
import { Camera, CameraOptions } from '@ionic-native/camera';
constructor(private camera: Camera) { }
...
const options: CameraOptions = {
quality: 100,
...
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64:
let base64Image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
// Handle error
});
Accessing hardware
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Ionic
Native
Direct access to native APIs
CocoaPods
Plugins
NativeScript
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919475/nativescript-plugins.gif)
$ npm install nativescript-camera --save
NativeScript
import { Component } from "@angular/core";
import { ImageAsset } from "image-asset";
import { takePicture, requestPermissions, isAvailable } from "nativescript-camera";
@Component({
moduleId: module.id,
templateUrl: "./using-camera.component.html"
})
export class UsingCameraExampleComponent {
public imageTaken: ImageAsset;
onTakePhoto() {
let options = {
width: 600,
height: 300,
...
};
takePicture(options)
.then(imageAsset => {
this.imageTaken = imageAsset;
console.log("Size: " + imageAsset.options.width + "x" + imageAsset.options.height);
}).catch(err => {
console.log(err.message);
});
}
}
Accessing hardware
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Ionic
Native
Direct access to native APIs
CocoaPods
Plugins
APIs
Writing native code
Components
React Native
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919478/reactnative-api.gif)
$ npm install react-native-camera --save
$ react-native link react-native-camera
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3919504/reactnative-components.gif)
React Native
import React, { Component } from 'react';
...
import Camera from 'react-native-camera';
class BadInstagramCloneApp extends Component {
render() {
return (
<View>
<Camera
ref={(cam) => {
this.camera = cam;
}}
aspect={Camera.constants.Aspect.fill}>
<Text onPress={this.takePicture.bind(this)}>[CAPTURE]</Text>
</Camera>
</View>
);
}
takePicture() {
const options = {};
//options.location = ...
this.camera.capture({metadata: options})
.then((data) => console.log(data))
.catch(err => console.error(err));
}
}
AppRegistry.registerComponent('BadInstagramCloneApp', () => BadInstagramCloneApp);
Accessing hardware
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3911487/pwa-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916801/icon-ionic-logo.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916803/icon-react-native.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916805/icon-nativescript-logo.png)
Ionic
Native
Direct access to native APIs
CocoaPods
Plugins
APIs
Writing native code
Components
Web APIs
What Web Can Do
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3918187/Screen_Shot_2017-06-16_at_20.29.13.png)
User Experience
Performance
-
No serious performance difference between the native and NativeScript/React Native
-
A hybrid version of an app will never be as fast as a native version
Performance
-
Performance doesn’t matter so much as long as the hybrid app is fast enough
-
Javascript on Chrome for Android became 35% faster during the last year
Business Experience
-
48% of consumers start mobile research with a search engine
-
NativeScript and React Native apps could only be distributed via app stores
-
Ionic goes smart cross-platform approach
Discoverability
-
60% of apps in the Google Play app store have never been downloaded
-
The average user downloads <3 apps per month
-
50% of US smartphone users download 0 apps per month
-
Very expensive to acquire users for mobile apps
App stores...
-
Easy to find
-
Easy to share
-
Easy to install
-
Easy to update
PWA wins!
We need a mobile app
You: !!!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916807/sleepphone.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916808/dont-want-to-wakeup.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/40730/images/3916810/Wake-up-Answer-the-phone.gif)
> 50%
> 1 000 000 000
Dziękuję Ci bardzo
@webmaxru
Maxim Salnikov
Questions?
The Mobile Web Second Edition: First-Class Citizen on Your Device Now
By Maxim Salnikov
The Mobile Web Second Edition: First-Class Citizen on Your Device Now
They are so similar: Web and Mobile apps. What a nice option to use our web development experience (JavaScript, to be specific) to create cross-platform native-like applications. Is it that simple? What are the pros and cons of mobile web VS native? What is the difference between hybrid mobile apps, progressive web apps and JavaScript-compiled-to-native ones? Let's find the answers together! Attendees will get an overview of modern concepts for building web-based mobile applications, pros and cons from tech and business sides. Bonus: some practical advices on when to go for this option. For the each option I'll give advantages/disadvantages from both tech and business points of view so both developers and managers will get a big picture of today's (and tomorrow's) possibilities of the mentioned concept.
- 3,342