<?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>DEV Community: Mike Hartington</title>
    <description>The latest articles on DEV Community by Mike Hartington (@mhartington).</description>
    <link>https://dev.to/mhartington</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%2F11268%2F75c600d1-fee4-4b04-be24-dcbd5080509a.jpg</url>
      <title>DEV Community: Mike Hartington</title>
      <link>https://dev.to/mhartington</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mhartington"/>
    <language>en</language>
    <item>
      <title>Announcing Ioniconf 2020</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Thu, 21 May 2020 15:41:01 +0000</pubDate>
      <link>https://dev.to/ionic/announcing-ioniconf-2020-5hlh</link>
      <guid>https://dev.to/ionic/announcing-ioniconf-2020-5hlh</guid>
      <description>&lt;p&gt;It’s finally happening! The moment that’s been talked about, questioned, speculated, humbly requested, not so humbly requested, and otherwise called for by many a community member …the first-ever Ionic conference.&lt;/p&gt;

&lt;p&gt;You heard it right, folks. Announcing &lt;a href="https://ionicframework.com/ioniconf" rel="noopener noreferrer"&gt;Ioniconf 2020&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ionicframework.com/ioniconf" rel="noopener noreferrer"&gt;Ioniconf 2020&lt;/a&gt; is an all digital event taking place June 24th (t-minus 34 days and counting) from the comfort of your own home! We’ve brought together industry leaders to share everything they can about Ionic and the Web Platform, in a celebration of the web and web developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need to know
&lt;/h2&gt;

&lt;p&gt;Let’s share some backstory here, because it’s been a wild ride getting this event up and running. Rewind back to my first ngConf in 2015. After the conference was over, a few of us on the Ionic team and some community members were celebrating a successful trip when one brought the idea of an Ionic conference. “Yeah, we’ll have the event in Vegas, I’ll help you all out in setting up the details, and it will be great. It will be something to celebrate this amazing community and bring in people who are experts in our industry to share their knowledge.”&lt;/p&gt;

&lt;p&gt;Well, you know how it goes. Planning and executing a physical event is no easy - or cheap - endeavor. And as weeks turned to months, and months turned to years, we put off the idea until we were ready. &lt;/p&gt;

&lt;p&gt;Well, given the current climate and the growing acceptance of (nay, clamoring for) virtual events, we decided that the time was indeed right. And now here we are. &lt;/p&gt;

&lt;p&gt;And just like we originally envisioned, &lt;a href="https://ionicframework.com/ioniconf" rel="noopener noreferrer"&gt;Ioniconf 2020&lt;/a&gt; will be a celebration of the Ionic community. A fun-filled day focused on education, sharing, and enlightenment in the ways of the web.  &lt;/p&gt;

&lt;p&gt;The format is a one day, single track, online conference covering all things related to web development and Ionic. Attendees can sit back and enjoy a full day of amazing talks, plus Q&amp;amp;A with speakers after sessions. We’ll be watching for questions from social media, so be sure to tag your questions with &lt;a href="https://twitter.com/intent/tweet?text=I%20want%20to%20know%20%22%22%20%23AskIoniconf2020" rel="noopener noreferrer"&gt; &lt;code&gt;#AskIoniconf2020&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for details about Ioniconf 2020 in the coming weeks as we add speakers, topics, and other exciting details. We are excited to put this event on and we hope you’ll join us!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ionicframework.com/ioniconf" rel="noopener noreferrer"&gt;SIGN UP AND HELP CELEBRATE OUR COMMUNITY →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>community</category>
      <category>conference</category>
    </item>
    <item>
      <title>Is Apple trying to kill PWAs?</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Thu, 02 Apr 2020 16:19:45 +0000</pubDate>
      <link>https://dev.to/ionic/is-apple-trying-to-kill-pwas-4g78</link>
      <guid>https://dev.to/ionic/is-apple-trying-to-kill-pwas-4g78</guid>
      <description>&lt;p&gt;It seems that any time Apple releases something there is bound to be some noise regarding it. This time, it's in regards to browser storage and Apple’s &lt;a href="https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/"&gt;recent proclamation&lt;/a&gt; that such data will be deleted after 7 days. Well let's break this down and see what this really means for developers.&lt;/p&gt;

&lt;p&gt;Let me start by saying that these are only my opinions. These do not reflect the opinions of Ionic or the rest of my coworkers. In fact, there’s healthy disagreement and differing views among our team, as I’m sure there are on yours.&lt;/p&gt;

&lt;p&gt;Recently, Apple released a blog post talking about their latest enhancements to Intelligent Tracking Prevention. There's a lot to this blog post, but the part that stuck out to everyone was&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now ITP has aligned the remaining script-writable storage forms with the existing client-side cookie restriction, deleting all of a website’s script-writable storage after seven days of Safari use without user interaction on the site. These are the script-writable storage forms affected (excluding some legacy website data types):&lt;/p&gt;

&lt;p&gt;Indexed DB&lt;br&gt;
LocalStorage&lt;br&gt;
Media keys&lt;br&gt;
SessionStorage&lt;br&gt;
Service Worker registrations&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wait what? Apple is going to clear out my site's storage after seven days? WTF Apple?? This seems to be the reaction that most people are having on Twitter, Hacker News, etc. The backlash was so strong that the blog post author went back and added some additional comments to clarify exactly what they meant. So what does this mean?&lt;/p&gt;

