{"id":2063,"date":"2019-07-20T21:07:07","date_gmt":"2019-07-20T21:07:07","guid":{"rendered":"https:\/\/www.codeastar.com\/?p=2063"},"modified":"2019-07-20T21:07:22","modified_gmt":"2019-07-20T21:07:22","slug":"pwa-create-easy-progressive-web-app-with-react","status":"publish","type":"post","link":"https:\/\/www.codeastar.com\/pwa-create-easy-progressive-web-app-with-react\/","title":{"rendered":"PWA – Create Easy Progressive Web App with React"},"content":{"rendered":"\n
Nowadays, using smart mobile is a part of our daily life. People use mobile apps to do things they want to do, messaging, shopping, reading, learning, and the list goes on. In order to enter the mobile users market, companies need to spend time and effort to create an app then publish it on Google Play or Mac App Store. While websites can be built easier and reached by more audiences. What if… What if we combine the convenience of apps and the reach of webs? So we have — Progressive Web App (PWA). <\/p>\n\n\n\n\n\n\n\n
As we mentioned earlier, PWA is a type of mobile app which works like ordinary apps and reaches like ordinary webs. A PWA can be installed on our mobile with an app icon, just likes other apps in our phone. It is fast and accessible in offline mode. And since it can be installed directly by entering a web url, instead of using Play \/ App Store to search and download. It is easier for people to add the app to their phone.<\/p>\n\n\n\n
Ain’t it attractive? Yes! But what do we need to build a PWA? HTML, JavaScript and CSS. Wow, it sounds easy! Yes, then what are we waiting for? <\/p>\n\n\n\n
We used React to build a weather forecast frontend<\/a> in past. And we know how React can make the job done in an easy and component based way. So we decide to use React agto build our PWA. But before we move to step 1, there is a step 0. The reference links for PWA:<\/p>\n\n\n\n You can take a look on above links to find more details about PWA. Or you can go straightly with our steps to build a PWA. <\/p>\n\n\n\n Let’s use create-react-app <\/em>command to create our React template, pwa_funhouse<\/em>!<\/p>\n\n\n\n Then we start our pwa_funhouse <\/em>web app.<\/p>\n\n\n\n You may notice that I use yarn<\/a> instead of npm<\/a> to start the React app. As I find the Facebook created package manager, yarn, out performs npm in speed and stability (you can still use npm by the way).<\/p>\n\n\n\n After running the start command, it will pop out the pwa_funhouse <\/em>app on your default browser. <\/p>\n\n\n\n If your default browser is not Chrome, let’s open a Chrome browser and run our app on it. As we will use Lighthouse<\/a>, the audit tool on Chrome, to check our PWA readiness. <\/p>\n\n\n\n On your Chrome browser, open the “Developer tools<\/em>” option, select the “Audits<\/em>” tab. Then you will see the Lighthouse tool there.<\/p>\n\n\n\n Press the “Run audits<\/em>” at the bottom. It starts auditing our app, then displays the results. There are different kind of results, like “Accessibility” and “SEO”. But what we need to look at, is the “Progressive Web App” result. Once we click on it, it shows us many problematic issues:<\/p>\n\n\n\n Don’t worry, we are going to clear them on next step.<\/p>\n\n\n\n There are several issues found by Lighthouse, let’s clear those easy ones first. <\/p>\n\n\n\n From the above messages, we know there are missing icons for our app. You can download icon images from my source here<\/a> and put them in “public\/images\/icons<\/em>” folder. Then update the icons<\/em> part from the “public\/manifest.json<\/em>” file to:<\/p>\n\n\n\n Re-run the Lighthouse audits again. Yes, those icons related issues are gone. Now we go to handle other issues: <\/p>\n\n\n\n Let’ sum up above issues: we don’t use a service worker to handle app in offline mode. Then we have another question. <\/p>\n\n\n\n What is a service worker? <\/p>\n\n\n\n A service worker<\/a> is a script that runs in background. It handles page caching, background sync and push notification in PWA. Well, doesn’t it sound complicated? Maybe, but the good thing is, in React, the service worker part is already prepared for us. We edit the “src\/index.js<\/em>” file, then change the line of serviceWorker.unregister();<\/em> to <\/p>\n\n\n\n Since service worker works in a production environment not development environment, we run following command to make a production build: <\/p>\n\n\n\n Once the build is ready, we can start a server to run the build. If you have installed serve, you can ignore the first command. <\/p>\n\n\n\n Open the Chrome browser and we run the Lighthouse audits again. <\/p>\n\n\n\n Poof! The service worker is on an we finish all major issues here!<\/p>\n\n\n\n Since our app is now a PWA, it caches the current page when the network is down. Then it brings out an issue for us. How do we know our app is online, when both online and offline pages are the same? React-detect-offline<\/em> package to rescue! Firstly, let’s install the react-detect-offline<\/em> using yarn.<\/p>\n\n\n\n It is a package that allows users to add <Online> and<Offline> tags in React. So the app can run certain behaviors when it is online or offline. In our “src\/App.js<\/em>” file, let import the package:<\/p>\n\n\n\n And add following code insider <header className=”App-header”> :<\/p>\n\n\n\n Now we build the app again and open it on Chrome browser. You may see there is nothing changed at all. Don’t panic, it is a caching behavior of the service worker. I would suggest reading “The Service Worker Lifecycle<\/a>” article for more details. At this moment, let’s clear up the cache ourselves, by using “Developer tools” > “Application” > “Clear storage”, then press the “Clear site data” button.<\/p>\n\n\n\n After that, when we refresh the app, the message of “You are online” is now showed. <\/p>\n\n\n\n For the offline message, of cause we can cut the network to make it display. But we have an easier way to test it. Let’s use the “Developer tools” > “Application” once again. This time, we click “Service Workers” on the left then “Offline” on the right.<\/p>\n\n\n\n The app then shows “You are offline” message. We can untick the “Offline” checkbox to make it online again.<\/p>\n\n\n\n We make a PWA with online\/offline indicator, but then… now what? A PWA with React logo spinning around is so meaningless. In CodeAStar here, we always make easy and useful<\/a> things :]] . Bitcoin is going up again (as of July 2019), let’s build a easy BTC price tracker then.<\/p>\n\n\n\n The packages we need:<\/p>\n\n\n\n We have used the “axios” package in our weather forecast React project before. This time, we use this package to get the BTC price info from Blockchain.com<\/a>. And we use “moment” package to handle the Javascript date object. We create 1 folder “Btc<\/em>” and 2 files, “Btc.css<\/em>” and “Btc.js<\/em>“, under “src<\/em>” folder.<\/p>\n\n\n\n Once again, you can go to my github page<\/a> to download the source of those files. Inside the “Btc.js<\/em>” file, we use setInterval() <\/em>method to get BTC info every 1 second.<\/p>\n\n\n\n Then on the “src\/App.js<\/em>“, we import Btc component to our app. <\/p>\n\n\n\n And render the Btc component.<\/p>\n\n\n\n \n Real Time BTC tracker from blockchain.info\n <\/p> \n After changing the css and logo of our app (copy and paste from the source), we can re-build and re-run it.<\/p>\n\n\n\n And now we have a working BTC tracker PWA.<\/p>\n\n\n\n Things look good so far. Isn’t it? :]] But what we have done is all on our development environment. The next thing we do is putting all our work on a web server, so we can make a complete PWA. <\/p>\n\n\n\nStep 1: Create a React web app<\/h3>\n\n\n\n
$npx create-react-app pwa_funhouse<\/code><\/pre>\n\n\n\n
$cd pwa_funhouse\n$yarn start<\/code><\/pre>\n\n\n\n
<\/figure><\/div>\n\n\n\n
Step 2: Check rather our app is PWA ready<\/h3>\n\n\n\n
<\/figure>\n\n\n\n
<\/figure><\/div>\n\n\n\n
Step 3: Clear the PWA issues<\/h3>\n\n\n\n
\"icons\": [{\n \"src\": \".\/images\/icons\/icon-128x128.png\",\n \"sizes\": \"128x128\",\n \"type\": \"image\/png\"\n }, {\n \"src\": \".\/images\/icons\/icon-144x144.png\",\n \"sizes\": \"144x144\",\n \"type\": \"image\/png\"\n }, {\n \"src\": \".\/images\/icons\/icon-152x152.png\",\n \"sizes\": \"152x152\",\n \"type\": \"image\/png\"\n }, {\n \"src\": \".\/images\/icons\/icon-192x192.png\",\n \"sizes\": \"192x192\",\n \"type\": \"image\/png\"\n }, {\n \"src\": \".\/images\/icons\/icon-256x256.png\",\n \"sizes\": \"256x256\",\n \"type\": \"image\/png\"\n }, {\n \"src\": \".\/images\/icons\/icon-512x512.png\",\n \"sizes\": \"512x512\",\n \"type\": \"image\/png\"\n }],<\/code><\/pre>\n\n\n\n
serviceWorker.register();<\/code><\/pre>\n\n\n\n
$yarn build<\/code><\/pre>\n\n\n\n
$yarn global add serve\n$serve -s build<\/code><\/pre>\n\n\n\n
<\/figure><\/div>\n\n\n\n
Step 4: Check PWA network status<\/h3>\n\n\n\n
$yarn add react-detect-offline<\/code><\/pre>\n\n\n\n
import { Offline, Online } from \"react-detect-offline\";<\/pre>\n\n\n\n
<\/figure><\/div>\n\n\n\n
<\/figure><\/div>\n\n\n\n
<\/figure><\/div>\n\n\n\n
Step 5: Build a BTC tracker<\/h3>\n\n\n\n
$yarn add axios\n$yarn add moment<\/code><\/pre>\n\n\n\n
\/src\n \/Btc\n |- Btc.css\n |- Btc.js<\/code><\/pre>\n\n\n\n
componentDidMount () \n {\n this.timerID = setInterval(\n () => this.getBtcInfo(),\n 1000\n );\n }\n \n getBtcInfo()\n { \n axios.get(\"https:\/\/blockchain.info\/ticker\")\n .then(response => {\n let current_price = response.data.USD.last;\n this.setState({ latest_price: current_price });\n this.setState({ btcusd: current_price });\n \n if (this.last_price)\n {\n let change = parseFloat(current_price) - parseFloat(this.last_price);\n if (change !== 0) \n {\n this.setState({ price_change: change.toFixed(2) });\n let sign = (change > 0) ? '+' : '';\n this.setState({ price_sign: sign });\n } \n }\n\n this.last_price = current_price;\n let curr_date = moment().local().format('YYYY-MM-DD HH:mm:ss');\n this.setState({ last_updated: curr_date }); \n })\n .catch(error => {\n console.log(error)\n this.setState({ btcusd: this.state.btcusd });\n }) \n }\n<\/pre>\n\n\n\n
import Btc from '.\/Btc\/Btc'<\/pre>\n\n\n\n
<\/figure><\/div>\n\n\n\n
Step 6: Put it on web server for FREE<\/h3>\n\n\n\n