PWA入门:手把手教你制作一个PWA应用
摘要: PWA圖文教程
- 原文:PWA入門:手把手教你制作一個PWA應用
- 作者:MudOnTire
Fundebug經(jīng)授權轉載,版權歸原作者所有。
簡介
Web前端的同學是否想過學習app開發(fā),以彌補自己移動端能力的不足?但在面對一眾的選擇時很多同學略感迷茫,是學習ios還是android開發(fā)?是學習原生開發(fā)、混合開發(fā)(比如:Ionic),還是使用react native或者flutter這樣的跨平臺框架?而app開發(fā)的學習周期長、學習成本高也讓一部分人望而卻步。得益于前端技術的飛速發(fā)展、瀏覽器性能的不斷提高,使用網(wǎng)頁技術開發(fā)出接近原生體驗的應用得以變?yōu)楝F(xiàn)實,PWA就在這樣的背景下應運而生。可以用自己熟悉的HTML、CSS、Javascript開發(fā)出媲美原生app的網(wǎng)站,不僅擁有接近原生app的流暢程度,并且具備一些原生app才有的特性,比如:a. 可以在主屏上安裝應用圖標,b. 離線狀態(tài)下訪問,c. 獲取消息通知,等等。。PWA的出現(xiàn)讓大家看到了希望!
對比原生應用
那PWA和原生應用相比到底有何競爭力呢?我們分別看一下原生應用和PWA的特點:
原生應用:
- 使用原生SDK和開發(fā)工具開發(fā)
- 需要考慮跨平臺,不同系統(tǒng)往往需要獨立開發(fā)
- 需要發(fā)布到應用商店才能下載使用
- 可以安裝到手機主屏,生成應用圖標
- 直接運行于操作系統(tǒng)上,訪問系統(tǒng)資源方便
- 可以離線使用
- 可以獲取消息通知
PWA應用:
- 使用HTML,CSS,JS開發(fā)
- 無需考慮跨平臺,只需要考慮瀏覽器兼容性
- 通過url訪問,無需發(fā)布到應用商店
- 可以安裝到手機主屏,生成應用圖標
- 運行于瀏覽器中,可訪問系統(tǒng)資源
- 可以離線使用
- 可以獲取消息通知
可以發(fā)現(xiàn)PWA具備了原生應用的主要能力,但是開發(fā)流程卻比原生應用更加簡潔:a. html/css/js的群眾基礎更好,開發(fā)效率更高;b. 省去了為不同系統(tǒng)開發(fā)獨立版本的大量成本;c. 省去了上架到應用市場的繁瑣流程;d. 無需前往應用商店下載,用戶使用起來也更加方便。但是值得注意的是,PWA還是相對比較新的技術,實現(xiàn)規(guī)范還有很多調整的空間,部分瀏覽器對PWA的支持也還不完善,但是PWA是一個趨勢,所以現(xiàn)在學習正合適!
本文將通過一個簡單的列子(一個簡單的郵編查詢app)向大家展示PWA的開發(fā)流程,項目參考:Traversy Media - Build a PWA With Vue & Ionic4。完成后的效果是 這樣的 。
創(chuàng)建項目
項目使用Vue + Ionic的組合進行開發(fā)。本文主要關注PWA的搭建,因此vue、ionic等技術不做過多描述。使用VSCode的同學,建議安裝Vetur插件增加開發(fā)效率。
1. 首先全局安裝 @vue/cli:
npm install -g @vue/cli2. 初始化vue項目:
vue create vue-ionic-pwa3. 因為ionic的路由依賴于vue-router,所以接下來安裝 vue-router:
vue add router4. 安裝 @ionic/vue
npm install @ionic/vue5. 在 src/main.js 中添加對ionic的引用:
import Ionic from '@ionic/vue' import '@ionic/core/css/ionic.bundle.css'Vue.use(Ionic)6. 在 src/router.js 中使用 IonicVueRouter 替換默認的vue router:
import Vue from 'vue' import { IonicVueRouter } from '@ionic/vue'; import Home from './views/Home.vue'Vue.use(IonicVueRouter)export default new IonicVueRouter({mode: 'history',base: process.env.BASE_URL,routes: [{path: '/',name: 'home',component: Home}] })7. 將 src/App.vue 內容修改為:
<template><div id="app"><ion-app><ion-vue-router/></ion-app></div> </template>8. 將 src/views/Home.vue 內容修改為:
<template><div class="ion-page"><ion-header><ion-toolbar><ion-title>ZipInfo</ion-title></ion-toolbar></ion-header><ion-content class="ion-padding">My App</ion-content></div> </template><script> export default {name: 'home',components: {} } </script>最后,我們運行yarn serve看下效果:
App功能實現(xiàn)
App主要有三部分組成:1. 搜索組件,用于輸入郵編并查詢,2. 展示組件,用于展示查詢到的郵編信息,3. 清除按鈕,用于清除查詢到的郵編信息
1. 搜索組件
我們在 src/components 下面新建 ZipSearch.vue 文件作為郵編搜索組件,主要邏輯為當用戶輸入一串字符,按下搜索按鈕,如果輸入合法則觸發(fā)get-zip事件,如果不合法則給出提示。
ZipSearch.vue
<template><ion-grid><form @submit="onSubmit"><ion-col><ion-item><ion-label>ZipCode:</ion-label><ion-input:value="zip"@input="zip = $event.target.value"name="zip"placeholder="Enter US ZipCode"/></ion-item></ion-col><ion-col><ion-button type="submit" color="primary" expand="block">Find</ion-button></ion-col></form></ion-grid> </template><script> export default {name: "ZipSearch",data() {return {zip: ""};},methods: {onSubmit(e) {e.preventDefault();const zipRegex = /(^\d{5}$)|(^\d{5}-\d{4}$)/;const isValid = zipRegex.test(this.zip);if (!isValid) {this.showAlert();} else {this.$emit("get-zip", this.zip);}this.zip = "";},showAlert() {return this.$ionic.alertController.create({header: "Enter zipcode",message: "Please enter a valid US ZipCode",buttons: ["OK"]}).then(a => a.present());}} }; </script>在 src/views/Home.vue 中引入 ZipSearch 組件,當Home接收到get-zip事件時調用 https://www.zippopotam.us 的接口,獲取郵編對應的信息:
...<ion-content class="ion-padding"><ZipSearch v-on:get-zip="getZipInfo"/></ion-content> ...<script> import ZipSearch from "../components/ZipSearch";export default {name: "home",components: {ZipSearch},data() {return {info: null};},methods: {async getZipInfo(zip) {const res = await fetch(`https://api.zippopotam.us/us/${zip}`);if (res.status == 404) {this.showAlert();}this.info = await res.json();},showAlert() {return this.$ionic.alertController.create({header: "Not Valid",message: "Please enter a valid US ZipCode",buttons: ["OK"]}).then(a => a.present());}} }; </script>我們先看一下搜索組件的效果:
輸入郵編格式錯誤:
2. 信息展示和清除組件
獲取到郵編信息后我們需要一個展示郵編信息的組件和一個清除信息的按鈕,在 src/components 下面新建 ZipInfo.vue和ClearInfo.vue 。
ZipInfo.vue
<template><ion-card v-if="info"><ion-card-header><ion-card-subtitle>{{info['post code']}}</ion-card-subtitle><ion-card-title>{{info['places'][0]['place name']}}</ion-card-title></ion-card-header><ion-card-content><ion-list><ion-item><ion-label><strong>State:</strong>{{info['places'][0]['state']}} ({{info['places'][0]['state abbreviation']}})</ion-label></ion-item><ion-item><ion-label><strong>Latitude:</strong>{{info['places'][0]['latitude']}}</ion-label></ion-item><ion-item><ion-label><strong>Longitude:</strong>{{info['places'][0]['longitude']}}</ion-label></ion-item></ion-list></ion-card-content></ion-card> </template><script> export default {name: "ZipInfo",props: ["info"] }; </script>ClearInfo.vue
<template><ion-button color="light" expand="block" v-if="info" @click="$emit('clear-info')">Clear</ion-button> </template><script> export default {name: "ClearInfo",props: ["info"] }; </script>接著在Home中引入ZipInfo和ClearInfo組件:
src/views/Home.vue
...<ion-content class="ion-padding"><ZipSearch v-on:get-zip="getZipInfo"/><ZipInfo v-bind:info="info"/><ClearInfo v-bind:info="info" v-on:clear-info="clearInfo"/></ion-content> ...import ZipInfo from "../components/ZipInfo"; import ClearInfo from "../components/ClearInfo";export default {name: "home",components: {ZipSearch, ZipInfo},methods:{...clearInfo(){this.info = null;}} }到此,app的主體就完成了,效果如下:
實現(xiàn)PWA
我們使用現(xiàn)成的 @vue/pwa 插件來給我們的app增加PWA的能力。
安裝 @vue/pwa:
vue add @vue/pwa安裝完成后項目中增加了 public/manifest.json 和 registerServiceWorker.js兩個文件。其中 public/manifest.json 文件內容如下:
{"name": "vue-ionic-pwa","short_name": "vue-ionic-pwa","icons": [{"src": "./img/icons/android-chrome-192x192.png","sizes": "192x192","type": "image/png"},{"src": "./img/icons/android-chrome-512x512.png","sizes": "512x512","type": "image/png"}],"start_url": "./index.html","display": "standalone","background_color": "#000000","theme_color": "#4DBA87" }manifest.json中主要包含app的基本信息,比如名稱(name)、圖標(icons)、顯示方式(display)等等,是web app能被以類似原生的方式安裝、展示的必要配置。更多的配置項可參考 MDN Web App Manifest。
在Chrome瀏覽器控制臺中也可看到app的manifest配置:
registerServiceWorker.js用于注冊service worker。service worker通俗來講就是在瀏覽器后臺獨立于網(wǎng)頁運行的一段腳本,service worker可以完成一些特殊的功能,比如:消息推送、后臺同步、攔截和處理網(wǎng)絡請求、管理網(wǎng)絡緩存等。Service worker之于pwa的意義在于能夠為用戶提供離線體驗,即掉線狀態(tài)下用戶依舊能夠訪問網(wǎng)站并獲取已被緩存的數(shù)據(jù)。使用service worker需要HTTPS,并且考慮 瀏覽器兼容性。
registerServiceWorker.js
import { register } from 'register-service-worker'if (process.env.NODE_ENV === 'production') {register(`${process.env.BASE_URL}service-worker.js`, {ready () {console.log('App is being served from cache by a service worker.\n' +'For more details, visit https://goo.gl/AFskqB')},registered () {console.log('Service worker has been registered.')},cached () {console.log('Content has been cached for offline use.')},updatefound () {console.log('New content is downloading.')},updated () {console.log('New content is available; please refresh.')},offline () {console.log('No internet connection found. App is running in offline mode.')},error (error) {console.error('Error during service worker registration:', error)}}) }在Chrome瀏覽器控制臺中也可看到service worker的狀態(tài):
當然,只注冊service worker還不夠,我們還希望控制service worker的行為,通過在 vue.config.js 中增加相關的配置我們可以設置service worker文件的名稱、緩存邏輯等等。
vue.config.js
module.exports = {pwa: {workboxPluginMode: 'GenerateSW',workboxOptions: {navigateFallback: '/index.html', runtimeCaching: [{urlPattern: new RegExp('^https://api.zippopotam.us/us/'),handler: 'networkFirst',options: {networkTimeoutSeconds: 20,cacheName: 'api-cache',cacheableResponse: {statuses: [0, 200]}}}]}} }更多配置請參考:@vue/cli-plugin-pwa 和 workbox-webpack-plugin。由于@vue/cli-plugin-pwa生成的service worker只在生產(chǎn)環(huán)境生效,所以建議將項目build之后部署到生產(chǎn)環(huán)境測試。本文示例使用 github pages進行部署和展示。
到此,將普通web app轉成PWA的工作基本完成,我們部署到線上看下效果:
文件已被緩存用于離線訪問:
查詢一個郵編試試,可以發(fā)現(xiàn)請求被緩存了下來:
我們接著關掉網(wǎng)絡,再查詢剛剛的那個郵編,發(fā)現(xiàn)在網(wǎng)絡請求失敗之后立即切換用本地緩存的數(shù)據(jù):
好了,一個簡單的PWA就已經(jīng)制作完成了。當然PWA的功能遠不止本文所展示的,比如推送、安裝到手機,后續(xù)有機會再跟大家分享,謝謝?。
最后,推薦大家使用Fundebug,一款很好用的BUG監(jiān)控工具~
本文demo地址:https://github.com/MudOnTire/pwa-tutorial
關于Fundebug
Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監(jiān)控。 自從2016年雙十一正式上線,Fundebug累計處理了20億+錯誤事件,付費客戶有陽光保險、核桃編程、荔枝FM、掌門1對1、微脈、青團社等眾多品牌企業(yè)。歡迎大家免費試用!
總結
以上是生活随笔為你收集整理的PWA入门:手把手教你制作一个PWA应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数学建模专栏 | 第二篇 :MATLAB
- 下一篇: 声学计算机软件,《声学设计软件EASE及