{"id":68691,"date":"2019-07-31T04:19:20","date_gmt":"2019-07-31T11:19:20","guid":{"rendered":"http:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/"},"modified":"2019-07-31T04:19:20","modified_gmt":"2019-07-31T11:19:20","slug":"designing-and-building-a-progressive-web-application-without-a-framework-part-3","status":"publish","type":"post","link":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/","title":{"rendered":"Designing And Building A Progressive Web Application Without A Framework (Part 3)"},"content":{"rendered":"<link rel=\"canonical\" href=\"https:\/\/www.smashingmagazine.com\/2019\/07\/progressive-web-application-pwa-framework-part-3\/\"><title>Designing And Building A Progressive Web Application Without A Framework (Part 3)<\/title><\/p>\n<article>\n<header>\n<h1>Designing And Building A Progressive Web Application Without A Framework (Part 3)<\/h1>\n<address>Ben Frain<\/address>\n<p>                  <time datetime=\"2019-07-30T14:00:00+02:00\">2019-07-30T14:00:00+02:00<\/time><time datetime=\"2019-07-31T11:07:39+00:00\">2019-07-31T11:07:39+00:00<\/time><\/header>\n<p>Back in the <a href=\"https:\/\/www.smashingmagazine.com\/2019\/07\/progressive-web-application-pwa-framework-part-1\/\">first part<\/a> of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in vanilla JavaScript and to get a non-designing developer working his design chops a little.<\/p>\n<p>In <a href=\"https:\/\/www.smashingmagazine.com\/2019\/07\/progressive-web-application-pwa-framework-part-2\/\">part two<\/a> we took some basic initial designs and got things up and running with some tooling and technology choices. We covered how and why parts of the design changed and the ramifications of those changes.<\/p>\n<p>In this final part, we will cover turning a basic web application into a Progressive Web Application (PWA) and \u2018shipping\u2019 the application before looking at the most valuable lessons learned by making the simple web application In\/Out:<\/p>\n<ul>\n<li>The enormous value of JavaScript array methods;<\/li>\n<li>Debugging;<\/li>\n<li>When you are the only developer, you are the other developer;<\/li>\n<li>Design <em>is<\/em> development;<\/li>\n<li>Ongoing maintenance and security issues;<\/li>\n<li>Working on side projects without losing your mind, motivation or both;<\/li>\n<li>Shipping some product beats shipping no product.<\/li>\n<\/ul>\n<p>So, before looking at lessons learned, let\u2019s look at how you turn a basic web application written in HTML, CSS, and JavaScript into a Progressive Web Application (PWA).<\/p>\n<p>In terms of total time spent on making this little web-application, I\u2019d guestimate it was likely around two to three weeks. However, as it was done in snatched 30-60 minute chunks in the evenings it actually took around a year from the first commit to when I uploaded what I consider the \u20181.0\u2019 version in August 2018. As I\u2019d got the app \u2018feature complete\u2019, or more simply speaking, at a stage I was happy with, I anticipated a large final push. You see, I had done nothing towards making the application into a Progressive Web Application. Turns out, this was actually the easiest part of the whole process.<\/p>\n<div data-component=\"FeaturePanel\" data-audience=\"non-subscriber\" data-remove=\"true\"><\/div>\n<h3>Making A Progressive Web Application<\/h3>\n<p>The good news is that when it comes to turning a little JavaScript-powered app into a \u2018Progressive Web App\u2019 there are heaps of tools to make life easy. If you cast your mind back to <a href=\"https:\/\/www.smashingmagazine.com\/articles\/#\">part one<\/a> of this series, you\u2019ll remember that to be a Progressive Web App means meeting <a href=\"https:\/\/developers.google.com\/web\/progressive-web-apps\/checklist\">a set of criteria<\/a>.<\/p>\n<p>To get a handle on how your web-application measures up, your first stop should probably be the Lighthouse tools of Google Chrome. You can find the Progressive Web App audit under the \u2018Audits\u2019 tab.<\/p>\n<p>This is what Lighthouse told me when I first ran In\/Out through it.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/80b7d093-b657-4e80-abe8-8f34db93ede8\/pwa-framework-lighthouse2.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse2.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/80b7d093-b657-4e80-abe8-8f34db93ede8\/pwa-framework-lighthouse2.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/80b7d093-b657-4e80-abe8-8f34db93ede8\/pwa-framework-lighthouse2.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/80b7d093-b657-4e80-abe8-8f34db93ede8\/pwa-framework-lighthouse2.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/80b7d093-b657-4e80-abe8-8f34db93ede8\/pwa-framework-lighthouse2.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse2.png?w=900\" sizes=\"100vw\" alt=\"The Chrome dev tools showing Progressive Web App results of 55\/100\"><\/a><figcaption>\n      Initial scores for Progressive Web App weren\u2019t great. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/80b7d093-b657-4e80-abe8-8f34db93ede8\/pwa-framework-lighthouse2.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>At the outset In\/Out was only getting a score of <sup>55<\/sup>?<sub>100<\/sub> for a Progressive Web App. However, I took it from there to <sup>100<\/sup>?<sub>100<\/sub> in well under an hour!<\/p>\n<p>The expediency in improving that score was little to do with my ability. It was simply because Lighthouse told me exactly what was needed to be done!<\/p>\n<p>Some examples of requisite steps: include a <code>manifest.json<\/code> file (essentially a JSON file providing metadata about the app), add a whole slew of meta tags in the head, switch out images that were inlined in the CSS for standard URL referenced images, and add a bunch of home screen images.<\/p>\n<p>Making a number of home screen images, creating a manifest file and adding a bunch of meta tags might seem like a lot to do in under an hour but there are wonderful web applications to help you build web applications. How nice is that! I used <a href=\"https:\/\/app-manifest.firebaseapp.com\/\">https:\/\/app-manifest.firebaseapp.com<\/a>. Feed it some data about your application and your logo, hit submit and it furnishes you with a zip file containing everything you need! From there on, it\u2019s just copy-and-paste time.<\/p>\n<p>Things I&#8217;d put off for some time due to lack of knowledge, like a Service Worker, were also added fairly easily thanks to numerous blog posts and sites dedicated to service workers like <a href=\"https:\/\/serviceworke.rs\/\">https:\/\/serviceworke.rs<\/a>. With a service worker in place it meant the app could work offline, a requisite feature of a Progressive Web Application.<\/p>\n<p>Whilst not strictly related to making the application a PWA, the &#8216;coverage&#8217; tab of the Chrome Dev Tools were also very useful. After so much sporadic iteration on the design and code over months, it was useful to get a clear indication of where there was redundant code. I found a few old functions littering the codebase that I&#8217;d simply forgotten about!<\/p>\n<p>In short order, having worked through the Lighthouse audit recommendations I felt like the teacher\u2019s pet:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/59658e2c-0f69-4b84-b006-8a9c0dc06185\/pwa-framework-lighthouse4.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse4.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/59658e2c-0f69-4b84-b006-8a9c0dc06185\/pwa-framework-lighthouse4.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/59658e2c-0f69-4b84-b006-8a9c0dc06185\/pwa-framework-lighthouse4.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/59658e2c-0f69-4b84-b006-8a9c0dc06185\/pwa-framework-lighthouse4.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/59658e2c-0f69-4b84-b006-8a9c0dc06185\/pwa-framework-lighthouse4.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse4.png?w=900\" sizes=\"100vw\" alt=\"Getting a 100\/100 on Lighthouse Progressive Web App audit\"><\/a><figcaption>\n      Lighthouse makes it easy to get good scores by telling you exactly what to change. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/59658e2c-0f69-4b84-b006-8a9c0dc06185\/pwa-framework-lighthouse4.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The reality is that taking the application and making it a Progressive Web Application was actually incredibly straightforward.<\/p>\n<p>With that final piece of development concluded I uploaded the little application to a sub-domain of my website and that was it.<\/p>\n<h3>Retrospective<\/h3>\n<p>Months have passed since parking up development my little web application.<\/p>\n<p>I\u2019ve used the application casually in the months since. The reality is much of the team sports organization I do still happens via text message. The application is, however, definitely easier than writing down who is in and out than finding a scrap of paper every game night.<\/p>\n<p>So, the truth is that it\u2019s hardly an indispensable service. Nor does it set any bars for development or design. I couldn\u2019t tell you I\u2019m 100% happy with it either. I just got to a point I was happy to abandon it.<\/p>\n<p>But that was never the point of the exercise. I took a lot from the experience. What follows are what I consider the most important takeaways.<\/p>\n<div><\/div>\n<h3>Design <em>Is<\/em> Development<\/h3>\n<p>At the outset, I didn\u2019t value design enough. I started this project believing that my time spent sketching with a pad and pen or in the Sketch application, was time that could be better spent with coding. However, it turns that when I went straight to code, I was often just being a busy fool. Exploring concepts first at the lowest possible fidelity, saved far more time in the long run.<\/p>\n<p>There were numerous occasions at the beginning where hours were spent getting something working in code only to realize that it was fundamentally flawed from a user experience point of view.<\/p>\n<p>My opinion now is that paper and pencil are the finest planning, design and coding tools. Every significant problem faced was principally solved with paper and a pencil; the text editor merely a means of executing the solution. Without something making sense on paper, it stands no chance of working in code.<\/p>\n<p>The next thing I learned to appreciate, and I don\u2019t know why it took so long to figure out, is that design is iterative. I\u2019d sub-consciously bought into the myth of a Designer with a capital \u201cD\u201d. Someone flouncing around, holding their mechanical pencil up at straight edges, waxing lyrical about typefaces and sipping on a flat white (with soya milk, obviously) before casually birthing fully formed visual perfection into the world.<\/p>\n<p>This, not unlike the notion of the \u2018genius\u2019 programmer, is a myth. If you\u2019re new to design but trying your hand, I\u2019d suggest you don\u2019t get hung up on the first idea that piques your excitement. It\u2019s so cheap to try variations so embrace that possibility. None of the things I like about the design of In\/Out were there in the first designs.<\/p>\n<p>I believe it was the novelist, Michael Crichton, who coined the maxim, \u201cBooks are not written \u2014 they\u2019re rewritten\u201d. Accept that every creative process is essentially the same. Be aware that trusting the process lessens the anxiety and practice will refine your aesthetic understanding and judgment.<\/p>\n<h3>You Are The Other Dev On Your Project<\/h3>\n<p>I\u2019m not sure if this is particular to projects that only get worked on sporadically but I made the following foolhardy assumption:<\/p>\n<blockquote><p>\u201cI don\u2019t need to document any of this because it\u2019s just me, and obviously I will understand it because I wrote it.\u201d<\/p><\/blockquote>\n<p>Nothing could be further from the truth!<\/p>\n<p>There were evenings when, for the 30 minutes I had to work on the project, I did nothing more than try to understand a function I had written six months ago. The main reasons code re-orientation took so long was a lack of quality comments and poorly named variables and function arguments.<\/p>\n<p>I\u2019m very diligent in commenting code in my day job, always conscientious that someone else might need to make sense of what I\u2019m writing. However, in this instance, I was that someone else. Do you really think you will remember how the block of code works you wrote in six months time? You won\u2019t. Trust me on this, take some time out and comment that thing up!<\/p>\n<p>I\u2019ve since read a blog post entitled, <a href=\"https:\/\/jameshfisher.com\/2014\/05\/11\/your-syntax-highlighter-is-wrong\/\">Your syntax highlighter is wrong<\/a> on the subject of the importance of comments. The basic premise being that syntax highlighters shouldn\u2019t fade out the comments, they should be the most important thing. I\u2019m inclined to agree and if I don\u2019t find a code editor theme soon that scratches that itch I may have to adapt one to that end myself!<\/p>\n<h3>Debugging<\/h3>\n<p>When you hit bugs and you have written all the code, it\u2019s not unfair to suggest the error is likely originating between the keyboard and chair. However, before assuming that, I would suggest you test even your most basic assumptions. For example, I remember taking in excess of two hours to fix a problem I had assumed was due to my code; in iOS I just couldn\u2019t get my input box to accept text entry. I don\u2019t remember why it hadn\u2019t stopped me before but I do remember my frustration with the issue.<\/p>\n<p>Turns out it was due to a, still yet to be fixed, bug in Safari. Turns out that in Safari if you have:<\/p>\n<pre><code>* {\n  user-select: none;\n}\n<\/code><\/pre>\n<p>In your style sheet, input boxes won\u2019t take any input. You can work around this with:<\/p>\n<pre><code>* {\n  user-select: none;\n}\n\ninput[type] {\n  user-select: text;\n}\n<\/code><\/pre>\n<p>Which is the approach I take in my \u201c<a href=\"https:\/\/github.com\/benfrain\/app-reset\">App Reset<\/a>\u201d CSS reset. However, the really frustrating part of this was I had learned this already and subsequently forgotten it. When I finally got around to checking the WebKit bug tracking whilst troubleshooting the issue, I found I had written <a href=\"https:\/\/bugs.webkit.org\/show_bug.cgi?id=82692\">a workaround in the bug report thread more<\/a> than a year ago complete with reduction!<\/p>\n<h3>Want To Build With Data? Learn JavaScript Array Methods<\/h3>\n<p>Perhaps the single biggest advance my JavaScript skills took by undergoing this app-building exercise was getting familiar with JavaScript Array methods. I now use them daily for all my iteration and data manipulation needs. I cannot emphasize enough how useful methods like <code>map()<\/code>, <code>filter()<\/code>, <code>every()<\/code>, <code>findIndex()<\/code>, <code>find()<\/code> and <code>reduce()<\/code> are. You can solve virtually any data problem with them. If you don\u2019t already have them in your arsenal, bookmark <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array\">https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array<\/a> now and dig in as soon as you are able. My own run-down of my <a href=\"https:\/\/benfrain.com\/understanding-native-javascript-array-methods\/\">favored array methods<\/a> is documented here.<\/p>\n<p>ES6 has introduced other time savers for manipulating arrays, such as <code>Set<\/code>, <code>Rest<\/code> and <code>Spread<\/code>. Indulge me while I share one example; there used to be a bunch of faff if you wanted to remove duplicates from even a simple flat array. Not anymore.<\/p>\n<p>Consider this simple example of an Array with the duplicate entry, \u201cMr Pink\u201d:<\/p>\n<pre><code>let myArray = [\n  \"Mr Orange\",\n  \"Mr Pink\",\n  \"Mr Brown\",\n  \"Mr White\",\n  \"Mr Blue\",\n  \"Mr Pink\"\n];\n<\/code><\/pre>\n<p>To get rid of the duplicates with ES6 JavaScript you can now just do:<\/p>\n<div>\n<pre><code>let deDuped = [...new Set(myArray)]; \/\/ deDuped logs [\"Mr Orange\", \"Mr Pink\", \"Mr Brown\", \"Mr White\", \"Mr Blue\"]\n<\/code><\/pre>\n<\/div>\n<p>Something that used to require hand-rolling a solution or reaching for a library is now baked into the language. Admittedly, on such as short Array that may not sound like such a big deal but imagine how much time that saves when looking at arrays with hundreds of entries and duplicates.<\/p>\n<div><\/div>\n<h3>Maintenance And Security<\/h3>\n<p>Anything you build that makes any use of NPM, even if just for build tools, carries the possibility of being vulnerable to security issues. GitHub does a good job of keeping you aware of potential problems but there is still some burden of maintenance.<\/p>\n<p>For something that is a mere side-project, this can be a bit of a pain in the months and years that follow active development.<\/p>\n<p>The reality is that every time you update dependencies to fix a security issue, you introduce the possibility of breaking your build.<\/p>\n<p>For months, my <code>package.json<\/code> looked like this:<\/p>\n<div>\n<pre><code>{\n  \"dependencies\": {\n    \"gulp\": \"^3.9.1\",\n    \"postcss\": \"^6.0.22\",\n    \"postcss-assets\": \"^5.0.0\"\n  },\n  \"name\": \"In Out\",\n  \"version\": \"1.0.0\",\n  \"description\": \"simple utility to see who\u2019s in and who\u2019s out\",\n  \"main\": \"index.js\",\n  \"author\": \"Ben Frain\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"autoprefixer\": \"^8.5.1\",\n    \"browser-sync\": \"^2.24.6\",\n    \"cssnano\": \"^4.0.4\",\n    \"del\": \"^3.0.0\",\n    \"gulp-htmlmin\": \"^4.0.0\",\n    \"gulp-postcss\": \"^7.0.1\",\n    \"gulp-sourcemaps\": \"^2.6.4\",\n    \"gulp-typescript\": \"^4.0.2\",\n    \"gulp-uglify\": \"^3.0.1\",\n    \"postcss-color-function\": \"^4.0.1\",\n    \"postcss-import\": \"^11.1.0\",\n    \"postcss-mixins\": \"^6.2.0\",\n    \"postcss-nested\": \"^3.0.0\",\n    \"postcss-simple-vars\": \"^4.1.0\",\n    \"typescript\": \"^2.8.3\"\n  }\n}\n<\/code><\/pre>\n<\/div>\n<p>And by June 2019, I was getting these warnings from GitHub:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fefb13d9-fef4-4e1d-a4f7-83f4f93b2fca\/pwa-framework-security-alerts.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-security-alerts.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fefb13d9-fef4-4e1d-a4f7-83f4f93b2fca\/pwa-framework-security-alerts.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fefb13d9-fef4-4e1d-a4f7-83f4f93b2fca\/pwa-framework-security-alerts.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fefb13d9-fef4-4e1d-a4f7-83f4f93b2fca\/pwa-framework-security-alerts.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fefb13d9-fef4-4e1d-a4f7-83f4f93b2fca\/pwa-framework-security-alerts.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-security-alerts.png?w=900\" sizes=\"100vw\" alt=\"GitHub interface highlighting security issues with build tool dependencies\"><\/a><figcaption>\n      Keeping dependencies listed on GitHub means infrequent security warnings. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fefb13d9-fef4-4e1d-a4f7-83f4f93b2fca\/pwa-framework-security-alerts.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>None were related to plugins I was using directly, they were all sub-dependencies of the build tools I had used. Such is the double-edged sword of JavaScript packages. In terms of the app itself, there was no problem with In\/Out; that wasn\u2019t using any of the project dependencies. But as the code was on GitHub, I felt duty-bound to try and fix things up.<\/p>\n<p>It\u2019s possible to update packages manually, with a few choice changes to the package.json. However, both Yarn and NPM have their own update commands. I opted to run <code>yarn upgrade-interactive<\/code> which gives you a simple means to update things from the terminal.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/386e6a2c-af31-4e70-bc2e-ba4a7580b08b\/pwa-framework-yarn-upgrade-interative.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-yarn-upgrade-interative.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/386e6a2c-af31-4e70-bc2e-ba4a7580b08b\/pwa-framework-yarn-upgrade-interative.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/386e6a2c-af31-4e70-bc2e-ba4a7580b08b\/pwa-framework-yarn-upgrade-interative.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/386e6a2c-af31-4e70-bc2e-ba4a7580b08b\/pwa-framework-yarn-upgrade-interative.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/386e6a2c-af31-4e70-bc2e-ba4a7580b08b\/pwa-framework-yarn-upgrade-interative.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-yarn-upgrade-interative.png?w=900\" sizes=\"100vw\" alt=\"The CLI interface for upgrading packages with Yarn\"><\/a><figcaption>\n      Yarn makes upgrading project dependencies a little more predicatble. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/386e6a2c-af31-4e70-bc2e-ba4a7580b08b\/pwa-framework-yarn-upgrade-interative.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Seems easy enough, there\u2019s even a little colored key to tell you which updates are most important.<\/p>\n<p>You can add the <code>--latest<\/code> flag to update to the very latest major version of the dependencies, rather than just the latest patched version. In for a penny\u2026<\/p>\n<p>Trouble is, things move fast in the JavaScript package world, so updating a few packages to the latest version and then attempting a build resulted in this:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c47bb2c3-0596-4796-9eb5-8c5fe3371cc7\/pwa-framework-gulp-error.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-gulp-error.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c47bb2c3-0596-4796-9eb5-8c5fe3371cc7\/pwa-framework-gulp-error.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c47bb2c3-0596-4796-9eb5-8c5fe3371cc7\/pwa-framework-gulp-error.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c47bb2c3-0596-4796-9eb5-8c5fe3371cc7\/pwa-framework-gulp-error.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c47bb2c3-0596-4796-9eb5-8c5fe3371cc7\/pwa-framework-gulp-error.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-gulp-error.png?w=900\" sizes=\"100vw\" alt=\"Gulp build error\"><\/a><figcaption>\n      Gulp build error (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c47bb2c3-0596-4796-9eb5-8c5fe3371cc7\/pwa-framework-gulp-error.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>As such, I rolled back my <code>package.json<\/code> file and tried again this time without the <code>--latest<\/code> flag. That solved my security issues. Not the most fun I\u2019ve had on a Monday evening though I\u2019ll be honest.<\/p>\n<p>That touches on an important part of any side project. Being realistic with your expectations.<\/p>\n<h3>Side Projects<\/h3>\n<p>I don\u2019t know if you are the same but I\u2019ve found that a giddy optimism and excitement makes me start projects and if anything does, embarrassment and guilt makes me finish them.<\/p>\n<p>It would be a lie to say the experience of making this tiny application in my spare time was fun-filled. There were occasions I wish I\u2019d never opened my mouth about it to anyone. But now it is done I am 100% convinced it was worth the time invested.<\/p>\n<p>That said, it\u2019s possible to mitigate frustration with such a side project by being realistic about how long it will take to understand and solve the problems you face. Only have 30 mins a night, a few nights a week? You can still complete a side project; just don\u2019t be disgruntled if your pace feels glacial. If things can\u2019t enjoy your full attention be prepared for a slower and steadier pace than you are perhaps used to. That\u2019s true, whether it\u2019s coding, completing a course, learning to juggle or writing a series of articles of why it took so long to write a small web application!<\/p>\n<h5>Simple Goal Setting<\/h5>\n<p>You don\u2019t need a fancy process for goal setting. But it might help to break things down into small\/short tasks. Things as simple as \u2018write CSS for drop-down menu\u2019 are perfectly achievable in a limited space of time. Whereas \u2018research and implement a design pattern for state management\u2019 is probably not. Break things down. Then, just like Lego, the tiny pieces go together.<\/p>\n<p>Thinking about this process as chipping away at the larger problem, I\u2019m reminded of the famous Bill Gates quote:<\/p>\n<blockquote><p>\u201cMost people overestimate what they can do in one year and underestimate what they can do in ten years.\u201d<\/p><\/blockquote>\n<p>This from a man that\u2019s <a href=\"https:\/\/www.gatesfoundation.org\/What-We-Do\/Global-Development\/Polio\">helping to eradicate Polio<\/a>. Bill knows his stuff. Listen to Bill y\u2019all.<\/p>\n<h3>Shipping Something Is Better Than Shipping Nothing<\/h3>\n<p>Before \u2018shipping\u2019 this web application, I reviewed the code and was thoroughly disheartened.<\/p>\n<p>Although I had set out on this journey from a point of complete naivety and inexperience, I had made some decent choices when it came to how I might architect (if you\u2019ll forgive so grand a term) the code. I\u2019d researched and implemented a design pattern and enjoyed everything that pattern had to offer. Sadly, as I got more desperate to conclude the project, I failed to maintain discipline. The code as it stands is a real hodge-bodge of approaches and rife with inefficiencies.<\/p>\n<p>In the months since I\u2019ve come to realize that those shortcomings don\u2019t really matter. Not really.<\/p>\n<p>I\u2019m a fan of this quote from Helmuth von Moltke.<\/p>\n<blockquote><p>\u201cNo plan of operations extends with any certainty beyond the first contact with the main hostile force.\u201d<\/p><\/blockquote>\n<p>That\u2019s been paraphrased as:<\/p>\n<blockquote><p>\u201cNo plan survives first contact with the enemy\u201d.<\/p><\/blockquote>\n<p>Perhaps we can boil it down further and simply go with \u201cshit happens\u201d?<\/p>\n<p>I can surmise my coming to terms with what shipped via the following analogy.<\/p>\n<p>If a friend announced they were going to try and run their first marathon, them getting over the finish line would be all that mattered \u2014 I wouldn\u2019t be berating them on their finishing time.<\/p>\n<p>I didn\u2019t set out to write the <strong>best<\/strong> web application. The remit I set myself was simply to design and make one.<\/p>\n<p>More specifically, from a development perspective, I wanted to learn the fundamentals of how a web application was constructed. From a design point of view, I wanted to try and work through some (albeit simple) design problems for myself. Making this little application met those challenges and then some. The JavaScript for the entire application was just 5KB (gzipped). A small file size I would struggle to get to with any framework. Except maybe <a href=\"https:\/\/svelte.dev\/\">Svelte<\/a>.<\/p>\n<p>If you are setting yourself a challenge of this nature, and expect at some point to \u2018ship\u2019 something, write down at the outset why you are doing it. Keep those reasons at the forefront of your mind and be guided by them. Everything is ultimately some sort of compromise. Don\u2019t let lofty ideals paralyze you from finishing what you set out to do.<\/p>\n<h3>Summary<\/h3>\n<p>Overall, as it comes up to a year since I have worked on In\/Out, my feelings fall broadly into three areas: things I regretted, things I would like to improve\/fix and future possibilities.<\/p>\n<h4>Things I Regretted<\/h4>\n<p>As already alluded to, I was disappointed I hadn\u2019t stuck to what I considered a more elegant method of changing state for the application and rendering it to the DOM. The observer pattern, as discussed in the second part of this series, which solved so many problems in a predictable manner was ultimately cast aside as \u2018shipping\u2019 the project became a priority.<\/p>\n<p>I was embarrassed by my code at first but in the following months, I have grown more philosophical. If I hadn\u2019t used more pedestrian techniques later on, there is a very real possibility the project would never have concluded. Getting something out into the world that needs improving still feels better than it never being birthed into the world at all.<\/p>\n<h4>Improving In\/Out<\/h4>\n<p>Beyond choosing semantic markup, I\u2019d made no affordances for accessibility. When I built In\/Out I was confident with standard web page accessibility but not sufficiently knowledgeable to tackle an application. I\u2019ve done far more work\/research in that area now, so I\u2019d enjoy taking the time to do a decent job of making this application more accessible.<\/p>\n<p>The implementation of the revised design of \u2018Add Person\u2019 functionality was rushed. It\u2019s not a disaster, just a bit rougher than I would like. It would be nice to make that slicker.<\/p>\n<p>I also made no consideration for larger screens. It would be interesting to consider the design challenges of making it work at larger sizes, beyond simply making it a tube of content.<\/p>\n<h4>Possibilities<\/h4>\n<p>Using localStorage worked for my simplistic needs but it would be nice to have a \u2018proper\u2019 data store so it wasn\u2019t necessary to worry about backing up the data. Adding log-in capability would also open up the possibility of sharing the game organization with another individual. Or maybe every player could just mark whether they were playing themselves? It\u2019s amazing how many avenues to explore you can envisage from such simple and humble beginnings.<\/p>\n<p>SwiftUI for iOS app development is also intriguing. For someone who has only ever worked with web languages, at first glance, SwiftUI looks like something I\u2019m now emboldened to try. I\u2019d likely try rebuilding In\/Out with SwiftUI \u2014 just to have something specific to build and compare the development experience and results.<\/p>\n<p>And so, it\u2019s time to wrap things up and give you the TL;DR version of all this.<\/p>\n<p>If you want to learn how something works on the web, I\u2019d suggest skipping the abstractions. Ditch the frameworks, whether that\u2019s CSS or JavaScript until you really understand what they are dong for you.<\/p>\n<p>Design is iterative, embrace that process.<\/p>\n<p>Solve problems in the lowest fidelity medium at your disposal. Don\u2019t go to code if you can test the idea in Sketch. Don\u2019t draw it in Sketch if you can use pen and paper. Write out logic first. Then write it in code.<\/p>\n<p>Be realistic but never despondent. Developing a habit of chipping away at something for as little as 30 minutes a day can get results. That fact is true whatever form your quest takes.<\/p>\n<div>\n  <img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/logo-red-23.png?w=900\" alt=\"Smashing Editorial\"><span>(dm, il, ra)<\/span>\n<\/div>\n<\/article>\n<p class=\"wpematico_credit\"><small>Powered by <a href=\"http:\/\/www.wpematico.com\" target=\"_blank\">WPeMatico<\/a><\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Designing And Building A Progressive Web Application Without A Framework (Part 3) Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00 Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be&#8230;<a class=\"moretag\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/\"> Read the full article&#8230;<\/a><\/p>\n","protected":false},"author":4,"featured_media":68692,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[371],"tags":[],"class_list":["post-68691","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-user-experience"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Guest Contribution\"\/>\n\t<meta name=\"keywords\" content=\"user experience\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies\" \/>\n\t\t<meta property=\"og:description\" content=\"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-07-31T11:19:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-07-31T11:19:20+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#article\",\"name\":\"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies\",\"headline\":\"Designing And Building A Progressive Web Application Without A Framework (Part 3)\",\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/07\\\/pwa-framework-lighthouse2.png?fit=400%2C302&ssl=1\",\"width\":400,\"height\":302},\"datePublished\":\"2019-07-31T04:19:20-07:00\",\"dateModified\":\"2019-07-31T04:19:20-07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#webpage\"},\"articleSection\":\"User Experience\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"position\":2,\"name\":\"User Experience\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#listItem\",\"name\":\"Designing And Building A Progressive Web Application Without A Framework (Part 3)\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#listItem\",\"position\":3,\"name\":\"Designing And Building A Progressive Web Application Without A Framework (Part 3)\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/\",\"name\":\"Guest Contribution\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Guest Contribution\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#webpage\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/\",\"name\":\"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies\",\"description\":\"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/07\\\/pwa-framework-lighthouse2.png?fit=400%2C302&ssl=1\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#mainImage\",\"width\":400,\"height\":302},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\\\/#mainImage\"},\"datePublished\":\"2019-07-31T04:19:20-07:00\",\"dateModified\":\"2019-07-31T04:19:20-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies","description":"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in","canonical_url":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/","robots":"max-image-preview:large","keywords":"user experience","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#article","name":"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies","headline":"Designing And Building A Progressive Web Application Without A Framework (Part 3)","author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse2.png?fit=400%2C302&ssl=1","width":400,"height":302},"datePublished":"2019-07-31T04:19:20-07:00","dateModified":"2019-07-31T04:19:20-07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#webpage"},"isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#webpage"},"articleSection":"User Experience"},{"@type":"BreadcrumbList","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.taterboy.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","position":2,"name":"User Experience","item":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#listItem","name":"Designing And Building A Progressive Web Application Without A Framework (Part 3)"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#listItem","position":3,"name":"Designing And Building A Progressive Web Application Without A Framework (Part 3)","previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}}]},{"@type":"Organization","@id":"https:\/\/www.taterboy.com\/blog\/#organization","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","url":"https:\/\/www.taterboy.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author","url":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/","name":"Guest Contribution","image":{"@type":"ImageObject","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g","width":96,"height":96,"caption":"Guest Contribution"}},{"@type":"WebPage","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#webpage","url":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/","name":"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies","description":"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#breadcrumblist"},"author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"creator":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse2.png?fit=400%2C302&ssl=1","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#mainImage","width":400,"height":302},"primaryImageOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/#mainImage"},"datePublished":"2019-07-31T04:19:20-07:00","dateModified":"2019-07-31T04:19:20-07:00"},{"@type":"WebSite","@id":"https:\/\/www.taterboy.com\/blog\/#website","url":"https:\/\/www.taterboy.com\/blog\/","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","og:type":"article","og:title":"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies","og:description":"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in","og:url":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/","article:published_time":"2019-07-31T11:19:20+00:00","article:modified_time":"2019-07-31T11:19:20+00:00","twitter:card":"summary","twitter:title":"Designing And Building A Progressive Web Application Without A Framework (Part 3) | Design for Immersive Technologies","twitter:description":"Designing And Building A Progressive Web Application Without A Framework (Part 3)Designing And Building A Progressive Web Application Without A Framework (Part 3) Ben Frain 2019-07-30T14:00:00+02:002019-07-31T11:07:39+00:00Back in the first part of this series, we explained why this project came to be. Namely a desire to learn how a small web application could be made in"},"aioseo_meta_data":{"post_id":"68691","title":null,"description":null,"keywords":null,"keyphrases":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_custom_image_width":null,"og_custom_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"created":"2021-02-07 18:42:17","updated":"2026-09-01 18:01:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"twitter_image_url":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/\" title=\"User Experience\">User Experience<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tDesigning And Building A Progressive Web Application Without A Framework (Part 3)\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.taterboy.com\/blog"},{"label":"User Experience","link":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/"},{"label":"Designing And Building A Progressive Web Application Without A Framework (Part 3)","link":"https:\/\/www.taterboy.com\/blog\/2019\/07\/designing-and-building-a-progressive-web-application-without-a-framework-part-3\/"}],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8wzr5-hRV","jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/pwa-framework-lighthouse2.png?fit=400%2C302&ssl=1","_links":{"self":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/68691","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/comments?post=68691"}],"version-history":[{"count":0,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/68691\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media\/68692"}],"wp:attachment":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media?parent=68691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/categories?post=68691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/tags?post=68691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}