SlideShare a Scribd company logo
1 of 100
Download to read offline
Host your own
Over-the-air update service
Roadmap
Buggy Valley App
Glorified cURLing App
Designing an OTA Service
Hosting Your Own Service
OTA Assets
Announcements
Pillar Valley
Pillar Valley
Pillar Valley
My Awesome App
Standing on the shoulders
of giants
Pillar Valley
Buggy Valley
Buggy Valley
$
p = 0.5
$$
Nothingp = 0.5
Buggy Valley
p = 0.5
p = 0.5
Android Java Implementation
String redScreenPath = “file:///red-screen.js”;
String pillarValleyPath = “file:///pillar-valley.js”;
Android Java Implementation
String redScreenPath = “file:///red-screen.js”;
String pillarValleyPath = “file:///pillar-valley.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(redScreenPath);
} else {
loadApp(pillarValleyPath);
}
Android Java Implementation
String redScreenPath = “file:///red-screen.js”;
String pillarValleyPath = “file:///pillar-valley.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(redScreenPath);
} else {
loadApp(pillarValleyPath);**
}
** how does loadApp work?
Quick Recap
String redScreenPath = “file:///red-screen.js”;
String pillarValleyPath = “file:///pillar-valley.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(redScreenPath);
} else {
loadApp(pillarValleyPath);**
}
** how does loadApp work?
Roadmap
Buggy Valley App
Glorified cURLing App
Designing an OTA Service
Hosting Your Own Service
OTA Assets
Announcements
Buggy Valley fits in perfectly with my use case.
Your MVP was just what I needed!
One small suggestion tho...
Original Buggy Valley
String redScreenPath = “file:///red-screen.js”;
String pillarValleyPath = “file:///pillar-valley.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(redScreenPath);
} else {
loadApp(pillarValleyPath);
}
Modified Buggy Valley
String redScreenPath = “file:///red-screen.js”;
String aliceAppPath = “file:///alice-app.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(redScreenPath);
} else {
loadApp(aliceAppPath);
}
Modified Buggy Valley
String redScreenPath = “file:///red-screen.js”;
String aliceAppPath = “file:///alice-app.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(redScreenPath);
} else {
loadApp(aliceAppPath);
}
Modified Buggy Valley
String newAliceAppPath
String aliceAppPath = “file:///alice-app.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(newAliceAppPath);
} else {
loadApp(aliceAppPath);
}
Modified Buggy Valley
String newAliceAppPath = cURLToDisk(“https://expo.io/@alice/app”);
String aliceAppPath = “file:///alice-app.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(newAliceAppPath);
} else {
loadApp(aliceAppPath);
}
Modified Buggy Valley
String newAliceAppPath = cURLToDisk(“https://expo.io/@alice/app”);
String aliceAppPath = “file:///alice-app.js”;
int randNum = getRandom();
if (isEven(randNum)){
loadApp(newAliceAppPath);
} else {
loadApp(aliceAppPath);
}
Glorified cURL
String newAliceAppPath = cURLToDisk(“https://expo.io/@alice/app”);
String aliceAppPath = “file:///alice-app.js”;
if (newAliceAppPath != null){
loadApp(newAliceAppPath);
} else {
loadApp(aliceAppPath);
}
Wait but how does this benefit me?
JS Bundle
Native Modules
Currently on disk:
JS Bundle
Native Modules
Currently on disk:
Traditional update
New JS Bundle
New Native Modules
JS Bundle
Native Modules
Currently on disk:
Traditional update
New JS Bundle
New Native Modules
Avg binary size ~30Mb
JS Bundle
Native Modules
Currently on disk:
JS Bundle
Native Modules
Currently on disk:
Glorified cURL update
New JS Bundle
Native Modules
Roadmap
Buggy Valley App
Glorified cURLing App
Designing an OTA Service
Hosting Your Own Service
OTA Assets
Announcements
Glorified cURL fits in perfectly with my use case.
Your MVP was just what I needed!
It’s not very performant tho...
Glorified cURL
String newBobAppPath = cURLToDisk(“https://expo.io/@bob/app”);
String bobAppPath = “file:///bob-app.js”;
if (newBobAppPath != null){
loadApp(newBobAppPath);
} else {
loadApp(bobAppPath);
}
Glorified cURL
String newBobAppPath = cURLToDisk(“https://expo.io/@bob/app”);
String bobAppPath = “file:///bob-app.js”;
if (newBobAppPath != null){
loadApp(newBobAppPath);
} else {
loadApp(bobAppPath);
}
JS Bundle
We don’t want to load the JS bundle unnecessarily.
We only want to load the JS bundle if there’s a new change available.
Let’s take a step back
And think about how the web
works for a sec
The Web
<script src=“bundle.js” />
Big JS bundle
bundle.js
index.html
Taking a page out of the web book
{bundleUrl: ‘bundle.js’}
Big JS bundle
bundle.js
index.json
Taking a page out of the web book
{bundleUrl: ‘ios-1a2b3c.js’}
Big JS bundle
ios-1a2b3c.js
index.json
Bundle name is based off its md5 hash
Taking a page out of the web book
{bundleUrl: ‘ios-7a8b9c’}
Big JS bundle
ios-7a8b9c.js
index.json
Cache the bundleUrl
Only download bundleUrl
if we don’t have it cached
How do I use an OTA service in my app?
^ these are my app files
^ this is what my app looks like
How do I use an OTA service in my app?
dev tools GUI
^ push this button to upload app to expo server
How do I use an OTA service in my app?
Or use the cli if you prefer
> expo publish
Run this command in your project directory to upload to expo servers
How often is the server polled for updates?
The default behavior is to poll the server when the app starts up
What if I don’t like the default behavior?
You can use the Updates module to customize when you’d to update your app
^ from the docs page
Roadmap
Buggy Valley App
Glorified cURLing App
Designing an OTA Service
Hosting Your Own Service
OTA Assets
Announcements
I’m in a country where network latency
to your CDNs are really high
I’m in a country where network latency
to your CDNs are really high
How about hosting your own app then?
I’m in a country where network latency
to your CDNs are really high
How about hosting your own app then?*
* in our upcoming SDK release
How do I host my own app?
^ these are my app files
^ this is what my app looks like
> expo export
Run this command in your project directory
to dump your app to disk
How do I host my own app?
This is what gets dumped to disk
How do I host my own app?
.
├── android-index.json
├── ios-index.json
├── assets
│   └── 1ecc2
└── bundles
      ├── android-01ee6.js
      └── ios-ee820.js
How do I host my own app?
.
├── android-index.json
├── ios-index.json
├── assets
│   └── 1ecc2
└── bundles
      ├── android-01ee6.js
      └── ios-ee820.js
How do I host my own app?
.
├── android-index.json
├── ios-index.json
├── assets
│   └── 1ecc2
└── bundles
      ├── android-01ee6.js
      └── ios-ee820.js
{bundleUrl: ‘ios-ee820.js’}
Big JS bundle
ios-ee820.js
ios-index.json
How do I host my own app?
.
├── android-index.json
├── ios-index.json
├── assets
│   └── 1ecc2
└── bundles
      ├── android-01ee6.js
      └── ios-ee820.js
git push master
I pushed to GitHub because it has free static hosting.
You can host your app from any server.
How do I build my app binary?
> expo build:ios
Run this command in your project directory
How do I build my app binary?
> expo build:ios —public-url https://quinlanj.github.io/self-hosting/ios-index.json
Run this command in your project directory
How do I build my app binary?
> expo build:ios —public-url https://quinlanj.github.io/self-hosting/ios-index.json
{bundleUrl: ‘ios-ee820.js’}
Big JS bundle
ios-ee820.js
ios-index.json
^ This file is served first
Press this button
To download
How do I use this in development?
https://quinlanj.github.io/selfhost/ios-index.json
Convert to QR code
How do I use this in development?
Scan the QR code into the expo dev app
How do I use this in development?
http://localhost:8000/ios-index.json
Convert to QR code
How do I use this in development?
Scan the QR code into the expo dev app
Roadmap
Buggy Valley App
Glorified cURLing App
Designing an OTA Service
Hosting Your Own Service
OTA Assets
Announcements
This is what my app looks like.
I’ve installed it on my phone.
In development, let’s make a change by adding another pic
Push changes to GitHub
This is what my app looks like.
I’ve installed it on my phone.
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
JS Bundle
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
JS Bundle
quinlanj.github.io
Here is the server hosting my app
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
JS Bundle
quinlanj.github.io
An update is ready!
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
JS Bundle
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
JS Bundle
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
JS Bundle
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
New
JS Bundle
<Image source={require(‘cat.png’} />
<Image source={require(‘dog.png’} />
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
?
dog.png is pulled down to filesystem?
New
JS Bundle
<Image source={require(‘cat.png’} />
<Image source={require(‘dog.png’} />
But how? It looks like these assets are fetched from filesystem
New
JS Bundle
<Image source={require(‘cat.png’} />
<Image source={require(‘dog.png’} />
We wrote a module to override asset resolution
New
JS Bundle
<Image source={require(‘cat.png’} />
<Image source={require(‘dog.png’} />
Module Logic:
Look for asset in the filesystem
If it’s not there, look for it from the server
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
?
dog.png is pulled down to filesystem?
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
?
dog.png is not on the filesystem
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
?
Let’s grab dog.png from server then!
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
This is what my app looks like.
I’ve installed it on my phone.
Currently on filesystem:
quinlanj.github.io
An update is ready!
Files to be served:
New
JS Bundle
Cached for future use
How come assets are stored by hash?
.
├── android-index.json
├── ios-index.json
├── assets
│   └── 1ecc2
└── bundles
      ├── android-01ee6.js
      └── ios-ee820.js
JS Bundle
<Image source={require(‘cat.png’)} />
We are requiring assets by their name, not by their hash
JS Bundle
require(‘cat.png’)
React native packager
{assetName: ‘cat.png’, hash:’1ecc2’}
App packaging
App.js
JS Bundle
<Image source={require(‘cat.png’} />
Module Logic:
Look for cat.png in the filesystem
If it’s not there, look for cat.png from the server
Recall
JS Bundle
Module Logic:
Look for 1ecc2 in the filesystem
If it’s not there, look for 1ecc2 from the server
Actual Implementation
{assetName: ‘cat.png’, hash:’1ecc2’}
How does this benefit me?
<Image source={require(‘cat1.png’} />
<Image source={require(‘crazy-cat.png’} />
<Image source={require(‘lime-cat.png’} />
…
This app displays the same cat picture
These cat pictures are all named something different
{assetName: ‘cat1.png’, hash:’1ecc2’}
{assetName: ‘crazy-cat.png’, hash:’1ecc2’}
{assetName: ‘lime-cat.png’, hash:’1ecc2’}
…
They all resolve to the same file on disk: 1ecc2
Roadmap
Buggy Valley App
Glorified cURLing App
Designing an OTA Service
Hosting Your Own Service
OTA Assets
Announcements
Announcements
We made a web application called Snack
Snack is like a JS Fiddle for react native apps
Snack is now open source, check it out at https://github.com/expo/snack-web

More Related Content

What's hot

Lcu14 107- op-tee on ar mv8
Lcu14 107- op-tee on ar mv8Lcu14 107- op-tee on ar mv8
Lcu14 107- op-tee on ar mv8Linaro
 
LAS16-402: ARM Trusted Firmware – from Enterprise to Embedded
LAS16-402: ARM Trusted Firmware – from Enterprise to EmbeddedLAS16-402: ARM Trusted Firmware – from Enterprise to Embedded
LAS16-402: ARM Trusted Firmware – from Enterprise to EmbeddedLinaro
 
Uboot startup sequence
Uboot startup sequenceUboot startup sequence
Uboot startup sequenceHoucheng Lin
 
Learning AOSP - Android Linux Device Driver
Learning AOSP - Android Linux Device DriverLearning AOSP - Android Linux Device Driver
Learning AOSP - Android Linux Device DriverNanik Tolaram
 
U Boot or Universal Bootloader
U Boot or Universal BootloaderU Boot or Universal Bootloader
U Boot or Universal BootloaderSatpal Parmar
 
LAS16-406: Android Widevine on OP-TEE
LAS16-406: Android Widevine on OP-TEELAS16-406: Android Widevine on OP-TEE
LAS16-406: Android Widevine on OP-TEELinaro
 
Trusted firmware deep_dive_v1.0_
Trusted firmware deep_dive_v1.0_Trusted firmware deep_dive_v1.0_
Trusted firmware deep_dive_v1.0_Linaro
 
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM SystemsXPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM SystemsThe Linux Foundation
 
LAS16-200: SCMI - System Management and Control Interface
LAS16-200:  SCMI - System Management and Control InterfaceLAS16-200:  SCMI - System Management and Control Interface
LAS16-200: SCMI - System Management and Control InterfaceLinaro
 
Red Bend Software: Optimizing the User Experience with Over-the-Air Updates
Red Bend Software: Optimizing the User Experience with Over-the-Air UpdatesRed Bend Software: Optimizing the User Experience with Over-the-Air Updates
Red Bend Software: Optimizing the User Experience with Over-the-Air UpdatesRed Bend Software
 
Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBLinux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBshimosawa
 
The Yocto Project
The Yocto ProjectThe Yocto Project
The Yocto Projectrossburton
 

What's hot (20)

Lcu14 107- op-tee on ar mv8
Lcu14 107- op-tee on ar mv8Lcu14 107- op-tee on ar mv8
Lcu14 107- op-tee on ar mv8
 
FOTA Upgrade on Automotive and IoT Industry
FOTA Upgrade on Automotive and IoT IndustryFOTA Upgrade on Automotive and IoT Industry
FOTA Upgrade on Automotive and IoT Industry
 
LAS16-402: ARM Trusted Firmware – from Enterprise to Embedded
LAS16-402: ARM Trusted Firmware – from Enterprise to EmbeddedLAS16-402: ARM Trusted Firmware – from Enterprise to Embedded
LAS16-402: ARM Trusted Firmware – from Enterprise to Embedded
 
Uboot startup sequence
Uboot startup sequenceUboot startup sequence
Uboot startup sequence
 
Embedded C
Embedded CEmbedded C
Embedded C
 
Learning AOSP - Android Linux Device Driver
Learning AOSP - Android Linux Device DriverLearning AOSP - Android Linux Device Driver
Learning AOSP - Android Linux Device Driver
 
U Boot or Universal Bootloader
U Boot or Universal BootloaderU Boot or Universal Bootloader
U Boot or Universal Bootloader
 
Linux Internals - Interview essentials 4.0
Linux Internals - Interview essentials 4.0Linux Internals - Interview essentials 4.0
Linux Internals - Interview essentials 4.0
 
Android Audio System
Android Audio SystemAndroid Audio System
Android Audio System
 
LAS16-406: Android Widevine on OP-TEE
LAS16-406: Android Widevine on OP-TEELAS16-406: Android Widevine on OP-TEE
LAS16-406: Android Widevine on OP-TEE
 
Trusted firmware deep_dive_v1.0_
Trusted firmware deep_dive_v1.0_Trusted firmware deep_dive_v1.0_
Trusted firmware deep_dive_v1.0_
 
Flash Bootloader Development for ECU programming
Flash Bootloader Development for ECU programmingFlash Bootloader Development for ECU programming
Flash Bootloader Development for ECU programming
 
UDS Protocol Stack | Manual Guide | Fact Sheet
UDS Protocol Stack | Manual Guide | Fact SheetUDS Protocol Stack | Manual Guide | Fact Sheet
UDS Protocol Stack | Manual Guide | Fact Sheet
 
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM SystemsXPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
XPDDS19: [ARM] OP-TEE Mediator in Xen - Volodymyr Babchuk, EPAM Systems
 
LAS16-200: SCMI - System Management and Control Interface
LAS16-200:  SCMI - System Management and Control InterfaceLAS16-200:  SCMI - System Management and Control Interface
LAS16-200: SCMI - System Management and Control Interface
 
Red Bend Software: Optimizing the User Experience with Over-the-Air Updates
Red Bend Software: Optimizing the User Experience with Over-the-Air UpdatesRed Bend Software: Optimizing the User Experience with Over-the-Air Updates
Red Bend Software: Optimizing the User Experience with Over-the-Air Updates
 
Android Things : Building Embedded Devices
Android Things : Building Embedded DevicesAndroid Things : Building Embedded Devices
Android Things : Building Embedded Devices
 
A practical guide to buildroot
A practical guide to buildrootA practical guide to buildroot
A practical guide to buildroot
 
Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBLinux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKB
 
The Yocto Project
The Yocto ProjectThe Yocto Project
The Yocto Project
 

Similar to Hosting Your Own OTA Update Service

Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.catPablo Godel
 
TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...
TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...
TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...Amazon Web Services
 
AWS CodeDeploy - basic intro
AWS CodeDeploy - basic introAWS CodeDeploy - basic intro
AWS CodeDeploy - basic introAnton Babenko
 
Обход проверки безопасности в магазинах мобильных приложений при помощи платф...
Обход проверки безопасности в магазинах мобильных приложений при помощи платф...Обход проверки безопасности в магазинах мобильных приложений при помощи платф...
Обход проверки безопасности в магазинах мобильных приложений при помощи платф...Positive Hack Days
 
Appium workship, Mobile Web+Dev Conference
Appium workship,  Mobile Web+Dev ConferenceAppium workship,  Mobile Web+Dev Conference
Appium workship, Mobile Web+Dev ConferenceIsaac Murchie
 
Appium mobile web+dev conference
Appium   mobile web+dev conferenceAppium   mobile web+dev conference
Appium mobile web+dev conferenceIsaac Murchie
 
Cannibalising The Google App Engine
Cannibalising The  Google  App  EngineCannibalising The  Google  App  Engine
Cannibalising The Google App Enginecatherinewall
 
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...Amazon Web Services
 
Torquebox @ Raleigh.rb - April 2011
Torquebox @ Raleigh.rb - April 2011Torquebox @ Raleigh.rb - April 2011
Torquebox @ Raleigh.rb - April 2011tobiascrawley
 
[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...
[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...
[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...Future Processing
 
Symfony Deployments on Heroku
Symfony Deployments on HerokuSymfony Deployments on Heroku
Symfony Deployments on HerokuStefan Adolf
 
Node Summit 2018: Cloud Native Node.js
Node Summit 2018: Cloud Native Node.jsNode Summit 2018: Cloud Native Node.js
Node Summit 2018: Cloud Native Node.jsChris Bailey
 
Silicon Valley Code Camp 2019 - Reaching the Cloud Native World
Silicon Valley Code Camp 2019 - Reaching the Cloud Native WorldSilicon Valley Code Camp 2019 - Reaching the Cloud Native World
Silicon Valley Code Camp 2019 - Reaching the Cloud Native WorldChris Bailey
 
Torquebox Asheville.rb April 2011
Torquebox Asheville.rb April 2011Torquebox Asheville.rb April 2011
Torquebox Asheville.rb April 2011Lance Ball
 
Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...
Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...
Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...Amazon Web Services
 
Running Microservices on AWS Elastic Beanstalk
Running Microservices on AWS Elastic BeanstalkRunning Microservices on AWS Elastic Beanstalk
Running Microservices on AWS Elastic BeanstalkAmazon Web Services
 
Nodejs Intro - Part2 Introduction to Web Applications
Nodejs Intro - Part2 Introduction to Web ApplicationsNodejs Intro - Part2 Introduction to Web Applications
Nodejs Intro - Part2 Introduction to Web ApplicationsBudh Ram Gurung
 
Can I Contain This?
Can I Contain This?Can I Contain This?
Can I Contain This?Eficode
 
Modern Web Application Development Workflow - EclipseCon France 2014
Modern Web Application Development Workflow - EclipseCon France 2014Modern Web Application Development Workflow - EclipseCon France 2014
Modern Web Application Development Workflow - EclipseCon France 2014Stéphane Bégaudeau
 

Similar to Hosting Your Own OTA Update Service (20)

Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.cat
 
TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...
TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...
TLS303 How to Deploy Python Applications on AWS Elastic Beanstalk - AWS re:In...
 
AWS CodeDeploy - basic intro
AWS CodeDeploy - basic introAWS CodeDeploy - basic intro
AWS CodeDeploy - basic intro
 
Обход проверки безопасности в магазинах мобильных приложений при помощи платф...
Обход проверки безопасности в магазинах мобильных приложений при помощи платф...Обход проверки безопасности в магазинах мобильных приложений при помощи платф...
Обход проверки безопасности в магазинах мобильных приложений при помощи платф...
 
Appium workship, Mobile Web+Dev Conference
Appium workship,  Mobile Web+Dev ConferenceAppium workship,  Mobile Web+Dev Conference
Appium workship, Mobile Web+Dev Conference
 
Appium mobile web+dev conference
Appium   mobile web+dev conferenceAppium   mobile web+dev conference
Appium mobile web+dev conference
 
Cannibalising The Google App Engine
Cannibalising The  Google  App  EngineCannibalising The  Google  App  Engine
Cannibalising The Google App Engine
 
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Torquebox @ Raleigh.rb - April 2011
Torquebox @ Raleigh.rb - April 2011Torquebox @ Raleigh.rb - April 2011
Torquebox @ Raleigh.rb - April 2011
 
[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...
[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...
[QE 2018] Adam Stasiak – Nadchodzi React Native – czyli o testowaniu mobilnyc...
 
Symfony Deployments on Heroku
Symfony Deployments on HerokuSymfony Deployments on Heroku
Symfony Deployments on Heroku
 
Node Summit 2018: Cloud Native Node.js
Node Summit 2018: Cloud Native Node.jsNode Summit 2018: Cloud Native Node.js
Node Summit 2018: Cloud Native Node.js
 
Silicon Valley Code Camp 2019 - Reaching the Cloud Native World
Silicon Valley Code Camp 2019 - Reaching the Cloud Native WorldSilicon Valley Code Camp 2019 - Reaching the Cloud Native World
Silicon Valley Code Camp 2019 - Reaching the Cloud Native World
 
Torquebox Asheville.rb April 2011
Torquebox Asheville.rb April 2011Torquebox Asheville.rb April 2011
Torquebox Asheville.rb April 2011
 
Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...
Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...
Running Microservices and Docker on AWS Elastic Beanstalk - August 2016 Month...
 
Running Microservices on AWS Elastic Beanstalk
Running Microservices on AWS Elastic BeanstalkRunning Microservices on AWS Elastic Beanstalk
Running Microservices on AWS Elastic Beanstalk
 
Nodejs Intro - Part2 Introduction to Web Applications
Nodejs Intro - Part2 Introduction to Web ApplicationsNodejs Intro - Part2 Introduction to Web Applications
Nodejs Intro - Part2 Introduction to Web Applications
 
Can I Contain This?
Can I Contain This?Can I Contain This?
Can I Contain This?
 
Modern Web Application Development Workflow - EclipseCon France 2014
Modern Web Application Development Workflow - EclipseCon France 2014Modern Web Application Development Workflow - EclipseCon France 2014
Modern Web Application Development Workflow - EclipseCon France 2014
 

Recently uploaded

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 

Recently uploaded (20)

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 

Hosting Your Own OTA Update Service

  • 1. Host your own Over-the-air update service
  • 2. Roadmap Buggy Valley App Glorified cURLing App Designing an OTA Service Hosting Your Own Service OTA Assets Announcements
  • 7. Standing on the shoulders of giants
  • 10. Buggy Valley $ p = 0.5 $$ Nothingp = 0.5
  • 11. Buggy Valley p = 0.5 p = 0.5
  • 12. Android Java Implementation String redScreenPath = “file:///red-screen.js”; String pillarValleyPath = “file:///pillar-valley.js”;
  • 13. Android Java Implementation String redScreenPath = “file:///red-screen.js”; String pillarValleyPath = “file:///pillar-valley.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(redScreenPath); } else { loadApp(pillarValleyPath); }
  • 14. Android Java Implementation String redScreenPath = “file:///red-screen.js”; String pillarValleyPath = “file:///pillar-valley.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(redScreenPath); } else { loadApp(pillarValleyPath);** } ** how does loadApp work?
  • 15.
  • 16.
  • 17. Quick Recap String redScreenPath = “file:///red-screen.js”; String pillarValleyPath = “file:///pillar-valley.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(redScreenPath); } else { loadApp(pillarValleyPath);** } ** how does loadApp work?
  • 18. Roadmap Buggy Valley App Glorified cURLing App Designing an OTA Service Hosting Your Own Service OTA Assets Announcements
  • 19.
  • 20. Buggy Valley fits in perfectly with my use case. Your MVP was just what I needed!
  • 22. Original Buggy Valley String redScreenPath = “file:///red-screen.js”; String pillarValleyPath = “file:///pillar-valley.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(redScreenPath); } else { loadApp(pillarValleyPath); }
  • 23. Modified Buggy Valley String redScreenPath = “file:///red-screen.js”; String aliceAppPath = “file:///alice-app.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(redScreenPath); } else { loadApp(aliceAppPath); }
  • 24. Modified Buggy Valley String redScreenPath = “file:///red-screen.js”; String aliceAppPath = “file:///alice-app.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(redScreenPath); } else { loadApp(aliceAppPath); }
  • 25. Modified Buggy Valley String newAliceAppPath String aliceAppPath = “file:///alice-app.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(newAliceAppPath); } else { loadApp(aliceAppPath); }
  • 26. Modified Buggy Valley String newAliceAppPath = cURLToDisk(“https://expo.io/@alice/app”); String aliceAppPath = “file:///alice-app.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(newAliceAppPath); } else { loadApp(aliceAppPath); }
  • 27. Modified Buggy Valley String newAliceAppPath = cURLToDisk(“https://expo.io/@alice/app”); String aliceAppPath = “file:///alice-app.js”; int randNum = getRandom(); if (isEven(randNum)){ loadApp(newAliceAppPath); } else { loadApp(aliceAppPath); }
  • 28. Glorified cURL String newAliceAppPath = cURLToDisk(“https://expo.io/@alice/app”); String aliceAppPath = “file:///alice-app.js”; if (newAliceAppPath != null){ loadApp(newAliceAppPath); } else { loadApp(aliceAppPath); }
  • 29. Wait but how does this benefit me?
  • 31. JS Bundle Native Modules Currently on disk: Traditional update New JS Bundle New Native Modules
  • 32. JS Bundle Native Modules Currently on disk: Traditional update New JS Bundle New Native Modules Avg binary size ~30Mb
  • 34. JS Bundle Native Modules Currently on disk: Glorified cURL update New JS Bundle Native Modules
  • 35. Roadmap Buggy Valley App Glorified cURLing App Designing an OTA Service Hosting Your Own Service OTA Assets Announcements
  • 36.
  • 37. Glorified cURL fits in perfectly with my use case. Your MVP was just what I needed!
  • 38. It’s not very performant tho...
  • 39. Glorified cURL String newBobAppPath = cURLToDisk(“https://expo.io/@bob/app”); String bobAppPath = “file:///bob-app.js”; if (newBobAppPath != null){ loadApp(newBobAppPath); } else { loadApp(bobAppPath); }
  • 40. Glorified cURL String newBobAppPath = cURLToDisk(“https://expo.io/@bob/app”); String bobAppPath = “file:///bob-app.js”; if (newBobAppPath != null){ loadApp(newBobAppPath); } else { loadApp(bobAppPath); } JS Bundle We don’t want to load the JS bundle unnecessarily. We only want to load the JS bundle if there’s a new change available.
  • 41. Let’s take a step back And think about how the web works for a sec
  • 42. The Web <script src=“bundle.js” /> Big JS bundle bundle.js index.html
  • 43. Taking a page out of the web book {bundleUrl: ‘bundle.js’} Big JS bundle bundle.js index.json
  • 44. Taking a page out of the web book {bundleUrl: ‘ios-1a2b3c.js’} Big JS bundle ios-1a2b3c.js index.json Bundle name is based off its md5 hash
  • 45. Taking a page out of the web book {bundleUrl: ‘ios-7a8b9c’} Big JS bundle ios-7a8b9c.js index.json Cache the bundleUrl Only download bundleUrl if we don’t have it cached
  • 46. How do I use an OTA service in my app? ^ these are my app files ^ this is what my app looks like
  • 47. How do I use an OTA service in my app? dev tools GUI ^ push this button to upload app to expo server
  • 48. How do I use an OTA service in my app? Or use the cli if you prefer > expo publish Run this command in your project directory to upload to expo servers
  • 49. How often is the server polled for updates? The default behavior is to poll the server when the app starts up
  • 50. What if I don’t like the default behavior? You can use the Updates module to customize when you’d to update your app ^ from the docs page
  • 51. Roadmap Buggy Valley App Glorified cURLing App Designing an OTA Service Hosting Your Own Service OTA Assets Announcements
  • 52. I’m in a country where network latency to your CDNs are really high
  • 53. I’m in a country where network latency to your CDNs are really high How about hosting your own app then?
  • 54. I’m in a country where network latency to your CDNs are really high How about hosting your own app then?* * in our upcoming SDK release
  • 55. How do I host my own app? ^ these are my app files ^ this is what my app looks like
  • 56. > expo export Run this command in your project directory to dump your app to disk How do I host my own app?
  • 57. This is what gets dumped to disk How do I host my own app? . ├── android-index.json ├── ios-index.json ├── assets │   └── 1ecc2 └── bundles       ├── android-01ee6.js       └── ios-ee820.js
  • 58. How do I host my own app? . ├── android-index.json ├── ios-index.json ├── assets │   └── 1ecc2 └── bundles       ├── android-01ee6.js       └── ios-ee820.js
  • 59. How do I host my own app? . ├── android-index.json ├── ios-index.json ├── assets │   └── 1ecc2 └── bundles       ├── android-01ee6.js       └── ios-ee820.js {bundleUrl: ‘ios-ee820.js’} Big JS bundle ios-ee820.js ios-index.json
  • 60. How do I host my own app? . ├── android-index.json ├── ios-index.json ├── assets │   └── 1ecc2 └── bundles       ├── android-01ee6.js       └── ios-ee820.js git push master
  • 61. I pushed to GitHub because it has free static hosting. You can host your app from any server.
  • 62. How do I build my app binary? > expo build:ios Run this command in your project directory
  • 63. How do I build my app binary? > expo build:ios —public-url https://quinlanj.github.io/self-hosting/ios-index.json Run this command in your project directory
  • 64. How do I build my app binary? > expo build:ios —public-url https://quinlanj.github.io/self-hosting/ios-index.json {bundleUrl: ‘ios-ee820.js’} Big JS bundle ios-ee820.js ios-index.json ^ This file is served first
  • 66. How do I use this in development? https://quinlanj.github.io/selfhost/ios-index.json Convert to QR code
  • 67. How do I use this in development? Scan the QR code into the expo dev app
  • 68. How do I use this in development? http://localhost:8000/ios-index.json Convert to QR code
  • 69. How do I use this in development? Scan the QR code into the expo dev app
  • 70. Roadmap Buggy Valley App Glorified cURLing App Designing an OTA Service Hosting Your Own Service OTA Assets Announcements
  • 71. This is what my app looks like. I’ve installed it on my phone.
  • 72. In development, let’s make a change by adding another pic
  • 73. Push changes to GitHub
  • 74. This is what my app looks like. I’ve installed it on my phone.
  • 75. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: JS Bundle
  • 76. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: JS Bundle quinlanj.github.io Here is the server hosting my app
  • 77. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: JS Bundle quinlanj.github.io An update is ready!
  • 78. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: JS Bundle quinlanj.github.io An update is ready! Files to be served: New JS Bundle
  • 79. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: JS Bundle quinlanj.github.io An update is ready! Files to be served: New JS Bundle JS Bundle
  • 80. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle
  • 81. New JS Bundle <Image source={require(‘cat.png’} /> <Image source={require(‘dog.png’} />
  • 82. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle ? dog.png is pulled down to filesystem?
  • 83. New JS Bundle <Image source={require(‘cat.png’} /> <Image source={require(‘dog.png’} /> But how? It looks like these assets are fetched from filesystem
  • 84. New JS Bundle <Image source={require(‘cat.png’} /> <Image source={require(‘dog.png’} /> We wrote a module to override asset resolution
  • 85. New JS Bundle <Image source={require(‘cat.png’} /> <Image source={require(‘dog.png’} /> Module Logic: Look for asset in the filesystem If it’s not there, look for it from the server
  • 86. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle ? dog.png is pulled down to filesystem?
  • 87. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle ? dog.png is not on the filesystem
  • 88. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle ? Let’s grab dog.png from server then!
  • 89. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle
  • 90. This is what my app looks like. I’ve installed it on my phone. Currently on filesystem: quinlanj.github.io An update is ready! Files to be served: New JS Bundle Cached for future use
  • 91. How come assets are stored by hash? . ├── android-index.json ├── ios-index.json ├── assets │   └── 1ecc2 └── bundles       ├── android-01ee6.js       └── ios-ee820.js
  • 92. JS Bundle <Image source={require(‘cat.png’)} /> We are requiring assets by their name, not by their hash
  • 93. JS Bundle require(‘cat.png’) React native packager {assetName: ‘cat.png’, hash:’1ecc2’} App packaging App.js
  • 94. JS Bundle <Image source={require(‘cat.png’} /> Module Logic: Look for cat.png in the filesystem If it’s not there, look for cat.png from the server Recall
  • 95. JS Bundle Module Logic: Look for 1ecc2 in the filesystem If it’s not there, look for 1ecc2 from the server Actual Implementation {assetName: ‘cat.png’, hash:’1ecc2’}
  • 96. How does this benefit me?
  • 97. <Image source={require(‘cat1.png’} /> <Image source={require(‘crazy-cat.png’} /> <Image source={require(‘lime-cat.png’} /> … This app displays the same cat picture These cat pictures are all named something different
  • 98. {assetName: ‘cat1.png’, hash:’1ecc2’} {assetName: ‘crazy-cat.png’, hash:’1ecc2’} {assetName: ‘lime-cat.png’, hash:’1ecc2’} … They all resolve to the same file on disk: 1ecc2
  • 99. Roadmap Buggy Valley App Glorified cURLing App Designing an OTA Service Hosting Your Own Service OTA Assets Announcements
  • 100. Announcements We made a web application called Snack Snack is like a JS Fiddle for react native apps Snack is now open source, check it out at https://github.com/expo/snack-web