構建一個簡單的新聞客戶端PWA應用

開始

這是一個純練手的小項目,旨在練習使用PWA(Progressive Web Apps)相關技術構建一個網絡應用。css

項目地址:https://github.com/bjw1234/ne...html

預覽地址:https://bjw1234.github.io/new...git

手機端截屏:github

主頁面
clipboard.pngweb

詳情頁
clipboard.pngshell

PWA是什麼?

PWA(Progressive Web Apps)漸進式網絡應用,結合了 Web 和 原生應用中最好功能的一種體驗。對於首次訪問的用戶它是很是有利的, 用戶能夠直接在瀏覽器中進行訪問,不須要安裝應用。隨着時間的推移當用戶漸漸地和應用創建了聯繫,它將變得愈來愈強大。它可以快速地加載,即便在比較糟糕的網絡環境下,可以推送相關消息, 也能夠像原生應用那樣添加至主屏,可以有全屏瀏覽的體驗。json

Service Worker

PWA中一個很重要的點就是利用Service Worker攔截攔截客戶端請求,若是請求命中緩存中的數據,則無需訪問網絡,直接返回。canvas

註冊Service Worker

if('serviceWorker' in navigator){
        navigator.serviceWorker.register('./news_sw.js').then(reg => {            
            console.log('ServiceWorker registration successful with scope:' + reg.scope);
        }).catch(err => {
            console.log('ServiceWorker registration fail:',err);    
        });
    }

Service Worker詳情

news_sw.js,在這個文件中咱們須要去監聽三件事情,Service Worker的安裝,激活以及fetch事件。瀏覽器

// 安裝事件,在這裏將一些初始化或者`app shell`資源加入緩存列表
self.addEventListener('install', event => {
    event.waitUntil(
        // xxx
    );
});

// 激活事件,在這個函數中處理資源的更新
self.addEventListener('activate', event => {
    event.waitUntil((
        //xxx
    );
});

// fetch事件,在這個函數中攔截並處理用戶的請求
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request,{ ignoreSearch: true }).then( response => {
            if(response){ // 緩存命中直接返回 }
            // 向服務器請求資源
                // 出錯則返回
                // response ok
                // 添加到緩存列表 
        });
    );
});

客戶端發起請求

function requestData(url) {
    fetch(url,{
        method:'GET'
    }).then(result => {
        if(result){
            return result.json();
        }
    }).then(data => {
        console.log(data);
        buildWebPage(data.latestNews);
    });
}

解析URL

當用戶在首頁點擊不一樣的新聞,須要跳轉到新聞詳情頁。因此在article.js中去解析URL判斷給用戶呈現什麼內容。緩存

// 解析url
function queryParameter(url){
    let obj = {};
    url.replace(/([^?&=]+)=([^?&=]+)/g,($0,$1,$2) => {
        obj[$1] = $2;
    });
    return obj;
}

// 獲取地址欄的url
let param = queryParameter(document.location.href);

每一條新聞的數據結構

模擬來自服務器端的json數據。

{
  "id": 0,
  "image":"./images/0.jpg",
  "title": "中方迴應馬來西亞將取消新隆高鐵項目",
  "desc": "有記者問:據報道,馬來西亞總理昨天宣佈將取消新隆高鐵項目......",
  "time":"兩分鐘前",
  "read":"2344評",
  "type":"國內"
}
...

manifest.json配置

{
  "name": "news web app",
  "short_name": "hello news",
  "start_url": "./index.html",
  "theme_color": "#00ff8b",
  "background_color": "#00ff8b",
  "display": "standalone",
  "icons": [
    {
      "src": "./images/news-144.png",
      "sizes": "144X144",
      "type": "image/png"
    },
    {
      "src": "./images/news-192.png",
      "sizes": "192X192",
      "type": "image/png"
    }
  ]
}

CSS實現多行文本超出省略號顯示

overflow : hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;

是否支持webp格式的判斷

// 在serviceWorker中攔截請求
self.addEventListener('fetch',event => {
    if(/\.jpg$|\.png$/.test(event.request.url)){
        let supportWebp = false;
        // 判斷是否支持webp文件        
        if(event.request.headers.has('accept')){
            supportWebp = event.request.headers.get('accept').includes('webp');
        }

        if(supportWebp){
            var req = event.request.clone();            
            var returnUrl = 'http://localhost/sunset.jpg';
            console.log(returnUrl);
            event.respondWith(
                fetch(returnUrl,{
                    mode:'no-cors'
                })
            );
        }    
    }
});

// 在window中判斷
function isSupportWebp(){
    var isSWebp = !![].map && 
document.createElement('canvas').toDataURL('image/webp').
indexOf('data:image/webp') == 0;
    return isSWebp;
}
相關文章
相關標籤/搜索