&lt;h2&gt;
  
  
  📞 Seven days...
&lt;/h2&gt;

&lt;p&gt;Well from the very beginning, it's been pretty vague what is considered "Seven days of use". I kept thinking about the scene from "Scary Movie 3" where the main character has an argument about what "Seven Days" really means (a gem in an otherwise 'meh' movie). Well after thinking about the blog post for a few days now, I think I finally have the breakdown.&lt;/p&gt;

&lt;p&gt;Inside of Safari, there is an internal counter. Let's say you access Site A (&lt;a href="https://startrack-ng.web.app" rel="noopener noreferrer"&gt;startrack-ng.web.app&lt;/a&gt;). Site A has a service worker and when you visit it, it registers the service worker with Safari. You leave the site and don't touch your phone for the rest of the day. The next day, you use your phone again and go to Site A. Since you've used Site A again, there is no day counted against you.&lt;/p&gt;

&lt;p&gt;So now you wait another day, you open Safari, but this time you go to Site B. You read some articles, close out the browser and don't use your phone. After this day, you have now reached one day of Safari use without interacting with Site A. You are now down to six days.&lt;/p&gt;

&lt;p&gt;The next day you don't use Safari at all. You still use your phone, but you haven't actually opened the browser. Well since you haven't used Safari, you do not accrue another day. So your count will still be at six days remaining.&lt;/p&gt;

&lt;p&gt;This is the pattern. You have seven days of Safari use for users to visit your site. If after seven days of Safari use, your site is not loaded, the script-writable storage will be cleared out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Home Screen Apps
&lt;/h2&gt;

&lt;p&gt;One of the questions that did arise out of the Twitter/Hacker News backlash was with regards to apps on the home screen. Since they are not loaded through Safari, what's their counter logic? Turns out, they effectively do not have a counter. Well, they do, but the same logic as above is applied. Since they only load one web app, their counter will effectively never hit seven days.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capacitor/Cordova Apps
&lt;/h2&gt;

&lt;p&gt;Similar to Home Screen Apps, Capacitor/Cordova apps are not affected by this. Some interesting technical details here...it seems the counter is limited to Safari-based apps. Since Cap/Cordova Apps use WKWebview, they actually don't have a counter at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, I believe you, but my Twitter circle doesn't
&lt;/h2&gt;

&lt;p&gt;So if this is the case, what is all the frustration about? There seems to be an inherent distrust when it comes to Apple and the web. A lot of people see Apple as the villain in the Web Ecosystem, wanting to kill it in favor of the iOS App Store. While Apple is certainly an odd-duck when it comes to its behavior in the Web Ecosystem, I do not see them as the villain.&lt;/p&gt;

&lt;p&gt;Apple and Safari have made their claim on being a fast, secure, and private browser. That's their mission statement. Everything that Safari/Webkit does all goes to make sure users have a fast browser that doesn't use their data for ads or malicious intents. When third-party sources attempt to track you and identify who you are, this goes against Safari's goals.&lt;/p&gt;

&lt;p&gt;Let's go back to Service Worker, since it seems to be the most contentious change. As it stands, the Service Worker Spec does not define a limit on how long a registration should last. I read this &lt;a href="https://adactio.com/journal/16619"&gt;blog post&lt;/a&gt; from &lt;a href="https://twitter.com/adactio"&gt;Jeremy Keith&lt;br&gt;
&lt;/a&gt; and came across this passage:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So I was curious. Wanting to give Apple the benefit of the doubt, I set about trying to find out how long service worker registrations currently last before getting deleted. Maybe this announcement of a seven day time limit would turn out to be not such a big change from current behavior. Maybe currently service workers last for 90 days, or 60, or just 30.&lt;br&gt;
&lt;a href="https://twitter.com/jonathandavis/status/1242918858324725760"&gt;Nope&lt;/a&gt;:&lt;br&gt;
There was no time limit previously.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which links to a &lt;a href="https://twitter.com/jonathandavis/status/1242918858324725760"&gt;tweet from Safari's Dev Rel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I will say this, yeah this is a drastic change. I can think of a few situations where this will hurt my user experience. But I do think that having no limit on service worker life is even more dangerous. Considering how powerful service workers are, they should have some limitations to make sure they do not become an attack vector for fingerprinting.&lt;/p&gt;

&lt;h2&gt;
  
  
  PWA !== Service Workers
&lt;/h2&gt;

&lt;p&gt;There are a lot of people who see service workers as a key part of Progressive Web Apps. If you are not adding a service worker to your site, it's not a PWA. I respectfully disagree. A PWA is not a specification. There is no official document that says "A PWA is A,B,C", and there shouldn't be. PWA is defined by best practices. Tying PWA to a specific API seems like a mistake and does more harm. &lt;/p&gt;

&lt;h2&gt;
  
  
  Is Apple Trying to kill the Web?
&lt;/h2&gt;

&lt;p&gt;No, Apple is not trying to kill the web. The people who work on Safari love the web and want to see the web’s continued growth. What I think we’re seeing is a conflict of culture, goals, and priorities. Developers constantly want new bells and whistles but haven’t considered what all that means. While it might be difficult to have a voice in the community push back and say “we should have limits”, it’s a conversation I think we all should be having. &lt;/p&gt;

