摘要:另外,單頁應用因為數據前置到了前端,不利于搜索引擎的抓取。所以我們需要對自己的單頁應用進行一些優化。
前言
最近秋招之余空出時間來按自己的興趣動手做了一個項目,一個基于vue-cli3.0, vue,typescript的移動端pwa,現在趁熱打鐵,將這個項目從開發到部署整個過程記錄下來,并將從這個項目中學習到的東西分享出來,如果大家有什么意見或補充也可以在評論區提出。先介紹一下這個項目
項目介紹基于vue,typescript,pwa的一個移動端webapp,取名叫browseExp,主要功能是瀏覽學校心理學院部分實驗信息。(上圖是添加到桌面的一級入口)。這個項目已經部署到了服務器上,我們看一下項目最終在客戶端運行的樣子
可以看到我通過桌面上的一級入口,進入了我們的webapp,并且在斷網的條件下進行。這就是pwa的作用,下面開始分享這次的開發到部署的過程。
為什么要做這個項目呢?pwa 在國內已經火過一段時間了,但是自己還沒做過一款pwa應用。
vue-cli 3.0 增加了對pwa的支持
vue2.5后增加了對ts的支持
想搞事情!
開發過程這個項目的地址為: browseExp pwa,想要查看代碼的同學可以看一下。這個項目要注意的點主要是:
在vue中使用ts
簡單骨架屏的運用
首屏加載時間和seo的優化
pwa相關特性的實現
移動端的一些問題解決
如何部署項目
后面的內容也圍繞著這些點來展開。
vue中使用ts使用ts主要是因為ts給我們帶來了類型系統,可以讓我們寫出健壯的代碼,它的作用在大型項目中尤其突出,所以還是非常鼓勵大家去使用的,我們使用ts進行開發一般是編寫基于類的vue組件,所以可以使用官方維護的vue-class-component或者vue-property-decorator,vue-cli3.0也給我們提供了開箱即用的typescript支持,開發體驗還是相當友好的。一個vue組件demo:
import { Component, Vue, Prop } from "vue-property-decorator"; @Component export default class Name extends Vue { @Prop() private name!: string; private complete!: boolean; private data() { return { complete: false, }; } private myMethod() { // ... } private created() { // ... } }
另外,在vue-cli3.0提供的腳手架下,可以在shims-tsx.d.ts文件下添加全局接口或變量等,在shims-vue.d.ts定義第三方包的類型聲明。
骨架屏的簡單運用骨架屏(skeleton screen)已經不是什么新奇的概念,他的主要作用就是用來過渡頁面的空白狀態,提升用戶體驗,比如頁面跳轉等待,數據加載等待等,傳統的骨架平實現方案有 服務端渲染和預渲染等,而這個項目中引入骨架屏主要是想過渡數據加載時頁面的局部空白狀態,所以就直接采用編寫一個骨架屏組件SkeletonExp.vue的方式來過渡。
如果你對骨架屏有更大的需求,可以在網上搜到更多的教程,這里就不列舉了。
首屏加載速度和seo的優化單頁應用(single page web application,SPA)一個缺點就是首次加載需要加載較多的內容,所以首屏加載時間就會比較長。另外,單頁應用因為數據前置到了前端,不利于搜索引擎的抓取。所以我們需要對自己的單頁應用進行一些優化。這里我們使用了prerender-spa-plugin這個webpack插件,他的作用就是將我們指定的路由進行預渲染到html,進而解決首次加載白屏時間長問題,以及一定程度上解決seo問題。在vue-cli3.0中,我們的相關配置是被隱藏起來的,我們可以通過vue.config.js來將我們的配置合并到默認配置中。
// vue.config.js const path = require("path") const PrerenderSPAPlugin = require("prerender-spa-plugin") module.exports = { configureWebpack(config) { if (process.env.NODE_ENV !== "production") return; return { plugins: [ new PrerenderSPAPlugin({ // Required - The path to the webpack-outputted app to prerender. staticDir: path.join(__dirname, "dist"), // Required - Routes to render. routes: ["/"], }) ] } }, }
效果:
上圖是該app在網絡環境為slow 3G下首次打開時的效果,可以看到整個過程,先由谷歌頁面跳至browseExp,首先引入眼簾的是我們的預渲染頁面,它代替我網址跳轉后應用加載的白屏時間,(前面的小段白屏是頁面跳轉的白屏,不是應用加載的白屏)然后加載完畢后就會去請求我們的數據,這時候骨架屏就出現了,過渡這段頁面局部白屏的時間,最后為真實的頁面。
預渲染也有它的缺點:那就是預渲染的頁面內容可能與真實內容由一定出入,而且還無法交互。所以如果應用的內容具有很強的實時性和交互性的話,可以考慮采用骨架屏的方式來進行首屏加載的白屏過渡,但是這樣就無法優化seo了,所以按自己的實際場景來做選擇。
另外對于首屏加載速度還可以通過組件懶加載的方式,對組件進行懶加載,只有當需要默寫組件的時候才去加載他們,也可以減少首屏加載需要加載的文件大小,提高首屏加載速度,也有利于service worker對app shell進行顆粒度更小的緩存。結合Vue的異步組件和webpack的代碼分割功能,輕松實現路由組件的懶加載,例如
// router.js通過動態import來引入組件,其他 import Vue from "vue"; import Router from "vue-router"; //這里用home組件做例子 const Home = () => import("./views/Home/Home.vue"); Vue.use(Router); export default new Router({ routes: [ { path: "/", name: "Home", component: Home, ], });
這樣就可以對我們的路由組件進行懶加載了,你會發現我們的代碼會按組件為單位打包成了多個js文件。
將項目升級為 pwa在我們的項目基本成型之后,可以考慮將其升級為pwa了。關于pwa是什么,我相信大家都知道,這玩意在國外已經火了幾百年了,但國內除了幾家大公司,貌似沒多少人去嘗試它,不過在上一年開始,pwa在國內還是熱了一下的。pwa是我們在追求webapp便捷和原生應用良好體驗結合的過程中的產物,目前兼容性是最大障礙,但相信它在國內的前景還是明朗的。pwa的特性有可離線、添加到桌面(一級入口)、后臺同步、服務端推送等等,這個項目的話實現了可離線和添加到桌面這兩個功能。起初聽聞pwa時以為會很復雜,實踐后發現很簡單。
ps: 開發過程在控制臺的Application中可調試對應內容
workboxworkbox 是pwa的一個工具集合,圍繞它的還有一些列工具,如 workbox-cli、gulp-workbox、workbox-webpack-plagin 等等,workbox本身相當于service worker的一個框架,封裝了各種api,和緩存策略,可以讓我們更加便捷的使用service worker。vue-cli3.0集成的是workbox-webpack-plagin,我們可以通過vue.config.js的pwa配置項進行配置
首先,在vue.config.js文件中的進行配置,更詳細的配置項
// vue.config.js module.exports = { pwa: { // 一些基礎配置 name: "Browsing-Exp", themeColor: "#6476DB", msTileColor: "#000000", appleMobileWebAppCapable: "yes", appleMobileWebAppStatusBarStyle: "black", /* * 兩個模式,GenerateSW(默認)和 InjectManifest * GenerateSW 在我們build項目時候,每次都會新建一個service worker文件 * InjectManifest 可以讓我們編輯一個自定義的service worker文件,實現更多的功能,并且可以 * 拿到預緩存列表 */ workboxPluginMode: "InjectManifest", workboxOptions: { // 自定義的service worker文件的位置 swSrc: "src/service-worker.js", // ...other Workbox options... } }
然后我們需要在src文件目錄下面新建一個service-worker.js,這里拿此項目做例子,workbox的常用接口有:
workbox.precaching 對靜態支援進行緩存
workbox.routing 進行路由控制
workbox.strategies 提供緩存策略
等等
更詳細的 接口和配置教程
// src/service-worker.js // 設置相應緩存的名字的前綴和后綴 workbox.core.setCacheNameDetails({ prefix: "browse-exp", suffix: "v1.0.0", }); // 讓我們的service worker盡快的得到更新和獲取頁面的控制權 workbox.skipWaiting(); workbox.clientsClaim(); /* * vue-cli3.0通過workbox-webpack-plagin 來實現相關功能,我們需要加入 * 以下語句來獲取預緩存列表和預緩存他們,也就是打包項目后生產的html,js,css等* 靜態文件 */ workbox.precaching.precacheAndRoute(self.__precacheManifest || []); // 對我們請求的數據進行緩存,這里采用 networkFirst 策略 workbox.routing.registerRoute( new RegExp(".*experiments?.*"), workbox.strategies.networkFirst() ); workbox.routing.registerRoute( new RegExp(".*experiments/d"), workbox.strategies.networkFirst() ) workbox.routing.registerRoute( new RegExp(".*experiment_types.*"), workbox.strategies.networkFirst() )
在這里,首先通過workbox.precaching.precacheAndRoute配置app shell的預緩存,然后就是通過workbox.routing.registerRoute對請求數據的緩存,因為對于請求的數據有一定的實時性要求,所以采用網絡優先策略 networkFirst ,這里隨便提一下相關的策略:
networkFirst網絡優先策略,優先嘗試通過網絡請求來獲取數據,拿到數據后將數據返回給用戶,并更新緩存,獲取數據失敗就使用緩存中的數據。
cacheFirst緩存優先策略,優先獲取緩存中的資源,如果緩存中沒有相關資源,那么就發起網絡請求。
networkOnly顧名思義,只使用網絡請求獲取的資源
cacheOnly顧名思義,只使用緩存中的資源
stateWhileRevalidate此策略會直接返回緩存中的資源,確保獲取資源的速度,然后再發起網絡請求獲取數據去更新緩存中的資源。如果緩存中沒有對應資源的話就會發起網絡請求,并緩存資源。
如何查看效果呢這些配置可以讓我們的得以在離線環境下運行,但是這些配置都是相對于打包出來的項目文件的,也就是dist文件里的內容。我們在開發過程的dev模式是體驗不到效果的,我們怎么查看效果呢?
方案1:編寫一個后臺服務,我們可以通過node.js等編寫一個后臺服務去訪問我們的應用,service worker本來需要在https環境下運行,但是如果是本地 localhost 環境的話,service worker可以在http協議上運行。
方案2:借助google提供的chrome擴展應用Web Server for Chrome為我們的應用啟動一個服務,比較靈活,所以我采用了這種方式。
Web Server for Chrome點擊choose foloer選擇我們的dist文件夾,勾選Automatically show index.html開啟服務,我們就可以通過下面的鏈接訪問應用了,通過勾選Accessible on local network還可以生成另一個地址,可以讓我們在手機端訪問應用。
manifest.json 提供了將webapp 添加到設備主屏幕的功能,更詳細的配置內容在此查看。我們可以通過它給我們的應用設置圖標,啟動動畫,背景顏色等等。它在我們項目的public下:
// public/manifest.json // 最基本的配置內容 { "name": "瀏覽我們的實驗吧!", "short_name": "BrowseExp", "icons": [ { "src": "/img/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/img/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ], "start_url": "/index.html", "display": "standalone", "background_color": "#000000", "theme_color": "#4DBA87" }
當瀏覽器(支持此功能的瀏覽器)檢測到目錄中的manifest.json文件時,就會讀取其中的內容。在適當的時機彈出詢問框,詢問是否將應用添加到桌面。注意它不會在第一次訪問就彈出,而是發現用戶在一定時間內多次訪問該網站時才會彈出。在開發過程中我們可以點擊Application -> Manifest -> Add to homescreen 觸發彈框彈出。
移動端其他小問題作為移動端web app,我們需要解決一些常見的小問題,比如:
各瀏覽器間樣式統一問題
移動端點擊300ms延遲問題
點透事件
rem的運用
1.各瀏覽器間樣式統一問題常見做法就是引入normalize.css重置我們設備的默認樣式,使得各瀏覽器的默認樣式高度一致,避免我們的布局出現意想不到的情況。
2.點擊300ms延遲和點透事件因為我們的移動端的瀏覽器需要判斷用戶是否想要雙擊放大,所以會有一個300ms的延遲來查看用戶是否雙擊屏幕;點透事件就是當我們混用touch和click事件的時候,在touch事件響應后,如果該元素隱藏掉,那么300ms后同一位置的底層元素的click事件就會被觸發。對于它們常用的解決方法就是引入 fastclick.js ,這個庫的原理就是:修改瀏覽器的touch事件來模擬一個click事件,并把瀏覽器在300ms之后的click事件阻止掉。讓前端開發人員可以以熟悉的click來書寫代碼
3.rem的運用移動端我們常常會使用到rem來進行響應式的布局,我們通常會將html的font-size設置為 62.5%,那么我們的 1rem = 10px,便于我們的單位轉換。
項目部署開發完畢后,就需要把我們的項目部署到自己的服務器上面去
編寫一個服務首先我們編寫一個后端服務,讓我們可以訪問到項目的index.html文件,這里采用express起個服務。
// browse-exp.js const fs = require("fs") const path = require("path") const express = require("express") const app = express(); app.use(express.static(path.resolve(__dirname, "./dist"))) app.get("*", function(req, res) { const html = fs.readFileSync(path.resolve(__dirname, "./dist/index.html"), "utf-8") res.send(html) }) app.listen(3002, function() { console.log("server listening on port 3002!") })
然后將項目通過比如ftp等工具上傳到服務器,我用的服務器是nginx,它的特點就是輕量級,高并發,可配置反向代理。然后需要配置個代理將我們對服務器的訪問代理到該項目。在etc/nginx/conf.d目錄下創建我們的配置文件 holyzheng-top-3002.conf
# etc/nginx/conf.d/holyzheng-top-3002.conf # 實例,代表我們的應用 upstream browseexp { server 127.0.0.1:3002; } # 將以http協議對我們項目的訪問轉到https協議 server { listen 80; # http監聽的端口 server_name browseexp.holyzheng.top; # 我要使用的ip域名 error_page 405 =200 @405; # 允許對靜態資源進行POST請求 location @405 { proxy_pass http://browseexp; } rewrite ^(.*) https://$host$1 permanent; } # 配置代理,將對域名browseexp.holyzheng.top的訪問代理到服務端的127.0.0.1:3002 # 也就是我們的應用 server { listen 443; server_name browseexp.holyzheng.top; # 跟證書有關的配置,在申請證書的時候會有提示這部分配置 ssl on; ssl_certificate /etc/nginx/cert/1538045542271.pem; ssl_certificate_key /etc/nginx/cert/1538045542271.key; ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; if ($ssl_protocol = "") { # 判斷用戶是否輸入協議 rewrite ^(.*) https://$host$1 permanent; } location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Nginx-Proxy true; proxy_pass http://browseexp; # 要代理的實例 } }
這樣我們就可以通過對于域名來訪問了來訪問該項目了。這里給出對應二維碼,可以進行訪問查看:
下面是在安卓端UC瀏覽器訪問的結果(因為UC對pwa的支持十分好),在幾次訪問我們的應用后就彈出了相關的提示,點擊“好的”就可以添加到主屏幕了。
結語我非常享受嘗試新事物(自己沒做過)的這個過程,這次記錄下來并分享給大家,希望對大家有幫助,如果大家看后有什么補充或意見的話,歡迎評論區提出。項目地址:browse-Exp
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40145.html
摘要:前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點;分為新聞熱點、開發教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎關注【前端之巔】微信公眾號(ID:frontshow),及時獲取前端每周清單;本文則是對于...
摘要:前端每周清單第期支付寶前端構建工具發展用加快網頁響應速度餓了么升級實踐前端前端每周清單前端每周清單專注前端領域內容,分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。 前端每周清單第 12 期:支付寶前端構建工具發展、LinkedIn用Brotli加快網頁響應速度、餓了么PWA 升級實踐 為InfoQ中文站特供稿件,首發地址為這里;如需轉載,請與InfoQ中文站聯系。從屬于筆...
摘要:雖然有著各種各樣的不同,但是相同的是,他們前端優化不完全指南前端掘金篇幅可能有點長,我想先聊一聊閱讀的方式,我希望你閱讀的時候,能夠把我當作你的競爭對手,你的夢想是超越我。 如何提升頁面渲染效率 - 前端 - 掘金Web頁面的性能 我們每天都會瀏覽很多的Web頁面,使用很多基于Web的應用。這些站點看起來既不一樣,用途也都各有不同,有在線視頻,Social Media,新聞,郵件客戶端...
摘要:前端每周清單半年盤點之與篇前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。與求同存異近日,宣布將的構建工具由遷移到,引發了很多開發者的討論。 前端每周清單半年盤點之 React 與 ReactNative 篇 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點;分為...
摘要:但是,有一件事是肯定的年對全棧開發者的需求量很大。有一些方法可以解決這個問題,例如模式,或者你可以這么想,其實谷歌機器人在抓取單頁應用程序時沒有那么糟糕。谷歌正在這方面努力推進,但不要指望在年會看到任何突破。 對于什么是全棧開發者并沒有一個明確的定義。但是,有一件事是肯定的:2019 年對全棧開發者的需求量很大。在本文中,我將向你概述一些趨勢,你可以嘗試根據這些趨勢來確定你可能要投入的...
閱讀 2207·2021-10-18 13:28
閱讀 2520·2021-10-11 10:59
閱讀 2345·2019-08-29 15:06
閱讀 1137·2019-08-26 13:54
閱讀 814·2019-08-26 13:52
閱讀 3151·2019-08-26 12:02
閱讀 3005·2019-08-26 11:44
閱讀 2515·2019-08-26 10:56