介绍

PWA(Progressive Web App) 是结合了网络和应用程序体验的产物。不需要安装,本身是Web网页。在手机系统上,还能添加到主屏幕,快速加载,全屏展示,达到接近原生应用的体验。

特点

  • 渐进式 - 不会存在兼容性的问题,在不支持的浏览器下会按照正常网页的加载方式
  • 响应式 - 可以适配任何屏幕,因为本身就是浏览器打开网页,所以…
  • 网络独立 - 没有网或者网络质量低的情况下也能使用
  • 自动更新 - 依赖于 Service Workers 的功能
  • 可安装 - 可以添加到主屏幕(Android IOS)
  • 可链接 - 通过一个URL就可以很容易的分享App

工作方式

PWA流程

依赖于 Service Workers 的功能,可以控制指定的资源请求,通过本地来存储。下次再请求时就不用访问网络了。

笔记应用Demo

  • 第一次打开网页,会去服务器下载静态资源(JS,CSS,图片等),然后浏览器渲染,资源存到本地
  • 再次打开网页,静态资源都会从本地加载
  • 当静态资源更新之后,后台运行的 Service Workers 会下载最新的资源存到本地

网页整体结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Notes</title>
<link rel="stylesheet" type="text/css" href="styles/inline.css">
<link rel="manifest" href="/manifest.json">
</head>
<body>
<main class="main">
<div class="main__inner">
<h1 class="title">Notes</h1>
<form class="note__form" id="note-form">
<input id="note-input" class="note__input" name="note-item" placeholder="Input you want note">
</form>
<ul id="note-list" class="note__list"></ul>
</div>
</main>
<script src='scripts/app.js' async></script>
</body>
</html>

app.js

  • 实现笔记的增加获取
  • 绑定 ServiceWorker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
(function () {
'use strict';

var app = {
isLoading: true,
noteList: document.getElementById('note-list'),
noteCount: 0
};

document.getElementById('note-form').addEventListener('submit', function (e) {
app.sumbitNote();
e.preventDefault();
});

app.saveNote = function (noteId, value) {
localStorage.setItem('task-' + noteId, value);
};

app.getNote = function (noteId) {
return localStorage.getItem(noteId);
};

app.sumbitNote = function () {
var noteNode = document.getElementById("note-input");
console.log('[Note App] sumbit note');
var value = noteNode.value;
if (value === '' || value === null) {
return
}
app.saveNote(app.noteCount, value);
noteNode.value = '';
app.noteCount++;
app.loadNotes();
};

app.loadNotes = function () {
app.noteList.innerHTML = '';
for (app.noteCount = 0; app.noteCount < localStorage.length; app.noteCount++) {
var nodeId = 'task-' + app.noteCount;
var ele = document.createElement('li');
ele.className = 'note__item';
ele.id = nodeId;
ele.innerHTML = app.getNote(nodeId);
app.noteList.appendChild(ele);
}
};

app.bindServiceWorker = function () {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('./service-worker.js')
.then(function () { console.log('Service Worker Registered'); });
}
};

app.bindServiceWorker();
app.loadNotes();
})();

service-worker.js

  • 确定哪些文件需要存储
  • 从网络获取时,先从本地拿
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Polyfill for Chrome caching
importScripts('scripts/cache-polyfill.js');

var cacheName = 'note-pwa-v1';

var filesToCache = [
'/',
'/index.html',
'scripts/app.js',
'styles/inline.css',
'manifest.json',
'imgs/icons/icon-128.png',
'imgs/icons/icon-144.png',
'imgs/icons/icon-152.png',
'imgs/icons/icon-256.png'
];

self.addEventListener('install', function (e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function (cache) {
return cache.addAll(filesToCache);
})
);
});

self.addEventListener('activate', function (e) {
e.waitUntil(
caches.keys().then(function (keyList) {
return Promise.all(keyList.map(function (key) {
if (key !== cacheName) {
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});

self.addEventListener('fetch', function (e) {
e.respondWith(
caches.match(e.request).then(function (response) {
return response || fetch(e.request);
})
);
});

manifest.json

  • 配置图标和描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"short_name": "简记",
"name": "最简笔记",
"start_url": "/index.html",
"background_color": "#eeeeee",
"orientation": "portrait",
"display": "standalone",
"theme_color": "#ffffff",
"icons": [
{
"src": "imgs/icons/icon-128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "imgs/icons/icon-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "imgs/icons/icon-152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "imgs/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "imgs/icons/icon-256.png",
"sizes": "256x256",
"type": "image/png"
}
]
}

Repo

https://github.com/jiyangg/Progressive-Web-Notes



Web      PWA

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!