&lt;p&gt;Thanks y’all for listening, I would love to know your thoughts on this as well. Cheers!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>pwa</category>
      <category>apple</category>
      <category>ios</category>
    </item>
    <item>
      <title>Deploying an Ionic PWA to ZEIT</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Thu, 19 Mar 2020 14:26:34 +0000</pubDate>
      <link>https://dev.to/ionic/deploying-an-ionic-pwa-to-zeit-b55</link>
      <guid>https://dev.to/ionic/deploying-an-ionic-pwa-to-zeit-b55</guid>
      <description>&lt;p&gt;There's no shortage of fantastic hosting providers these days. If you're looking to deploy a web app, you really can't pick wrong. But there are a few that stand out as being the best hosting solution for Progressive Web Apps. Today we're going to look at how to deploy an Ionic React app to &lt;a href="https://zeit.co/home" rel="noopener noreferrer"&gt;ZEIT&lt;/a&gt; and how simple ZEIT makes the whole process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ZEIT?
&lt;/h2&gt;

&lt;p&gt;When I say "ZEIT", what I really mean is their static site platform, &lt;a href="https://zeit.co/docs" rel="noopener noreferrer"&gt;Now&lt;/a&gt;. This platform provides a fast and scalable solution for static sites, JAMstack based web apps, and Serverless Functions. For our use case, we're just going to be utilizing the static hosting, but I highly suggest you take a look at the &lt;a href="https://zeit.co/docs/v2/serverless-functions/introduction"&gt;Serverless portion of their docs&lt;/a&gt;, as this could be your one stop shop for all your future apps. The serverless features become very compelling though once you consider SSR with Ionic Angular and Ionic React.&lt;/p&gt;

&lt;p&gt;With ZEIT, we can simply connect an existing app that is on GitHub, configure the build commands, and we'll have our app deployed almost instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The App itself
&lt;/h2&gt;

&lt;p&gt;For this demo, I'll just use a sidemenu based template and use React for my framework. ZEIT itself can support more than React, so if you're using Angular, the process will be similar.&lt;/p&gt;

&lt;p&gt;I'll create my app and connect it to a GitHub repo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ionic start zeit-pwa sidemenu &lt;span class="nt"&gt;--type&lt;/span&gt; react

&lt;span class="nb"&gt;cd &lt;/span&gt;zeit-pwa

git remote add origin git@github.com:mhartington/zeit-pwa.git

git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the app portion, this is all we need, so let's move over to Zeit's dashboard and connect the app. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sBQAAada--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.07.22-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sBQAAada--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.07.22-PM.png" alt="" class="aligncenter size-full wp-image-3210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the dashboard, we're presented with the option to import a new project. Once we click on that, we're given the option to either start from a new template (a blank slate) or import from a git repository. Since our project is already on GitHub, we'll select that and connect our GitHub account.&lt;/p&gt;

&lt;p&gt;Once connected, we can click "Import from GitHub", search our repositories for the project, and select it. Once we've confirmed the project import, we'll be prompted to enter an app name. By default this will just be the repo name, which will be fine for our test. We'll hit continue for this and the next prompt which asks us for the project root. Since &lt;br&gt;
our app is not in a mono-repo setup, the default here works just fine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--00n4weLr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.10.22-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--00n4weLr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.10.22-PM.png" alt="" class="aligncenter size-full wp-image-3208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next segment is the one that is the most important. We'll need to modify the output directory and development command. Since this is a React project, our output directory will be &lt;code&gt;build&lt;/code&gt;, and our development command will be &lt;code&gt;npm run start&lt;/code&gt;. For Angular projects, the output directory would be either WWW or the outputPath value in your angular.json and the development command would be &lt;code&gt;npm run start&lt;/code&gt;. With this information corrected, we can hit deploy and ship our app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bXJnojvW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.16.19-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bXJnojvW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.16.19-PM.png" alt="" class="aligncenter size-full wp-image-3207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With our project created, it will take about a minute for our app to be built and deployed to a live URL. For my app, the url is &lt;a href="https://zeit-pwa.now.sh" rel="noopener noreferrer"&gt;zeit-pwa.now.sh&lt;/a&gt;. All apps deployed through ZEIT will be assigned a &lt;code&gt;.now.sh&lt;/code&gt; suffix domain. But this can be configured to use a custom domain.&lt;/p&gt;

&lt;p&gt;With our app now setup and deployed, any time we commit changes and push them to GitHub, ZEIT will automatically trigger a new build. Once the build is completed, our app will be deployed and will be live!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nEmrC4V0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.18.23-PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nEmrC4V0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-17-at-12.18.23-PM.png" alt="" class="aligncenter size-full wp-image-3206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting thoughts
&lt;/h2&gt;

&lt;p&gt;ZEIT, Now, and the whole product suit is quite a compelling service. Given its easy integration with popular frameworks/libraries, simple setup with existing Git repositories, and overall speed, it's pretty obvious why it's starting to look like a premier solution for PWAs. There's a lot more that can be done with ZEIT/Now, so be sure to check out their documentation. Cheer!&lt;/p&gt;

