PWA 渐进式 WEB 应用

PWA 渐进式 web 应用

简介

PWA(Progressive Web App,渐进式网页应用)是一种可以提供类似原生应用体验的网页应用。 通过利用最新的 Web 技术特性,实现跨平台兼容性,并且在桌面和移动设备上都能够以全屏或近似原生应用的方式运行。

特性

  • 渐进式:PWA 适用于所有用户,无论他们使用什么浏览器,因为它是以渐进式增强作为核心原则构建的。
  • 响应式:它们的界面自适应各种形态的设备:桌面、手机、平板电脑等。
  • 离线工作:通过 Service Workers 来缓存应用外壳和数据,在没有网络的情况下也可以使用。
  • 感觉像原生应用:PWA 可以添加到设备的主屏幕,发送推送通知,并访问设备功能。
  • 始终更新:由于 Service Worker 的更新过程,PWA始终保持最新。
  • 安全:通过 HTTPS 提供服务,确保应用数据的传输安全。
  • 易找寻:由于是网页应用,所以 PWA 可以通过搜索引擎被发现,与普通网页同样优化 SEO。
  • 可链接:通过 URL 容易分享应用,不需要复杂的安装流程。

关键技术

  • Service Workers: 脚本工作在浏览器后台,独立于网页,可以拦截和处理网络请求,包括缓存或检索资源。
  • Web App Manifest: JSON 文件,描述了个性化起始画面、全屏等展示解决方案以及PWA的外观。
  • Application Shell (App Shell): 基础的 HTML/CSS/JS 架构,负责加载用户界面的速度。
  • IndexedDB 和 Cache API: 缓存资料与结构,实现离线数据的有效管理。

从零创建一个简单的 PWA 渐进式应用

你如果希望使用脚手架搭建一个完整的 PWA 项目,可以尝试使用 Quasar 框架,这也是 Vue 官方推荐的框架。 (www.quasarchs.com/quasar-cli-...

应用目录如下

  • index.html
  • manifest.json
  • service-worker.js
  • icons
    • icon-128x128.png
    • icon-192x192.png
    • icon-256x256.png
    • icon-384x384.png
    • icon-512x512.png

PWA 应用部署与普通网页基本一致,唯一不同的是 PWA 必须使用 https 协议(localhost 除外)。 windows 系统下可以直接下载 nginx,将 html 下的文件替换成项目文件,运行 nginx 即可(nginx.org/en/download...

代码实现

html 复制代码
// index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>PWA渐进式应用</title>
    <link rel="manifest" href="./manifest.json">
</head>
<body>
<h1>PWA渐进式应用</h1>
<script>
    window.addEventListener("load", () => {
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/service-worker.js')
         .then(function({ installing, waiting, active }) {
           if (installing) console.log("正在安装 Service worker");
           if (waiting) console.log("已安装 Service worker installed");
           if (active) console.log("激活 Service worker");
         })
         .catch(function(err) {
           console.log('Service Worker 注册失败:', err);
         });
      }
    })
</script>
</body>
</html>
json 复制代码
{
  "manifest.json": "配置并引入该文件后即可实现下载,如果需要实现离线使用则需结合 Service Worker",
  "参考地址": "https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json",
  "id": "pwa",
  "name": "pwa",
  "short_name": "pwa",
  "description": "pwa",
  "display": "standalone",
  "start_url": "/",
  "orientation": "portrait",
  "background_color": "#aaa",
  "theme_color": "#fff",
  "icons": [
    {
      "src": "icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icons/icon-256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
js 复制代码
// service-worker.js
// API 可参考 https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API

// 定义您想要缓存的文件列表
const CACHE_NAME = 'FIRSTPWA';
const urlsToCache = [
  '/index.html',
  '/manifest.json',
  '/icons/icon-128x128.png',
  '/icons/icon-192x192.png',
  '/icons/icon-256x256.png',
  '/icons/icon-384x384.png',
  '/icons/icon-512x512.png'
];

// 安装 Service Worker 并缓存所有预定义资源
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

// 捕获页面请求,从缓存中提供数据
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
          // 如果缓存命中直接返回缓存内容,否则继续请求
          if (response) {
            return response;
          }
          return fetch(event.request);
        }
      )
  );
});

// 更新缓存
self.addEventListener('activate', event => {
  const cacheWhiteList = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          // 删除不在白名单中的缓存
          if (cacheWhiteList.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
相关推荐
开心工作室_kaic2 分钟前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿21 分钟前
webWorker基本用法
前端·javascript·vue.js
cy玩具42 分钟前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161771 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test2 小时前
js下载excel示例demo
前端·javascript·excel
Yaml42 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事2 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶2 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo2 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v2 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript