跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端

前端 PWA:构建离线可用与可安装的 Web 应用

介绍 PWA(渐进式 Web 应用)的核心概念与实现方案。通过对比错误配置与正确实践,详细阐述了 manifest.json 配置、Service Worker 缓存策略及推送通知功能的完整代码示例。旨在帮助开发者构建支持离线访问、主屏幕安装及高性能的现代化 Web 应用,避免常见误区。

GopherDev发布于 2026/4/6更新于 2026/7/2052 浏览

前端 PWA:构建离线可用与可安装的 Web 应用

常见误区

PWA(Progressive Web App)常被误解为简单的技术组合。常见的错误认知包括:

  • '用户直接用浏览器不就好了'——导致无法离线访问,用户体验差。
  • '我有原生 App,不需要 PWA'——忽略了开发成本高、维护困难的问题。
  • 'PWA 就是加个 manifest 和 service worker'——往往功能不完整,体验不佳。

PWA 不是简单的技术堆砌,而是一种现代化的 Web 应用模式。

为什么你需要这个?

  • 离线访问:即使没有网络也能访问应用核心内容。
  • 安装到主屏幕:像原生 App 一样方便使用,无浏览器地址栏干扰。
  • 推送通知:及时向用户发送重要信息,提升活跃度。
  • 性能提升:缓存静态资源,加快加载速度。
  • 跨平台:一次开发,多平台运行。

反面教材

以下是不完整的配置示例,会导致 PWA 功能失效。

<!DOCTYPE html>
<html>
<head>
<title>我的 PWA 应用</title>
<!-- 缺少 manifest.json -->
<!-- 缺少 service worker -->
</head>
<body>
<h1>我的 PWA 应用</h1>
<p>这是一个 PWA 应用</p>
</body>
</html>
// 简单的 Service Worker,未实现缓存逻辑
self.addEventListener('install', event => {
  console.log('Service Worker 安装');
});
self.addEventListener(,  {
  .();
});
self.(,  {
  .();
});
'activate'
event =>
console
log
'Service Worker 激活'
addEventListener
'fetch'
event =>
console
log
'Service Worker 拦截请求'

正确的做法

1. HTML 配置

需包含 Manifest 链接、主题色及图标设置。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的 PWA 应用</title>
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#317EFB">
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
<link rel="preload" href="/style.css" as="style">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>我的 PWA 应用</h1>
<p>这是一个完整的 PWA 应用</p>
<button id="notification-btn">发送通知</button>
<script src="/script.js"></script>
<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log('Service Worker 注册成功:', registration.scope);
      })
      .catch(error => {
        console.log('Service Worker 注册失败:', error);
      });
  });
}
</script>
</body>
</html>
2. Manifest 配置

定义应用名称、图标及显示模式。

{
  "name": "我的 PWA 应用",
  "short_name": "PWA 应用",
  "description": "一个完整的 PWA 应用示例",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#317EFB",
  "icons": [
    { "src": "/icons/icon-72x72.png", "sizes": "72x72", "type": "image/png", "purpose": "any" },
    { "src": "/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }
  ]
}
3. Service Worker 实现

包含缓存策略、离线处理及推送支持。

const CACHE_NAME = 'pwa-app-cache-v1';
const ASSETS_TO_CACHE = [
  '/', '/index.html', '/style.css', '/script.js', '/manifest.json',
  '/icons/icon-192x192.png'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(ASSETS_TO_CACHE))
      .then(() => self.skipWaiting())
  );
});

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);
          }
        })
      ).then(() => self.clients.claim());
    })
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      if (response) return response;
      return fetch(event.request).then(response => {
        if (response && response.status === 200 && response.type === 'basic') {
          const responseToCache = response.clone();
          caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseToCache));
        }
        return response;
      }).catch(() => {
        if (event.request.mode === 'navigate') return caches.match('/offline.html');
      });
    })
  );
});

self.addEventListener('push', event => {
  const data = event.data.json();
  const options = {
    body: data.body,
    icon: '/icons/icon-192x192.png',
    badge: '/icons/icon-72x72.png',
    data: { url: data.url }
  };
  event.waitUntil(self.registration.showNotification(data.title, options));
});

self.addEventListener('notificationclick', event => {
  event.notification.close();
  event.waitUntil(clients.openWindow(event.notification.data.url));
});
4. 前端交互逻辑

处理通知权限与 PWA 模式检测。

function requestNotificationPermission() {
  if ('Notification' in window) {
    Notification.requestPermission().then(permission => {
      if (permission === 'granted') console.log('通知权限已授予');
      else console.log('通知权限被拒绝');
    });
  }
}

function sendNotification() {
  if ('serviceWorker' in navigator && 'PushManager' in window) {
    navigator.serviceWorker.ready.then(registration => {
      registration.showNotification('测试通知', {
        body: '这是一条测试通知',
        icon: '/icons/icon-192x192.png',
        badge: '/icons/icon-72x72.png',
        data: { url: '/' }
      });
    });
  }
}

window.addEventListener('load', () => {
  requestNotificationPermission();
  const notificationBtn = document.getElementById('notification-btn');
  if (notificationBtn) {
    notificationBtn.addEventListener('click', sendNotification);
  }
});

function checkPwaMode() {
  const isPwa = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone;
  console.log(isPwa ? '应用以 PWA 模式运行' : '应用以浏览器模式运行');
}
checkPwaMode();

总结

PWA 并非替代原生 App,而是通过 Web 技术获得类似原生体验的补充方案。关键点包括:

  • manifest.json:配置应用元数据与图标。
  • Service Worker:实现离线缓存、后台同步及推送。
  • 离线访问:确保无网络时核心功能可用。
  • 安装体验:提供独立入口,去除浏览器框架。
  • 推送通知:增强用户触达能力。
  • 性能优化:利用缓存策略加速加载。

正确实施 PWA 能让网站具备现代化应用的能力,同时保持 Web 的跨平台优势。

目录

  1. 前端 PWA:构建离线可用与可安装的 Web 应用
  2. 常见误区
  3. 为什么你需要这个?
  4. 反面教材
  5. 正确的做法
  6. 1. HTML 配置
  7. 2. Manifest 配置
  8. 3. Service Worker 实现
  9. 4. 前端交互逻辑
  10. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 Llama-Factory 部署微调大模型 API 服务实战
  • 2026 前端跨端框架选型指南
  • 嵌入式 C/C++ 核心知识点整理
  • 字节跳动前端一面面经深度解析
  • Agent 智能体开发框架对比:主流方案选型指南
  • 全网最牛批的前端面试八股文(最全)堪称2025最强!
  • Python 变量与数据类型核心指南
  • AI Agent 新范式:FastGPT 集成 MCP 协议构建工具增强型智能体
  • AI Coding 核心概念、工作流与上下文管理策略
  • JavaScript/TypeScript 前端实现文件上传到 MinIO 指南
  • 知网与维普 AIGC 检测机制对比及应对策略
  • 医疗 AI 场景下朴素贝叶斯算法深度解析
  • MacOS 安装 OpenClaw 并接入飞书机器人
  • YOLO11 无人机航拍小目标检测实战与系统实现
  • Windows 系统安装与配置 RabbitMQ 教程
  • 2024 生成式人工智能指南:大模型行业应用与开发实战
  • 夸克网盘精选资源合集:书籍、软件、教程及 AI 资料
  • 汽车雷达多径环境下幽灵目标检测技术解析
  • DeepSeek 深度使用指南与提示词技巧
  • OpenClaw:使用 AI 直接操控电脑的工具指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online