</description>
      <category>tutorials</category>
      <category>ionic</category>
      <category>zeit</category>
      <category>serverless</category>
    </item>
    <item>
      <title>SSR with Angular Universal And Ionic</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Thu, 05 Mar 2020 14:30:50 +0000</pubDate>
      <link>https://dev.to/ionic/ssr-with-angular-universal-and-ionic-3a32</link>
      <guid>https://dev.to/ionic/ssr-with-angular-universal-and-ionic-3a32</guid>
      <description>&lt;p&gt;So, Angular universal is a thing... And it seems it is something you all have been very excited about for some time. Since I &lt;a href="https://twitter.com/mhartington/status/1160941457131356164" rel="noopener noreferrer"&gt;tweeted about this&lt;/a&gt; some time ago, it's been one of the top 3 most common questions asked of us (right behind "when's Ionic Vue going to be ready"). Well I did promise that it would be happening soon and that there would indeed be a blog post, so let's take care of that today!&lt;/p&gt;

&lt;p&gt;Introducing the &lt;code&gt;@ionic/angular-server&lt;/code&gt; module for Angular Universal!&lt;/p&gt;

&lt;h2&gt;
  
  
  Universal JavaScript
&lt;/h2&gt;

&lt;p&gt;First off, what is Universal JavaScript anyway? Essentially it's JavaScript that can run on the server and in the browser. This is what people refer as "Server Side Rendering" (SSR). By utilizing SSR and Universal JavaScript in our app, we can do an initial render of our app on the server and send over a precompiled version before any JavaScript has been run on the client. With this technique we can achieve&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster load times &lt;sup&gt;1&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;Better SEO ranking&lt;/li&gt;
&lt;li&gt;Preview cards on social media&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Faster load times can vary and can really fluctuate depending on your app &amp;amp; other circumstances. Your mileage may vary.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;So if SSR can help us, how can we add it to our app? Well up until recently, you couldn't. A lot of Ionic's components utilize &lt;code&gt;window&lt;/code&gt; and other DOM specific APIs. Since we're on a server and running in Node, we don't have the DOM. This is where Angular Universal and &lt;code&gt;@ionic/angular-server&lt;/code&gt; module comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Universal
&lt;/h2&gt;

&lt;p&gt;Angular Universal is Angular's library for running our apps on the server. In earlier releases of Angular (and AngularJS), setting up an app to run on the server was a bit of a pain. Thankfully, Angular Universal and it's various runtimes make this really straight forward.&lt;/p&gt;

&lt;p&gt;First let's create an app and update it to the latest version of Angular&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ionic start myApp blank &lt;span class="nt"&gt;--type&lt;/span&gt; angular
&lt;span class="nb"&gt;cd &lt;/span&gt;myApp
ng update @angular/core @angular/cli
npm &lt;span class="nb"&gt;install&lt;/span&gt; @angular/animations
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once this has completed, let's add the Express engine for Angular Universal&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Express is a popular framework for Node. For more information, please checkout the &lt;a href="https://expressjs.com" rel="noopener noreferrer"&gt;Express website&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ng add @nguniversal/express-engine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will set up our project to be ready for Angular Universal. Before we continue any further, let's install the &lt;code&gt;@ionic/angular-server&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ionic/angular-server@dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@ionic/angular-server&lt;/code&gt; is currently part of a dev release and will be part of an upcoming release of Ionic. Be sure to keep an eye out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let's open our editor and inspect our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lay of the Land
&lt;/h2&gt;

&lt;p&gt;After Angular Universal is added to our project, you'll notice some &lt;code&gt;*.server.*&lt;/code&gt; related files around the project. Specifically a &lt;code&gt;main.server.ts&lt;/code&gt; and a &lt;code&gt;app.server.module.ts&lt;/code&gt;. These two files in particular are responsible for bootstrapping our app once it is loaded on the server. We can see what this will be like by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev:ssr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will start our live reload server for our SSR app. Don't be surprised if you see a lot of output from the terminal, we actually have a lot going on here. This script is performing a build of our client side app, as well as building out the server side portion as well. Once this has finished, we'll get a message that our app is available to load on &lt;code&gt;localhost:4200&lt;/code&gt;. Once loaded, our app looks like an normal Ionic App. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--um6SOfrc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-05-at-11.53.59-AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--um6SOfrc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-05-at-11.53.59-AM.png" alt="" class="aligncenter size-full wp-image-3187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But if we disable JavaScript on our page, we'll end up getting a blank screen. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kGt-YM0k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-05-at-11.54.22-AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kGt-YM0k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ionicframework.com/wp-content/uploads/2020/03/Screen-Shot-2020-03-05-at-11.54.22-AM.png" alt="" class="aligncenter size-full wp-image-3188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What gives? Well this is where the &lt;code&gt;@ionic/angular-server&lt;/code&gt; module comes in. &lt;/p&gt;

&lt;p&gt;First, let's stop our server for a bit and open our &lt;code&gt;src/app/app.server.module.ts&lt;/code&gt;. Here is where our app will bootstrap when it is deployed to our server. Without diving into too many details, Angular Universal provides an entry hook so we can handle situations where our components will be rendered on the server. To take advantage of this, we'll import &lt;code&gt;IonicServerModule&lt;/code&gt; and add it to the imports array of our &lt;code&gt;ngModule&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&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="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;ServerModule&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="s1"&gt;@angular/platform-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;AppModule&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="s1"&gt;./app.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;AppComponent&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="s1"&gt;./app.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Tell Ionic components how to render on the server&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;IonicServerModule&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="s1"&gt;@ionic/angular-server&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="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ServerModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;IonicServerModule&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AppServerModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once this has been added, we can run our dev-server again and see that our app will still work, even if JavaScript has been disabled.&lt;/p&gt;


  


