<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Carlos Ouro</title>
    <description>The latest articles on Forem by Carlos Ouro (@techtrouts).</description>
    <link>https://forem.com/techtrouts</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F223268%2F4ae12950-a648-4e87-b051-149db921800b.png</url>
      <title>Forem: Carlos Ouro</title>
      <link>https://forem.com/techtrouts</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/techtrouts"/>
    <language>en</language>
    <item>
      <title>Pitch: Web-only PWA phone</title>
      <dc:creator>Carlos Ouro</dc:creator>
      <pubDate>Thu, 20 Aug 2020 14:30:51 +0000</pubDate>
      <link>https://forem.com/techtrouts/pitch-web-only-pwa-phone-5dhp</link>
      <guid>https://forem.com/techtrouts/pitch-web-only-pwa-phone-5dhp</guid>
      <description>&lt;p&gt;PWA is becoming more and more usual on our phones. If it's so easy to deliver and maintain, why isn't it more widely used?&lt;/p&gt;

&lt;p&gt;In this post I'll propose a conceptual "app store" free mobile OS and a very different monetisation model, in a vision which would free us from biased store content and turn the mobile back to the free web.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;"I want to make something really clear: We support two platforms at Apple. Two.&lt;br&gt;
The first one is HTML5, a fully open uncontrolled platform (...). &lt;br&gt;
The second one is the App Store. (...)"&lt;br&gt;
- Steve Jobs, 2010&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've discussed how iOS in particular has moved from being the web innovator in 2010 to becoming &lt;a href="https://dev.to/techtrouts/safari-the-internet-explorer-of-the-mobile-web-2611"&gt;the internet explorer of the mobile era&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if a phone had only the mobile web?
&lt;/h3&gt;

&lt;p&gt;But like... supercharged.&lt;/p&gt;

&lt;p&gt;Hear me out -&lt;/p&gt;

&lt;h3&gt;
  
  
  What if we designed a ROM which only runs mobile web &amp;amp; PWA?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  What if this new phone came with crypto wallet powers in web payments?
&lt;/h3&gt;

&lt;p&gt;"Firefox OS again?" Not exactly.&lt;br&gt;
Firefox was bound by 3 concepts we disregard here from the start:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hybrid downloadable apps from a store&lt;/li&gt;
&lt;li&gt;cheap low-end phones&lt;/li&gt;
&lt;li&gt;lack of monetisation strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do not want a "store"&lt;/li&gt;
&lt;li&gt;assume modern decent phones and PWA standards&lt;/li&gt;
&lt;li&gt;drive phone lifetime monetisation to manufacturer&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In case you never heard of PWAs before - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps" rel="noopener noreferrer"&gt;read about it here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;







