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

Conquering Mobile with JavaScript (June 2019)

Conquering Mobile with JavaScript (June 2019)

[UPDATED June 2019] Are you looking for a comprehensive mobile development strategy that can help you deliver “the right” mobile app for every project? Look no further. In these workshop slides, we’ll explore a complete workflow for building mobile apps with JavaScript (and TypeScript) that can be applied to any mobile project. From achieving maximum reach with Progressive Web Apps, to delivering maximum richness with native apps powered by JavaScript (via NativeScript), the techniques in this workshop will give you the tools you need to make sure your mobile app projects don’t fail. We'll even explore techniques for sharing code between PWAs and {N} for maximum flexibility.

Todd Anglin

June 10, 2019
Tweet

More Decks by Todd Anglin

Other Decks in Technology

Transcript

  1. 1. We've built apps, we need a better way 2.

    We're tired of maintaining web AND apps
  2. What we thought. Web Presence Mobile Web Presence iOS app

    Android app Voice skills Chat bots My problem Some else's problem
  3. Reality. Web Presence Mobile Web Presence *Required *Required iOS app

    Android app Preferred for high transaction apps Voice skills Coming soon Chat bots Your problem
  4. Top 3 Problems with "App Strategy v1" 1. Built native

    apps for iOS, Android – too expensive 2. Built hybrid apps – too slow, too janky 3. Built web apps – too limited
  5. Reality. Web Presence Mobile Web Presence *Required *Required iOS app

    Android app Preferred for high transaction apps Voice skills Coming soon Chat bots
  6. No compromises PWA iOS app Android app Maximum reach, discoverability

    "Light" experience Unlimited power, capability "Premium" experience
  7. We'll be using JavaScript § It's everywhere § It's the

    web § With TypeScript, it's familiar and easy
  8. Learning Goals for Today 1. Understand PWAs § What are

    they (really)? § How do you get started? § How do you debug? 2. Understand NativeScript § What is it (really)? § How do you get started? § How do you debug? 3. Understand code sharing § What is it? Why do you need it? § How do you get started?
  9. What are PWAs (really)? Why do we need them? And,

    what ever happened to Responsive Web Apps?
  10. Evolution of the web Web 1.0 Responsive Web Design Progressive

    Web Apps Foundation Design for all Screens Design for offline
  11. Pillars of PWA 1. Reliable 2. Fast 3. Engaging 1.

    Progressive 2. Responsive 3. Connectivity independent 4. App-like 5. Safe 6. Discoverable 7. Re-engageable 8. Installable 9. Linkable
  12. "Progressive Web Apps use modern web capabilities to deliver an

    app- like user experience." "Progressive Web Apps work everywhere but are supercharged in modern browsers. ."
  13. Application Shell My App My App Settings Account Something else

    My App 80º Orlando 20º Boston Shell Content Cached on first visit Loaded from network
  14. Approaches to PWA 1. App Shell + Server-Side Render (SSR)

    for Entry Pages 2. App Shell + Client-Side Render (CSR) for Content 3. Full SSR SSR == Server-Side Rendering
  15. Image source: "Your First Progressive Web App", Google Developers •

    App shell method • Make it work offline • Using Angular
  16. Service Worker § It's just a separate JavaScript file §

    Special type of web worker focused on controlling network requests § Runs separate from main thread § Can run in the background (when no tab open) § No direct DOM access § Communicates with main thread via postMessages § One service worker "per scope" § Updated (at least) every 24 hours
  17. Service Worker fetch cache API for retrieving content from the

    network API for storing/retrieving cached app content/data
  18. Service Worker Lifecycle First Install 1. register 2. install 3.

    activate 4. idle Updates 1. install 2. waiting 3. activate 4. idle navigator.serviceWorker.register('./service-worker.js')
  19. Cache strategies § Cache Only § Network Only § Cache

    First, Fallback on Network § Cache First, Then Network § Cache and Network Race § Network First, Fallback on Cache § Generic Fallback
  20. Cache Only For "static" resources that change with "versions" of

    your site Page Cache Service Worker 1 2 3
  21. Network Only For resources that cannot (or should not) be

    cached Page Network Service Worker 1 2 3
  22. Cache First, Fallback on Network Primary offline-first pattern: load from

    cache if available, otherwise fetch Page Cache Service Worker Network x 1 2 3 4
  23. Network First, Fallback on Cache Load new content by default,

    or show cache if offline Page Cache Service Worker Network x 1 2 3 4
  24. Cache First, Then Network Display cached resource immediately, then update

    when network responds Page Cache Service Worker Network 1 1 2 2 3
  25. Cache and Network Race For cases where disk access may

    be slower than network response Page Cache Service Worker Network 1 2 2 3 x 3
  26. Generic Fallback For stuff that's not available in the cache

    OR on the network Page Cache Service Worker Network 1 2 3 x 5 x 4
  27. § JavaScript library to handle service worker boilerplate workbox.routing.registerRoute( new

    RegExp('^https://fonts.(?:googleapis|gstatic).com/(.*)'), workbox.strategies.cacheFirst(), ); workbox.routing.registerRoute( /\.(?:js|css)$/, workbox.strategies.staleWhileRevalidate(), );
  28. § PWA schematic automatically creates and manages service worker $

    ng add @angular/pwa --project *project-name* $ ng build --prod
  29. ngsw-config.json assetGroups § Static resources versioned with your app §

    App shell, images, styles, etc § installMode/updateMode § lazy § prefetch dataGroups § Caching policy for resources not versioned with your app § API responses § cacheConfig § maxSize (# of entries) § maxAge § timeout § strategy § performance § freshness
  30. Web App Manifest § Evolution of mobile meta tags §

    Control PWA's home screen icon, splash screen, theme colors, start URL § Helps PWA feel more "app like" (on Android) <link rel="manifest" href="/manifest.json">
  31. Image Source: Addy Osmani, https://addyosmani.com/blog/getting-started-with-progressive-web-apps/ Web App Install banner Requires:

    • Web App Manifest • HTTPS • Registered Service Worker • “Engagement heuristic” • 2 visits, at least 5 min between visits • 30 seconds “interacting” with domain
  32. Install Prompt § Events: § beforeinstallprompt § appinstalled Opportunity to

    intercept browser install banner and control when it is displayed
  33. Image Source: Addy Osmani, https://addyosmani.com/blog/getting-started-with-progressive-web-apps/ Home screen icon & splash

    screen Define: • App icon • App name • App theme color • Splash screen background color • Orientation limits
  34. • name • short_name • icons • dir • lang

    Control Home Screen • start_url • display • fullscreen, standalone, minimal-ui, browser • orientation • any, natural, landscape, portrait, landscape-preferred, landscape-secondary, portrait- preferred, portrait-secondary • background_color • theme_color Control App Behavior • description • related_ applications • prefer_ related_ applications • scope Extras
  35. Hosting § Azure for Static Sites § Uses Azure Storage

    § SUPER simple with VS Code § PWA friendly Azure account VS Code Azure Storage Plugin
  36. Background Sync // Register your service worker: navigator.serviceWorker.register('/sw.js'); // Then

    later, request a one-off sync: navigator.serviceWorker.ready.then(function(swRegistration) { return swRegistration.sync.register('myFirstSync'); }); self.addEventListener('sync', function(event) { if (event.tag == 'myFirstSync') { event.waitUntil(doSomeStuff()); } }); In app js: In service worker:
  37. [2] Requires full browser to be running to receive messages

    [3] Apple has custom API for desktop Safari
  38. iOS & Safari § Some PWA features coming soon §

    BUT some potentially problematic differences
  39. Notable limits on iOS § Limited to 50 MB (files

    and data) § No background sync (or background execution) § No ability to lock screen orientation § No app splash screen* § No “installation” UX § Less control over status bar styling § PWAs ”restart” every time the user switches apps § PWAs don’t work in non-default iOS browsers (Chrome, Brave, etc) § Auto-purged PWA cache for infrequently used apps
  40. When to PWA § Content centric apps § Read only

    OR apps with simple inputs § No user expectation of App Store install § No need for extensive device hardware access § Less need for on device encryption, storage
  41. All web apps should implement PWA for a better web.

    (But you may still want a native mobile app.)
  42. Download the NativeScript Playground & Preview apps PWA Weather App

    Source: https://github.com/toddanglin/NsPwaWeather While you wait…
  43. Hybrid (& PWA) Promise 100% Web 100% Native Hybrid Reach

    Code/Skill Reuse Richness Premium experience Device APIs Best of both?
  44. "Hybrid" Web UI with selective access to native APIs Native

    App Shell WebView Plugins Plugins Entire app lives here
  45. Native App "JavaScript-driven Native" Native UI driven by JavaScript Native

    UI JavaScript-to-Native bridge JavaScript Engine (Your app code runs here) Native APIs
  46. “JavaScript-driven Native” • Share code • Reuse existing skills/teams •

    Reuse existing libraries • Native UI • Full access to device APIs • Immediate access to new OS features Fast to market Best experience
  47. • Open source • Cross-platform • JavaScript/TypeScript • Native iOS

    & Android UI Reuse web skills and libraries to build better mobile apps
  48. Building a {N} app <page> <stacklayout> <label id=“myLbl” text=“Hello World”>

    </label> </stacklayout> </page> 1) Layout views 2) Style with CSS Page { background-color: #333; color: #000; padding: 10; } 3) Control with JS submit() { alert(“You did it!”); } Deploy native apps to iOS and Android
  49. 0% 50% 100% Sep '17 Oct '17 Nov '17 Dec

    '17 Jan '18 Feb '18 Mar '18 Apr '18 May '18 Jun '18 Jul '18 Aug '18 Sep '18 Oct '18 Nov '18 Dec '18 Jan '19 Feb '19 CLI Template Usage Angular Pure JavaScript Pure TypeScript Vue.js
  50. MYPUMA puts wholesale fashion in the pocket of buyers and

    allows them to purchase PUMA's latest styles anywhere, anytime. NativeScript enables premium app experiences and easy access to iOS and Android users.
  51. Starting a new project (CLI) $ npm install –g nativescript

    $ tns create MyFirstProject --ng $ tns preview
  52. Instantly start developing with {N} in a browser • Fastest

    way to get started with {N} • Support for Angular and Vue
  53. NativeScript Module Layer (NML) § Abstractions on native APIs that

    provide unified, cross- platform API § Dozens available out of the box § Easy for developers to add § IMPORTANT: All native APIs still available at JavaScript layer for platform- specific scenarios § NativeScript modules follow Node module’s conventions (CommonJS).
  54. AR/VR Support • Support for ARKit and ARCore • Support

    for iOS vector type • Image Tracking and Face Tracking (iOS) • Load 3D models • Interact with planes
  55. Image source: "Your First Progressive Web App", Google Developers •

    App shell method • Make it work offline • Using Angular
  56. Pages § XML markup structure § Elements (e.g. <Page>, <Label>)

    are NativeScript modules Angular Gotcha Must use closing tags with Angular
  57. Layouts: FlexBox <div style="display: flex;"> </div> == These are the

    same == <FlexboxLayout> </FlexboxLayout> Supported Flex properties: § Set flex properties via XML, CSS or JS § Uses same syntax as web § Use FlexboxLayout as root element § Same as HTML <div /> with "display: flex;" § Multiple FlexboxLayouts can be nested For containers: • flex-direction • flex-wrap • flex-flow • justify-content • align-items • align-content For children: • order • flex-grow • flex-shrink • flex • align-self • flex-wrap-before
  58. UI Widgets § Button § Label § TextField § TextView

    § SearchBar § Switch § Slider § Progress § ActivityIndicator § Image § ListView § HtmlView § WebView § TabView § SegmentedBar § DatePicker § TimePicker § ListPicker § Dialogs Out-of-the-box Native UI widgets means… • Native behavior • Native perf • Native accessibility • Parity with “native”
  59. NativeScript UI (free) • ListView • SideDrawer • Calendar •

    Chart • DataForm • Gauges • AutoComplete
  60. CSS Convention: app.css <-- Global styles [viewName].css <-- View styles

    [viewName].[platform].css @Component({ ... styleUrls: ["./items.component.css"] })
  61. Supported Properties § color § background-color § background-image § background-repeat

    § background-position § background-size § border-color § border-width § border-radius § font § font-family § font-size § font-style § font-weight § text-align § text-decoration § text-transform § vertical-align § horizontal-align § margin § margin-top § margin-right § margin-bottom § margin-left § width § height § min-width § min-height § padding § padding-top § padding-right § padding-bottom § padding-left § visibility § opacity
  62. Supported Selectors § Element § button { color: red; }

    § Class § .mybutton { color: green; } § ID § #myButton { color: #FFF; } § Hierarchical § button .mybutton { … } § button > .mybutton { … } § Attribute § button[attr] { … } § button[attr='val'] { … } § Pseudo § button:highlighted { … }
  63. Theme Core § Bootstrap for {N} § Pre-defined CSS classes

    to quickly give apps a polished look-and-feel § iOS and Android $ npm install nativescript-theme --save
  64. Theme for text <Label text="Name" class="text- primary text-right"></Label> <Label text="Email"

    class="text- danger"></Label> Change text color: - text-primary, text- muted, text-danger Change text alignment: - text-center, text- left, text-right to Apply text transformation - text-lowercase, text- uppercase, text-capitalize
  65. Theme for buttons <Button text="Primary" class="btn btn- primary"></Button> <Button text="Outline"

    class="btn btn- outline"></Button> <Button text="Orange" class="btn btn-primary btn- ornage"></Button> <Button text="Rounded Grey" class="btn btn-primary btn-grey btn-rounded- sm"></Button>
  66. Custom Fonts 1. Use TTF or OTF fonts 2. Put

    fonts in: app > fonts 3. Use in CSS .icon { font-size: 30; font-family: 'FontAwesome'; }
  67. Icon Font Helper § Angular pipe for handling icon fonts

    <Label class="fa" text="\uf293"></Label> <Label class="fa" [text]="'fa-bluetooth' | fonticon"></Label> npm install nativescript-ngx-fonticon --save
  68. Pipes § Transform bound data import { Pipe, PipeTransform }

    from "@angular/core"; @Pipe({ name: "myPipeName" }) export class MyPipe implements PipeTransform { transform(value: number): any { // Do something return newValue; } }
  69. TIP § Platform specific capabilities are always available § JavaScript:

    <view>.android or <view>.ios § Markup: <android></android> or <ios></ios> § Attributes: android:<attribute> or ios:<attribute> § Ex: <label android:class="…" ios:class="…" /> Write once by default. Target specific platform capabilities when needed.
  70. [ value ] or {{ value }} = One way

    binding from class to view
  71. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <input value=”{{ message }}”> ` }); export class AppComponent { message: 'Root Component' } app.component.ts
  72. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <input [(ngModel)]=”message”> <button (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  73. Two-way binding import { NativeScriptFormsModule } from 'natives cript-angular/forms'; …

    imports: [ NativeScriptModule, AppRoutingModule, NativeScriptHttpModule, NativeScriptFormsModule ], § You also need to add NativeScriptForms Module to @NgModule imports
  74. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <label [text]=”message”> <button (tap)=“showMessage($event)”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  75. Handling Events tap label.on(gestures.GestureTypes.tap, function (args) { console.log("Tap"); }); swipe

    label.on(gestures.GestureTypes.swipe, function (args) { console.log("Swipe Direction: " + args.direction); }); Multiple events label.on("tap, doubleTap, longPress", function (args) { console.log("Event: " + args.eventName); }); § Tap § Double Tap § Long Press § Swipe § Pan § Pinch § Rotation § Touch
  76. import { Injectable } from ”@angular/core” export class MessageService {

    message: string = ”Service Message” } message.service.ts
  77. import { Injectable } from ”@angular/core” @Injectable() export class MessageService

    { message: string = ”Service Message” } message.service.ts
  78. import { Component } from ”@angular/core” @Component({ selector: 'app', template:

    ` <input [(ngModel)]=”message”> <button (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  79. import { Component } from ”@angular/core” import { MessageService }

    from ”./message.service” @Component({ selector: 'app', template: ` <input [(ngModel)]=”message”> <button (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: 'Root Component’; showMessage() { alert(this.message); } } app.component.ts
  80. @Component({ selector: 'app', providers: [MessageService] template: ` <input [(ngModel)]=”message”> <button

    (click)=“showMessage()”>Show Message</button> ` }); export class AppComponent { message: string; showMessage() { alert(this.message); } constructor(MessageService _messageService) { this.message = _messageService.message; } app.component.ts
  81. “If debugging is the process of removing software bugs, then

    programming must be the process of putting them in.” - Edsger Dijkstra
  82. Debugging Strategies § Debug by alert (no really) § Debug

    by console.log § Debug by Developer Tools § Debug by IDE § Visual Studio § Visual Studio Code
  83. Web + Mobile Code Sharing • Build for web and

    mobile in one project • Leverages Angular schematics • Share business logic, routing
  84. Sharing DO share: - Routes - Services - Component definitions

    (common behavior) - (Some) Styles DON’T share: - UI layer - NgModules
  85. Code Splitting Strategies Polyfills • Make web APIs work in

    {N} Helpers • Inject services to handle specific functions differently for web & {N} Separate files • Create separate files for web & {N}
  86. Options § Start with a new project § Convert an

    existing Angular web project § Convert an existing {N} project (coming soon) $ ng add @nativescript/schematics $ ng g migrate-module --name=home $ ng new -c=@nativescript/schematics project-name --shared Migrate New
  87. Why do this? § Improve developer workflow across web, mobile

    § Share more code/assets between web, mobile § Deliver web, mobile updates simultaneously
  88. No compromises PWA iOS app Android app Maximum reach, discoverability

    "Light" experience Unlimited power, capability "Premium" experience +
  89. • Largely read-only • Simple user interactions • Mostly dynamic

    content • No need to access device APIs • No need for encrypted device storage • Web distribution • Frequently used • More complex user interactions • Need for access to device APIs • Need for encrypted storage • App store distribution PWA