&lt;h2&gt;
  
  
  Some technical details
&lt;/h2&gt;

&lt;p&gt;Now if we wanted to we could deploy our app to different providers (Firebase Cloud Functions for example) and be off to the races, but that doesn't cover everything. You should validate that any library being used can work in situations where there is no &lt;code&gt;window&lt;/code&gt; object. Since Universal still isn't too common of a practice, many DOM specific libraries either haven't added support for Universal, or simply just can’t. If you’re using libraries built with Angular, you should be good. If you’re not sure if your project will have issues, the output from a full server build should point you to the problematic library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting thoughts
&lt;/h2&gt;

&lt;p&gt;Since this is only a pre-release of Angular Universal support, we’re looking to get feedback from users. We’ve tested things pretty extensively, but we’d love for you to try it out and let us know if you run into any issues.&lt;/p&gt;

&lt;p&gt;We've really only scratched the surface of what can be done. There's topic's like prerender, state transfer, and even static site generation (via Scully) that are now available to us with Angular Universal. &lt;/p&gt;

&lt;p&gt;This really is an exciting time to be working in Angular with Ionic. There's a lot more information available out there and I'd encourage people to check out a few resources listed below. As for now, try out the Universal module, let us know if you run into any issues, and thank you for being so patient while we work on it! Cheers 🍻&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://angular.io/guide/universal"&gt;Angular Universal Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/scullyio/scully"&gt;Scully, A static site generator for Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=EiiZAGkiUXE"&gt;Universally Speaking, A talk by Craig Spence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>ssr</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>A New Package for the CLI</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Tue, 04 Feb 2020 15:40:02 +0000</pubDate>
      <link>https://dev.to/ionic/a-new-package-for-the-cli-550c</link>
      <guid>https://dev.to/ionic/a-new-package-for-the-cli-550c</guid>
      <description>&lt;p&gt;TL;DR, we're re-releasing the CLI package under a new name, &lt;code&gt;@ionic/cli&lt;/code&gt;!&lt;br&gt;
To update, first you will need to uninstall the old CLI package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; ionic
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ionic/cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will still interact with the CLI via &lt;code&gt;ionic&lt;/code&gt; command, just how the CLI is installed has changed. And now, on with the blog post!&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything has a beginning
&lt;/h2&gt;

&lt;p&gt;Many years ago, when Ionic was still in it's pre 1.0, we saw a great opportunity to help devs build amazing apps without having to guess how that would be done. While the V1 days of Ionic included things like bower, scripts tags, and gulp, it was our first attempt to make a tool that did everything for you. After building out all the initial functionality, we had one last task...what do we call this tool?&lt;/p&gt;

&lt;p&gt;We called it...Ionic!&lt;/p&gt;

&lt;p&gt;Our initial logic was that we would have one tool and one framework that covered everything. Want to build apps with Ionic? Just install Ionic. This worked great, and for a long time we were set on just keeping things as they were. That is until we started noticing a common point of confusion with our users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What version of Ionic are you using?
&lt;/h2&gt;

&lt;p&gt;When debugging a user issue or working with community members, one of the first things we ask people is "What version of Ionic are you using?" This has led to some confusion in the community as people would assume that &lt;code&gt;ionic -v&lt;/code&gt; would give them the version of both the framework and the CLI. This however is not the case. One or two instances would be enough to ignore this, but given how common this is, we thought it was finally time to solve this issue.&lt;/p&gt;

&lt;p&gt;As the number of packages under the Ionic organization has grown, we would ship them under the scoped package name. Our release of Ionic for Angular? &lt;code&gt;@ionic/angular&lt;/code&gt;. React? &lt;code&gt;@ionic/react&lt;/code&gt;. This is a pretty clear message that when you install one of these packages, you know exactly what you are getting. There is no confusion in this package's purpose or what context this package should be used in. &lt;/p&gt;

&lt;h2&gt;
  
  
  Moving towards a scoped package
&lt;/h2&gt;

&lt;p&gt;To help with this confusion, we're rereleasing the CLI package under a new name, &lt;code&gt;@ionic/cli&lt;/code&gt;. This unifies how we ship tools across Ionic and make sure that people are aware what tool they are installing when setting up their environment. I mentioned this last week in an Ionic newsletter and so far the feedback from the community has been incredibly supportive.&lt;/p&gt;

&lt;p&gt;In the past this has been a suggestion that many community members have made and as time has gone on, it seems to be the move many other CLI tools have done. Angular in particular rebranded the &lt;code&gt;angular-cli&lt;/code&gt; package in favor of &lt;code&gt;@angular/cli&lt;/code&gt; and the Vue CLI has done the same thing (&lt;code&gt;vue-cli&lt;/code&gt; to &lt;code&gt;@vue/cli&lt;/code&gt;). With this in mind, we finally decided it was time.&lt;/p&gt;

&lt;p&gt;To update to the new CLI, you must first uninstall the old CLI package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; ionic