&lt;h2&gt;
  
  
  Mobile platforms - 2010 to 2020+
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2010:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fufg7fk7zzziyla5n0alj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fufg7fk7zzziyla5n0alj.png" alt="2010 - native vs web"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2020+ state of "mobile native pros":
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Interface&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser app controls still take considerable space in the mobile web interface :(&lt;/li&gt;
&lt;li&gt;Not an issue on full-screen mode PWA :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Offline Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No longer an issue for DB &amp;amp; cache data&lt;/li&gt;
&lt;li&gt;In DB file storage already available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Marketing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Driven by app store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Earning Bucks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Driven by app store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Richer experience&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not an issue for "common" apps
in fact, a lot are just webview wrapped HTML5 today...&lt;/li&gt;
&lt;li&gt;Games/3d/AR are quickly catching up
(WebGL, WebXR, WebAssembly, WebGPU, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can see from the above that most issues on mobile web today are bound to the phone OS/store, its marketing and biased strategies, more than the mobile web technology which is coming leaps and bounds since 2010.&lt;/p&gt;

&lt;h2&gt;
  
  
  Re-imagining a Mobile OS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Interface
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"Web content on my phone is simply not the same as apps"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main reason for this is that you need to cater for the controls of the browser app itself such as address bar, settings, favourites, etc.&lt;br&gt;
We still see the browser as a the app, and the web content as... just content.&lt;/p&gt;

&lt;p&gt;The answer would be a web-only mobile OS UI.&lt;br&gt;
By having the concept of “web browser” as the only client runtime, we can immerse the web experience into the mobile phone UI. Apps become just tabs, and “bookmarking” is no different from “installing”.&lt;/p&gt;

&lt;p&gt;Let's take our modern phone to a "blank slate" and start off from a basic modern dashboard. Taking Android UI as a baseline, we could merge &lt;code&gt;home&lt;/code&gt;+&lt;code&gt;switch app&lt;/code&gt; buttons into a single button, and take the old &lt;code&gt;switch app&lt;/code&gt; place and use it for &lt;code&gt;context settings&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk8o72etsg47tl4wticga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk8o72etsg47tl4wticga.png" alt="PWA phone UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then when we travel to a web page/app, say gmail, the web page would be an "app" in itself and always present fullscreen&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbpxdcbkn7c4hkv7mwkk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbpxdcbkn7c4hkv7mwkk2.png" alt="Fullscreen web app in PWA phone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This seems natural!&lt;br&gt;
It doesn't "feel" like mobile web anymore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what about browser controls?&lt;/strong&gt;&lt;br&gt;
Remember the &lt;code&gt;context settings&lt;/code&gt; button we've added?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh8pzb3vo1tsxfdl708q3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh8pzb3vo1tsxfdl708q3.png" alt="PWA context settings in PWA phone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok - now its even easier to control security and permissions for any app that on a "native" apps phone!&lt;/p&gt;







&lt;h3&gt;
  
  
  Offline Data
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"Yeah but web apps can’t really create and store stuff locally"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Actually &lt;strong&gt;today they can&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There is already a suite of solutions for web apps in use today:&lt;br&gt;
Storage API standards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IndexedDB API - large amounts of data &amp;amp; files/blobs&lt;/li&gt;
&lt;li&gt;Cache API - in-app assets cache&lt;/li&gt;
&lt;li&gt;Web Storage API - in-app session information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We just need to organise appropriate storage settings and limits for installed and non-installed apps, and enable user review/override when necessary.&lt;br&gt;
Managing in-device storage also becomes much simpler than in other mobile operating systems today that need to account with multiple storage solutions for different app types.&lt;/p&gt;







&lt;h3&gt;
  
  
  Marketing
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"How are users going to get access to filtered quality content without a store? How are developers going to promote their content?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The web already knows&lt;/strong&gt; how to marketing&lt;/p&gt;

&lt;p&gt;Ads and SEO have been around for a long time and they are the natural marketing strategies of the web.&lt;br&gt;
It is the natural solution for developers which is provided out-of-the-box by the open web.&lt;/p&gt;

&lt;p&gt;Having said this, the manufacturer could consider some kind of branded dashboard/portal where top compatible “apps” can be listed...&lt;/p&gt;







&lt;h3&gt;
  
  
  Earning Bucks
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"Sounds like a cool project but we can’t really make money without a store"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enter &lt;strong&gt;crypto-currency superpowers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API" rel="noopener noreferrer"&gt;Payment Request API&lt;/a&gt; already exists today.&lt;br&gt;
With some work in this field we could easily can turn our phone into a eWallet for web payments.&lt;/p&gt;

&lt;p&gt;Phone manufacturers can bundle their own crypto providers to phone users and thus leverage of small micro-transaction fees out-of-the-box with the phone.&lt;br&gt;
Also - using crypto would make payments processing much easier in the web apps themselves.&lt;/p&gt;







&lt;h3&gt;
  
  
  Richer Experience
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"But can the content quality ever really match up to native speeds?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We know things have been evolving incredibly fast - we now have near-native speeds in web content today with WebAssembly, basic 3D graphics via WebGL, augmented reality capabilities via WebXR, threads via workers, and many, many other APIs. &lt;/p&gt;

&lt;p&gt;Vulkan/WebGPU is expected to soon enable game developers to reach even closer to native-level graphics with thousands of 3D objects not degrading performance, much above the ~100 objects that we can do today with WebGL.&lt;/p&gt;

&lt;p&gt;We don’t have the tools, frameworks and engines today that we do in native apps - but part of the problem is exactly because there has been no real need/business case for it. We just put up a native app instead.&lt;/p&gt;

&lt;p&gt;But with broader PWA adoption and newer web APIs, developers will soon create such tools and there is no real technical limitation in the near future for any relevant discrepancy in web vs native experiences.&lt;/p&gt;







&lt;h2&gt;
  
  
  But would this actually work?
&lt;/h2&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;I've pitched the idea to a few people over the last 3 years, and mostly everyone discards it as meh.&lt;/p&gt;

&lt;p&gt;So I've decided to post it here - maybe someone else will agree or build upon the idea :)&lt;/p&gt;

</description>
      <category>startup</category>
      <category>discuss</category>
      <category>ux</category>
      <category>android</category>
    </item>
    <item>
      <title>Embed Rust wasm into React</title>
      <dc:creator>Carlos Ouro</dc:creator>
      <pubDate>Wed, 19 Aug 2020 21:00:29 +0000</pubDate>
      <link>https://forem.com/techtrouts/embed-rust-wasm-into-react-48og</link>
      <guid>https://forem.com/techtrouts/embed-rust-wasm-into-react-48og</guid>
      <description>&lt;p&gt;WebAssembly is coming out to play. It's time for us, developers, to also move forward and push our heavy lifting computation algorithms into the low-level architecture in our products/libs/components and, together, speed up the web client as a whole.&lt;/p&gt;

&lt;p&gt;What should know (at a high-level) before we progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modern JavaScript;&lt;/li&gt;
&lt;li&gt;React;&lt;/li&gt;
&lt;li&gt;react-app-rewired pipeline;&lt;/li&gt;
&lt;li&gt;Rust;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are looking for a non-Rust WASM approach&lt;/p&gt;

&lt;p&gt;First, let's keep in mind how WebAssembly actually runs in a web page.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does WebAssembly run in a webpage?
&lt;/h2&gt;

&lt;p&gt;WebAssembly is a low-level module with a sandboxed shared memory allocated and managed by the browser.&lt;br&gt;
Today, we instance these WebAssembly modules via JavaScript and can then interop with their shared memory and call exported module functionality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx4u4ay6u7kejesbg49e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx4u4ay6u7kejesbg49e2.png" alt="WebAssembly runtime"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we're ready to see how we can make our Rust code take some algorithmic load from our modern React web app.&lt;/p&gt;


&lt;h2&gt;
  
  
  When to use WASM instead of JS
&lt;/h2&gt;

&lt;p&gt;JavaScript does an epic job in the web platform - it's perfect to describe events, functional flows and passing arbitrary small sets of data around. It has direct runtime scope integration into the window, giving you direct scope interoperability between different JavaScript modules loaded on the page with a simple single-threaded approach.&lt;br&gt;
Perhaps one day we'll find an even better approach, but that is not the goal of WebAssembly.&lt;/p&gt;

&lt;p&gt;WebAssembly thrives in heavy data manipulation and complex algorithmic logic and, last but not least, large chains of function calls.&lt;br&gt;
Think about image/video/sound data manipulation, heavy string operations, game/scene object interpolations, etc.&lt;/p&gt;

&lt;p&gt;You can read more at &lt;a href="https://koala42.com/using-webassembly-in-your-reactjs-app/" rel="noopener noreferrer"&gt;this great article by Koala42&lt;/a&gt;, where, near the bottom, he demonstrates how can WebAssembly be much slower or much faster than JS in 2 fairly similar tasks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are curious, check the difference of &lt;code&gt;factorize()&lt;/code&gt; and &lt;code&gt;factorialize_fib()&lt;/code&gt; in both &lt;a href="https://github.com/Koala42/webassembly-react/blob/master/src/utils.js" rel="noopener noreferrer"&gt;Javascript&lt;/a&gt; and &lt;a href="https://github.com/Koala42/webassembly-react/blob/master/wasm-koala-blog/src/lib.rs" rel="noopener noreferrer"&gt;Rust&lt;/a&gt; in his example source code to understand how is WebAssembly faster for &lt;code&gt;factorialize_fib()&lt;/code&gt;, but slower than JS on the simpler &lt;code&gt;factorize()&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  But the stack milord!
&lt;/h2&gt;

&lt;p&gt;Indeed the modern web app is not bare metal anymore. Our JSX+ES7 codebase and 3rd party modules are bundled on-the-fly by complex build pipelines transpiling, collating and cleaning up code into a shinny optimised web app output that we actually don't know much about anymore. &lt;br&gt;
This process takes away most of the cross-browser/transpile pain, but makes it hard to introduce something new or tweak under the hood.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rant: I hope web standards adoption trends and perhaps a standardised react alternative (&lt;a href="https://www.webcomponents.org/" rel="noopener noreferrer"&gt;Web Components?&lt;/a&gt;) will one day bring us back to simpler build pipelines, closer to bare metal web and JS...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, how do we integrate the modern stack with WebAssembly?&lt;/p&gt;
&lt;h2&gt;
  
  
  Back to the future
&lt;/h2&gt;

&lt;p&gt;Let's assume you have some kind of react app with a typical create-react-app base template structure. This example purposely showcases the git repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- myApp
  | - .git/
  | - node_modules/
  | - public/
  | - src/
  | - config-overrides.js
  | - package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;












&lt;p&gt;There are &lt;strong&gt;3 different approaches&lt;/strong&gt; to integrating WASM modules into your react app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a provided wasm module via npm&lt;/li&gt;
&lt;li&gt;Hook your own local wasm npm module into an app&lt;/li&gt;
&lt;li&gt;Embed a wasm module directly into your app git repo&lt;/li&gt;
&lt;/ol&gt;










&lt;h3&gt;
  
  
  Use case 1. Use a provided wasm module via npm
&lt;/h3&gt;

&lt;p&gt;This option is so simple you may even already be using 3rd party WASM modules without knowing.&lt;/p&gt;

&lt;p&gt;You just have to add the published npm module into your &lt;code&gt;package.json&lt;/code&gt; and use it directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;rust-wasm-react-calculator &lt;span class="nt"&gt;--save&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then simply use it in your react source code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;calculate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rust-wasm-react-calculator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// and use&lt;/span&gt;
&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14+5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know, that's way too simple - this is why we should be using WebAssembly today for whatever is meaningful in terms of performance (keep in mind - it's actually &lt;em&gt;slower&lt;/em&gt; for most common tasks!)&lt;/p&gt;



&lt;p&gt;Next, let's see how we can create our own&lt;/p&gt;




&lt;h3&gt;
  
  
  Use case 2. Hook your own local wasm npm module into an app
&lt;/h3&gt;

&lt;p&gt;First, in order to create and manage your wasm npm module, let's make sure you have &lt;code&gt;wasm-pack&lt;/code&gt; installed with all permissions it needs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; wasm-pack &lt;span class="nt"&gt;--unsafe-perm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, outside our app codebase, let's create our hello world wasm npm module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wasm-pack new helloWorld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- myApp
  | - .git/
  | - node_modules/
  | - public/
  | - src/
  | - config-overrides.js
  | - package.json
- helloWorld
  | - .git/
  | - src/
  | - tests/
  | - ... cargo files, etc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now can see the actual Rust source code generated in &lt;code&gt;helloWorld/src/lib.rs&lt;/code&gt;. &lt;br&gt;
The public methods here will be available to be called in JS, and &lt;code&gt;#wasm-bindgen&lt;/code&gt; takes care of passing things around on our behalf. &lt;br&gt;
Read more about &lt;a href="https://github.com/rustwasm/wasm-bindgen" rel="noopener noreferrer"&gt;wasm-bindgen&lt;/a&gt; if you need to know how it works in greater depth.&lt;/p&gt;

&lt;p&gt;Our piece of interesting code in &lt;code&gt;helloWorld/src/lib.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[wasm_bindgen]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, worldview test!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a quick &lt;code&gt;wasm-pack build&lt;/code&gt; an actual npm module will be generated into &lt;code&gt;helloWorld/pkg&lt;/code&gt; - this is a ready-made wasm npm module with all the methods and bindgen stuff in it - much like the &lt;code&gt;rust-wasm-react-calculator&lt;/code&gt; one we used for the example (1.)&lt;/p&gt;

&lt;p&gt;To test it locally with your app, you can import it directly as a local npm module in your &lt;code&gt;package.json&lt;/code&gt; with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;dependencies:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"helloWorldWasm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"file:../helloWorld/pkg"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and use it in your app code like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;helloWorldWasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// and use&lt;/span&gt;
&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: auto-update of the development server will not work out of the box - you will need to first rebuild &lt;code&gt;helloWorld&lt;/code&gt; and then refresh your app. &lt;/p&gt;
&lt;/blockquote&gt;







&lt;h3&gt;
  
  
  Use case 3. Embed a wasm module directly into your app git repo
&lt;/h3&gt;

&lt;p&gt;Finally, we come to the option where you really want to make rust part of your app and its source code.&lt;/p&gt;

&lt;p&gt;We start off similarly to 2., by creating our own &lt;code&gt;wasm-pack&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;Like before, in order to create and manage your wasm npm module, let's make sure you have &lt;code&gt;wasm-pack&lt;/code&gt; installed with all permissions it needs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; wasm-pack &lt;span class="nt"&gt;--unsafe-perm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in the root of your app source, let's create our hello world wasm npm module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wasm-pack new helloHelper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- myApp
  | - .git/
  | - node_modules/
  | - public/
  | - src/
  | - config-overrides.js
  | - package.json
  | - helloHelper
     | - .git/
     | - src/
     | - tests/
     | - ... cargo files, etc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to remove &lt;code&gt;.git&lt;/code&gt; from &lt;code&gt;helloHelper&lt;/code&gt;. We do not want to have a submodule here, we want to have our helper as part of our main app repo itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; helloHelper/.git/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: It would be much easier if &lt;code&gt;wasm-pack&lt;/code&gt; would allow us to create a module directly without VCS embedded, I've pointed this out as a &lt;a href="https://github.com/rustwasm/wasm-pack/issues/901" rel="noopener noreferrer"&gt;feature request in wasm-pack&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The final step is to hook it up to our react build, for this we will leverage &lt;a href="https://github.com/wasm-tool/wasm-pack-plugin" rel="noopener noreferrer"&gt;wasm-pack-plugin&lt;/a&gt;. &lt;br&gt;
Kick off by adding it to your app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @wasm-tool/wasm-pack-plugin &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will let &lt;code&gt;wasm-pack-plugin&lt;/code&gt; manage the &lt;code&gt;wasm-pack build&lt;/code&gt; on our behalf on its own, with its own watcher and outputting the npm module (&lt;code&gt;pkg&lt;/code&gt;) of &lt;code&gt;helloHelper&lt;/code&gt; directly into our own app &lt;code&gt;/src&lt;/code&gt; code. From there the react watcher itself also picks it up automatically and refreshes our app automatically when running locally.&lt;/p&gt;

&lt;p&gt;To achieve this we need to hook &lt;code&gt;helloHelper&lt;/code&gt; into our &lt;code&gt;config-overrides.js&lt;/code&gt; using &lt;code&gt;@wasm-tool/wasm-pack-plugin&lt;/code&gt; and make it part of the build. Additionally, we also need to ensure &lt;code&gt;file-loader&lt;/code&gt; does not attempt to load &lt;code&gt;.wasm&lt;/code&gt; file on its own.&lt;/p&gt;

&lt;p&gt;In my case I am already using &lt;code&gt;customize-cra&lt;/code&gt;, so I will just add two &lt;code&gt;config&lt;/code&gt; filter methods of my own, but you could modify &lt;code&gt;config&lt;/code&gt; directly in the same way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;override&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customize-cra&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WasmPackPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@wasm-tool/wasm-pack-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;// make the file loader ignore wasm files&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oneOf&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;wasm$/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//exclude wasm&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//ignore remaining rules&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;//hook up our helloHelper wasm module&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WasmPackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;crateDirectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./helloHelper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;extraArgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--no-typescript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/helloHelperWasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we simply use our new local module directly in react:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./helloHelperWasm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// and use&lt;/span&gt;
&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it - let's &lt;code&gt;npm start&lt;/code&gt; and let the real fun begin :)&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>rust</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Safari - The Internet Explorer of the Mobile Web</title>
      <dc:creator>Carlos Ouro</dc:creator>
      <pubDate>Fri, 07 Feb 2020 16:49:55 +0000</pubDate>
      <link>https://forem.com/techtrouts/safari-the-internet-explorer-of-the-mobile-web-2611</link>
      <guid>https://forem.com/techtrouts/safari-the-internet-explorer-of-the-mobile-web-2611</guid>
      <description>&lt;p&gt;It needs to be voiced.&lt;br&gt;
iOS Safari has fallen from a spearhead of innovation in early 2010's to become the &lt;em&gt;de facto&lt;/em&gt; limiting User Agent of the modern web.&lt;/p&gt;

&lt;p&gt;I'll make my case in 5 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bit of history&lt;/li&gt;
&lt;li&gt;Native &amp;amp; HTML5&lt;/li&gt;
&lt;li&gt;
So how is iOS Safari limiting the modern web?

&lt;ul&gt;
&lt;li&gt;Viewport / fullscreen support&lt;/li&gt;
&lt;li&gt;Web Notifications&lt;/li&gt;
&lt;li&gt;Web App Manifest&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or &lt;/p&gt;

&lt;p&gt;Skip to the gist - tl;dr&lt;/p&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Back in 2010
&lt;/h2&gt;

&lt;p&gt;Back in 2010, Steve Jobs made a big case of why iOS would not support flash in his open letter &lt;a href="https://www.apple.com/hotnews/thoughts-on-flash/" rel="noopener noreferrer"&gt;Thoughts on Flash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead, Steve proposed a view of a &lt;strong&gt;mobile HTML5 era&lt;/strong&gt; for the future:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;New open standards created in the mobile era, such as HTML5, will win on mobile devices (and PCs too)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was followed up with Apple's clear statement of supporting 2 development platforms at Apple - HTML5 &lt;em&gt;and&lt;/em&gt; App Store Native&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qKamumSGcaA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I want to make something really clear: We support two platforms at Apple. Two.&lt;/p&gt;

&lt;p&gt;The first one is HTML5, a fully open uncontrolled platform (...) we fully support HTML5 and Apple's browsers are in the lead in terms of supporting the full HTML5 standard. We are behind this 100%.&lt;/p&gt;

&lt;p&gt;The second one is the App Store. The App Store is a curated platform (...) with the most vibrant app community on the planet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With it, Flash was effectively out, and the new technology war in the mobile era had become &lt;strong&gt;Native vs HTML5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Native &amp;amp; HTML5
&lt;/h2&gt;

&lt;p&gt;In the coming years the two platforms would evolve each in its own way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML5 continued in its quest to eliminate old proprietary technologies and standardise itself the open web - slow and steady but with guaranteed sandboxing and cross-device runtime&lt;/li&gt;
&lt;li&gt;Native Mobile progressed to reach much higher levels of integration and performance - with much less sandbox boundaries and much quicker iterations it evolved much faster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the reality is that not all developers needed the tight coupling with the OS provided by Native. HTML5 had kept on improving, steadily and firmly and reaching ever nearer its Native counterpart.&lt;/p&gt;

&lt;p&gt;However soon the App Store had created a bind - not really a platform bind, but a &lt;strong&gt;delivery and profitability bind&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So came Hybrid apps - web platform runtimes that could be easily wrapped in a Native runtime. And with good design and implementation, &lt;strong&gt;hybrid&lt;/strong&gt; apps were now indistinguishable from Native.&lt;br&gt;
Although there are no official numbers, it is widely known and accepted that a considerable amount of applications today use this Hybrid approach.&lt;/p&gt;

&lt;p&gt;So I'll be calling all apps delivered through an App or Play Store "Native" throughout the rest of this post.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So how is iOS Safari limiting the modern web?
&lt;/h2&gt;

&lt;p&gt;In the past years, web standards have brought the web platform really close to the perceived "Native" standards.&lt;br&gt;
With APIs like WebGL, WebAudio, WebAssembly, Workers, Fullscreen API, Push API &amp;amp; Web Notifications, Accelerometer, Gyroscope, Orientation, Network Information and Web App Manifest, you can now install and run a web app and perform almost any task without a visible difference from a "Native" one. &lt;/p&gt;

&lt;p&gt;However most of such Web APIs are still lacking in iOS Safari.&lt;br&gt;
The decision of not implementing such APIs by Apple have avoided that a web app can be installed and run like a "Native" one through the web platform directly.&lt;/p&gt;

&lt;p&gt;There are 3 APIs in particular that are key to the perceived "app" experience in the OS:&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Viewport / fullscreen support
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;The Fullscreen API adds methods to present a specific Element (and its descendants) in full-screen mode, and to exit full-screen mode once it is no longer needed. This makes it possible to present desired content—such as an online game—using the user's entire screen, removing all browser user interface elements and other applications from the screen until full-screen mode is shut off.&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API" rel="noopener noreferrer"&gt;Fullscreen API - Web APIs | MDN&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Fullscreen API has been available in Chrome and Safari since 2011. It has never been made available in iOS Safari - not by a technical constraint, but by a design decision.&lt;/p&gt;

&lt;p&gt;For perspective, here is some of the commit history of pain I've been dragged through to workaround it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;small&gt;(partial) commit history related w/ Android Chrome&lt;/small&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2013‑12‑10&lt;/em&gt; - Android Chrome - normalised viewport scaling&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2013‑12‑10&lt;/em&gt; - Fixed width/height viewport for Android stock browser &amp;lt;=534.3&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2014-12-08&lt;/em&gt; - Support for Fullscreen API for Android Chrome&lt;/small&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;small&gt;(partial) commit history related w/ iOS Safari&lt;/small&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2013‑09‑19&lt;/em&gt; - generalised iOS7 viewport fix for all iPhones ( 4 / 4s / 5 )&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2014‑03‑05&lt;/em&gt; - viewport handling for iOS 7.0&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2014‑09‑30&lt;/em&gt; - hotfix for iPhone 6+ viewport&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2014‑10‑01&lt;/em&gt; - viewport fix for iOS 8.1+&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2015‑09‑03&lt;/em&gt; - viewport fix for iOS 9&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2015‑11‑09&lt;/em&gt; - Viewport is broken when the game is opened in portrait on iPhone 6s+&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2015‑11‑11&lt;/em&gt; - Swipe up hack is not working on iPhone 6s+ in portrait&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2016‑11‑14&lt;/em&gt; - fix(rendering): Fix iOS rendering when disabling swipe fix&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2017‑10‑13&lt;/em&gt; - fix(virtualEvents): Hack to disable iOS 10+ zoom&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2018‑08‑16&lt;/em&gt; - fix(iphoneX): iphoneX barheigth fix&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;small&gt;&lt;em&gt;2019‑08‑22&lt;/em&gt; - fix(iphone): viewport fix for iOS 13&lt;/small&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Web notifications
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/notification" rel="noopener noreferrer"&gt;Notifications - Web APIs | MDN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is another 5+ years old API that &lt;strong&gt;never reached iOS Safari&lt;/strong&gt;. It allows web apps to send users notifications, like "Native" apps.&lt;/p&gt;

&lt;p&gt;The only alternative is to build your own "Native" app and deliver it through the App Store.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add to home screen
&lt;/h3&gt;

&lt;p&gt;Mobile browsers have for long allowed web apps to be &lt;em&gt;added to homescreen&lt;/em&gt; as bookmarks with a chain of manual steps. But it is just such a buried option in the browser that no one actually used it.&lt;/p&gt;

&lt;p&gt;Now it has become a standard option for web apps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Add to home screen" (or a2hs for short) is a feature implemented by mobile browsers that takes the information found in an app's web manifest and uses them to represent the app on the device's home screen with an icon and name. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This key element is part of a collection of web technologies called progressive web apps (PWAs), which are websites that can be installed to a device’s homescreen like a "Native" app, from a user's perspective. And this can now be done directly from the web.&lt;/p&gt;

&lt;p&gt;Unlike regular web apps with simple homescreen links or bookmarks, PWAs can be downloaded in advance and can work offline, as well as use regular Web APIs. &lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps" rel="noopener noreferrer"&gt;Progressive Web Apps | MDN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This has not been added to iOS Safari up to now (iOS 13, 2019).&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;Web standards have bridged the gap with "Native" mobile apps enough that today, &lt;strong&gt;for most mobile apps&lt;/strong&gt;, the only reason to prefer some form of "Native" entanglement is really due to the App and Play Stores channels for delivery and profitability. &lt;strong&gt;You just have to be in the app stores&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Much like Microsoft tried to lock their user base to Internet Explorer Web APIs in the past, Apple today seems to be forcefully ridging the perception of web platform vs app store apps in iOS. It is doing so by not implementing web platform enhancements that are key to bringing web apps to be enabled and used as first class citizens (like "Native" apps) by the user.&lt;/p&gt;

&lt;p&gt;I'm not even original in this comparison, others have been noticing it too for a variety of reasons: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.safari-is-the-new-ie.com" rel="noopener noreferrer"&gt;safari-is-the-new-ie.com&lt;/a&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/nektro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F10538%2F7b306000-9464-4426-9f7e-400f0bdbc59d.jpg" alt="nektro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/nektro/safari-is-the-new-internet-explorer-1df0" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Safari is the New Internet Explorer&lt;/h2&gt;
      &lt;h3&gt;Meghan (she/her) ・ Jan 14 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#safari&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rephrasing Steve Jobs on &lt;a href="https://www.apple.com/hotnews/thoughts-on-flash/" rel="noopener noreferrer"&gt;Thoughts on flash&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;New open standards created in the mobile era, such as HTML5, will win on mobile devices (and PCs too).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perhaps Apple should focus more on creating great HTML5 tools for the future, and less on blocking out the web platform from being a first class citizen on mobile.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>safari</category>
      <category>ios</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