&lt;span class="c"&gt;# Then install the new CLI package&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @ionic/cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This new package name coincides with the release of the CLI’s 6.0. This includes some new features which can all be reviewed in the &lt;a href="https://github.com/ionic-team/ionic-cli/blob/develop/packages/%40ionic/cli/CHANGELOG.md#600-2020-01-25"&gt;Changelog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The old CLI package will not be updated to the newer 6.0 releases and has an official deprecated warning now. While this should work for some time, we encourage everyone to update to the new CLI package to receive all the latest updates.&lt;/p&gt;

&lt;p&gt;Well that’s all for now folks! We are glad the feedback so far has been super supportive of this change and can’t wait for you all to upgrade….Seriously, we can’t wait. Upgrade your CLI 😄.&lt;br&gt;
Cheers! &lt;/p&gt;

</description>
      <category>ionic</category>
      <category>cli</category>
    </item>
    <item>
      <title>Angular 9.0.0 and Ivy improvements</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Thu, 19 Dec 2019 17:49:06 +0000</pubDate>
      <link>https://dev.to/ionic/angular-9-0-0-and-ivy-improvements-4ah6</link>
      <guid>https://dev.to/ionic/angular-9-0-0-and-ivy-improvements-4ah6</guid>
      <description>&lt;p&gt;One of the biggest updates in the pipeline right now is the upcoming release of Angular 9.0.0. Currently in RC, Angular 9.0 will hopefully ship early next year. But this release includes so much that I thought it required a post to highlight some of the most important updates. Now for Ionic devs, why should they care about this? Well given that most apps currently are built with Angular and Ionic, any improvements to the overall ecosystem should always be welcomed! But given the goals of Angular 9.0, this directly impacts (in a positive way) Ionic be being able to ship faster and smaller apps, in faster manner. For reference, we'll be looking at the Angular version of the Star Track demo app - built with Ionic 4 and Angular - and checking out the improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ivy By Default
&lt;/h2&gt;

&lt;p&gt;One of the biggest improvements to Angular coming in 9.0 is that Ivy is enabled by default. Ivy is Angular's new renderer. A super high level overview is that Ivy enables apps to only require pieces of the render that they actually need, instead of the whole thing. This means that our final output will be smaller, which is always better for performance. It's important to note, that Ivy won't make your components/app significantly smaller if you're using every feature available to Angular. But there are noticeable improvements to the &lt;code&gt;main.js&lt;/code&gt; chunk of an app.&lt;/p&gt;

&lt;p&gt;For comparison, let’s look at the build output from Star Track with Ivy enabled and with it disabled. We’ll compare the size of the &lt;code&gt;main.js&lt;/code&gt; file, which is mostly going to be Angular specific code.&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="c"&gt;# Ivy disabled&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ng build &lt;span class="nt"&gt;--prod&lt;/span&gt;
...
chunk &lt;span class="o"&gt;{&lt;/span&gt;10&lt;span class="o"&gt;}&lt;/span&gt; main-es2015.d03d9cadf1579320f520.js &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; 537 kB &lt;span class="o"&gt;[&lt;/span&gt;initial] &lt;span class="o"&gt;[&lt;/span&gt;rendered]
chunk &lt;span class="o"&gt;{&lt;/span&gt;10&lt;span class="o"&gt;}&lt;/span&gt; main-es5.d03d9cadf1579320f520.js &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; 628 kB &lt;span class="o"&gt;[&lt;/span&gt;initial] &lt;span class="o"&gt;[&lt;/span&gt;rendered]
...


&lt;span class="c"&gt;# Ivy enabled&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ng build &lt;span class="nt"&gt;--prod&lt;/span&gt;
...
chunk &lt;span class="o"&gt;{&lt;/span&gt;10&lt;span class="o"&gt;}&lt;/span&gt; main-es2015.bfc9e260b847bc2b02fc.js &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; 465 kB &lt;span class="o"&gt;[&lt;/span&gt;initial] &lt;span class="o"&gt;[&lt;/span&gt;rendered]
chunk &lt;span class="o"&gt;{&lt;/span&gt;10&lt;span class="o"&gt;}&lt;/span&gt; main-es5.bfc9e260b847bc2b02fc.js &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; 551 kB &lt;span class="o"&gt;[&lt;/span&gt;initial] &lt;span class="o"&gt;[&lt;/span&gt;rendered]
..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From 537kb/628kb without Ivy, to 465kb/551kb with it! Note that Star Track is using almost every feature available from Angular, so delta is a bit smaller, but still a welcomed improvement!&lt;/p&gt;

&lt;p&gt;Now Ivy has been around for sometime in earlier release, but always as an opt-in feature. With 9.0, however, Ivy is enabled by default and developers need to opt-out manually. If Ivy is so great, why would developers need to opt-out of it? Well, as this is part of a new major version, there are bound to be some breaking changes here and there. Most of these are not change that app developers need to worry themselves with, but something that component authors would need to deal with. If you're using third-party components/packages that have not updated, you'll want to opt-out of Ivy for now, and open an issue (or better yet, a pull request) against the repo.&lt;/p&gt;

&lt;p&gt;Ionic itself will be ready for Ivy when Angular 9.0 is shipped. I've been following along and making the necessary updates needed. We recently have merged a &lt;a href="https://github.com/ionic-team/ionic/pull/19515" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; and have been testing a build of Ionic and Angular 9.0. &lt;/p&gt;

&lt;h2&gt;
  
  
  EntryComponents...BYE BYE BYE
&lt;/h2&gt;

&lt;p&gt;If you've been working with Angular for some time now, you know that one of the most frustrating things to deal with are &lt;code&gt;entryComponents&lt;/code&gt;. &lt;code&gt;entryComponents&lt;/code&gt;, for the uninitiated, are components that Angular will load imperatively and not through a template. For Ionic, this means overlay components like Modals and Popovers make heavy use of &lt;code&gt;entryComponent&lt;/code&gt; for figuring out what to actually render. From a users perspective, there's often a bit of a hiccup when working with Modals/Popovers. The process typically goes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate a new component&lt;/li&gt;
&lt;li&gt;Splitting it out into its own module&lt;/li&gt;
&lt;li&gt;Attempt to load the component in an overlay&lt;/li&gt;
&lt;li&gt;Get an obscure error about a Module Factory&lt;/li&gt;
&lt;li&gt;Realize you forgot to add setup entryComponents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was such a common issue that we even modified the component schematic from Angular to include options for auto-adding components to &lt;code&gt;entryComponents&lt;/code&gt;. Thankfully, with 9.0, this is a thing of the past!&lt;/p&gt;

&lt;p&gt;With the way components are compiled (thanks to Ivy), &lt;code&gt;entryComponent&lt;/code&gt;s are no longer needed. So Modals and Popovers just become much easier to think about.&lt;/p&gt;

&lt;h2&gt;
  
  
  CLI Improvements
&lt;/h2&gt;

&lt;p&gt;In addition to improvements coming to the framework itself, Angular's CLI is also getting some improvements as well. For starters, when serving your app, the app will automatically be built using AOT. This is a great improvement as we no longer have to deal with different environments for our apps. For example; you serve your app with &lt;code&gt;ionic serve&lt;/code&gt; or &lt;code&gt;ng serve&lt;/code&gt; and the app builds fine. There are no errors, the app loads, all is well! But, when you go to deploy and do a production build, an error appears. Why is the error there and why did it show up only during production? Well due to how components are built, AOT often is able to find potential errors before they happen at run time. Say you have a click handler like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ion-content&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Click the button&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ion-button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"logEvent($event)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="nt"&gt;&amp;lt;/ion-button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ion-content&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the component class looks like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({...})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(){...}&lt;/span&gt;

  &lt;span class="nf"&gt;logevent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;The small error here is that the click handler is for &lt;code&gt;logEvent&lt;/code&gt;, but the actual method is called &lt;code&gt;logevent&lt;/code&gt;. This would result in a runtime error, which we do not want. Thanks to being able to run AOT when running serve, we can now catch small errors like this and get meaningful feedback before they ever happen.&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%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2019%2F12%2FScreen-Shot-2019-12-11-at-3.04.33-PM.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%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2019%2F12%2FScreen-Shot-2019-12-11-at-3.04.33-PM.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another improvement is with differential builds. In previous releases, the Angular CLI would perform two different builds, on for ES5 environments and one for ES2015. This process produced the ES5 builds first, then would go back and rebuild the app for ES2015, which could make your production builds take a long time if the app was rather large. With 9.0, the CLI will now change how this is done. Instead of building the ES5 version, the CLI will do a ES2015 build of your app first. From there, that ES2015 build will go through a much quick build process to produce a ES5 build with the necessary polyfills. This is a small and subtle change, but can make your build time much faster!&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting Thoughts
&lt;/h2&gt;

&lt;p&gt;Angular 9.0 is still in RC (RC6) as of now and most likely won't be shipping before the year is over (good news IMO). But with all the improvements we've gone over here, Angular 9.0 will be a welcome update that should help every developer be successful! Cheers 🍻&lt;/p&gt;

</description>
      <category>angular</category>
      <category>ionic</category>
      <category>webdev</category>
      <category>webperf</category>
    </item>
    <item>
      <title>Progressive Web Apps in Ionic React</title>
      <dc:creator>Mike Hartington</dc:creator>
      <pubDate>Wed, 20 Nov 2019 22:06:18 +0000</pubDate>
      <link>https://dev.to/ionic/progressive-web-apps-in-ionic-react-5fb8</link>
      <guid>https://dev.to/ionic/progressive-web-apps-in-ionic-react-5fb8</guid>
      <description>&lt;p&gt;With the launch of Ionic React a few weeks back, the reception from the community has been incredible. We’re thrilled that so many of you are excited to use Ionic React, and I myself was excited to try React a bit more. Given that I spend most of my time with Angular, it was fun to see what another framework could offer as I learned how to "think" in React.&lt;/p&gt;

&lt;p&gt;With that in mind, I wanted to share my experience rebuilding a personal demo app that I have built in Angular (&lt;a href="http://startrack-ng.web.app" rel="noopener noreferrer"&gt;Star Track&lt;/a&gt;) and rebuild it in React. For this exercise, I’m going to focus on how I created a Progressive Web App (or PWA) with Ionic React. Let's dive in!&lt;/p&gt;

&lt;p&gt;If you would like to see the final results, you can see an early version of &lt;a href="https://gifted-volhard-a0566f.netlify.com/" rel="noopener noreferrer"&gt;Star Track React&lt;/a&gt; here.&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%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2019%2F11%2FScreen-Shot-2019-11-20-at-5.00.24-PM-2.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%2Fblog.ionicframework.com%2Fwp-content%2Fuploads%2F2019%2F11%2FScreen-Shot-2019-11-20-at-5.00.24-PM-2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  App Manifest
&lt;/h2&gt;

&lt;p&gt;Adding the App Manifest was fairly straightforward. &lt;/p&gt;

&lt;p&gt;If you’ve built with Angular, you’re probably used to running &lt;code&gt;ng add @angular/pwa&lt;/code&gt; and having one created for you. The logic here is that not everyone may need a PWA. &lt;/p&gt;

&lt;p&gt;With Create React App (CRA), however, a manifest and placeholder icons are provided out-of-the-box. This was nice, as I could quickly jump in there, make the edits I needed, and get back to building my app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Workers
&lt;/h2&gt;

&lt;p&gt;Service Workers are an essential part of the PWA experience. Without one, our apps would not be able to work offline or be resilient to flaky network connections. &lt;/p&gt;

&lt;p&gt;In Angular, we work with the &lt;code&gt;@angular/service-worker&lt;/code&gt; package to create and interact with our Service Worker. This allows us to express our caching strategy for our app's resources in a JSON files. &lt;/p&gt;

&lt;p&gt;So how does this work in React?&lt;/p&gt;

&lt;p&gt;Out-of-the-box, Create React App (CRA) utilized the &lt;a href="https://developers.google.com/web/tools/workbox" rel="noopener noreferrer"&gt;Workbox library&lt;/a&gt; from the Chrome team. By using Workbox's webpack plugin, we're able to get a complete list of all the resources our app needs and create a precache with a hash revision. This is done automatically at build time so there's no need for us to configure this.&lt;/p&gt;

&lt;p&gt;But we are putting the pig before the pen here, as we need to opt-in to Service Workers in our main &lt;code&gt;index.ts&lt;/code&gt; file. By default CRA has Service Workers disabled due to their advanced nature. The idea being that devs are not used to their content caching. While I disagree with this, I do appreciate that the team has noted their reason on the &lt;a href="https://create-react-app.dev/docs/making-a-progressive-web-app#why-opt-in" rel="noopener noreferrer"&gt;CRA docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To opt-in and register our Service Worker, we can call &lt;code&gt;serviceWorker.register()&lt;/code&gt;:&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;//index.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;serviceWorker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./serviceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// If you want your app to work offline and load faster, you can change&lt;/span&gt;
&lt;span class="c1"&gt;// unregister() to register() below. Note this comes with some pitfalls.&lt;/span&gt;
&lt;span class="c1"&gt;// Learn more about service workers: https://bit.ly/CRA-PWA&lt;/span&gt;
&lt;span class="c1"&gt;// serviceWorker.unregister();&lt;/span&gt;
&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this call, we're able to register the Service Worker that the build scripts will create for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling updates
&lt;/h2&gt;

&lt;p&gt;Since CRA internalizes a lot of moving pieces with Service Workers, I was worried that I would not have a mechanism for handling updates. But digging into the registration function, there's an optional &lt;code&gt;config&lt;/code&gt; parameter that could be passed that could handle this. The &lt;code&gt;config&lt;/code&gt; argument is an object that can accept an &lt;code&gt;onSuccess&lt;/code&gt; and &lt;code&gt;onUpdate&lt;/code&gt; key, with a callback function as their values. &lt;/p&gt;

&lt;p&gt;From this, we can modify our original &lt;code&gt;register&lt;/code&gt; call to pass a &lt;code&gt;config&lt;/code&gt; object:&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="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServiceWorkerRegistration&lt;/span&gt;&lt;span class="p"&gt;)&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;await&lt;/span&gt; &lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&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;Not a whole lot of magic happening here, but it's a bit clearer when looking at the registration function&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// At this point, the updated precached content has been fetched,&lt;/span&gt;
  &lt;span class="c1"&gt;// but the previous service worker will still serve the older&lt;/span&gt;
  &lt;span class="c1"&gt;// content until all client tabs are closed.&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New content is available and will be used when all tabs for this page are closed. See https://bit.ly/CRA-PWA.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Execute callback&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;config&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;onUpdate&lt;/span&gt;&lt;span class="p"&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="nf"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;registration&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;When our Service Worker has registered, we can hook into the lifecycles and trigger an update when the new content has been cached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting Thoughts
&lt;/h2&gt;

&lt;p&gt;While focusing mainly on Service Worker and App Manifest, I'm still diving deep into PWAs with React. With what I (and the rest of the Ionic team) learn while we build more and more Ionic React apps, we'll be able to provide the best suggestions for delivering fast, powerful, feature-rich apps with React. Cheers 🍻!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://startrack-ng.web.app" rel="noopener noreferrer"&gt;Star Track (Angular)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gifted-volhard-a0566f.netlify.com" rel="noopener noreferrer"&gt;Star Track (React)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ionicframework.com/docs/react/pwa" rel="noopener noreferrer"&gt;Ionic React PWA Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ionic</category>
      <category>react</category>
      <category>pwa</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
