乐闻世界logo
搜索文章和话题

PWA 开发中有哪些常用的工具和框架?如何使用它们?

2月18日 22:02

PWA 的开发需要使用一系列工具和框架来提高开发效率和代码质量。以下是常用的 PWA 开发工具和框架:

核心开发工具

1. Workbox

Workbox 是 Google 提供的 PWA 开发工具集,简化了 Service Worker 的开发。

安装

bash
npm install workbox-cli --global npm install workbox-webpack-plugin --save-dev

使用 Workbox CLI

bash
# 生成 Service Worker workbox generateSW workbox-config.js # 预缓存文件 workbox wizard

Workbox 配置

javascript
// workbox-config.js module.exports = { globDirectory: 'dist/', globPatterns: [ '**/*.{html,js,css,png,jpg,jpeg,svg,woff,woff2}' ], swDest: 'dist/sw.js', runtimeCaching: [ { urlPattern: /^https:\/\/api\.example\.com\/.*/, handler: 'NetworkFirst', options: { cacheName: 'api-cache', expiration: { maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 // 30 days } } }, { urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, handler: 'CacheFirst', options: { cacheName: 'image-cache', expiration: { maxEntries: 60, maxAgeSeconds: 60 * 24 * 60 * 60 // 60 days } } } ] };

在 Webpack 中使用 Workbox

javascript
// webpack.config.js const { GenerateSW } = require('workbox-webpack-plugin'); module.exports = { plugins: [ new GenerateSW({ clientsClaim: true, skipWaiting: true, runtimeCaching: [ { urlPattern: /\.(?:png|jpg|jpeg|svg)$/, handler: 'CacheFirst', options: { cacheName: 'images', expiration: { maxEntries: 60 } } } ] }) ] };

2. PWA Builder

PWA Builder 是 Microsoft 提供的工具,可以将 PWA 打包为原生应用。

bash
# 安装 PWA Builder CLI npm install -g pwabuilder # 打包应用 pwabuilder package

3. Lighthouse

Lighthouse 是 Google 提供的网站性能和质量审计工具。

bash
# 安装 Lighthouse npm install -g lighthouse # 运行审计 lighthouse https://your-pwa.com --view

使用 Lighthouse CI

bash
# 安装 Lighthouse CI npm install -g @lhci/cli # 初始化配置 lhci autorun # 运行 CI lhci autorun --collect.url=https://your-pwa.com

框架和库

1. React PWA

Create React App

bash
# 创建 PWA 项目 npx create-react-app my-pwa --template cra-template-pwa

使用 React PWA

javascript
// src/serviceWorkerRegistration.js export function register(config) { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); if (publicUrl.origin !== window.location.origin) return; window.addEventListener('load', () => { const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; registerValidSW(swUrl, config); }); } }

2. Vue PWA

Vue CLI PWA 插件

bash
# 创建 PWA 项目 vue create my-pwa # 选择 PWA 插件

配置 vue.config.js

javascript
// vue.config.js module.exports = { pwa: { name: 'My PWA', themeColor: '#4DBA87', msTileColor: '#000000', appleMobileWebAppCapable: 'yes', appleMobileWebAppStatusBarStyle: 'black', workboxPluginMode: 'GenerateSW', workboxOptions: { runtimeCaching: [ { urlPattern: /\.(?:png|jpg|jpeg|svg)$/, handler: 'CacheFirst', options: { cacheName: 'images', expiration: { maxEntries: 60 } } } ] } } };

3. Angular PWA

bash
# 添加 PWA 支持 ng add @angular/pwa

配置 ngsw-config.json

json
{ "$schema": "./node_modules/@angular/service-worker/config/schema.json", "index": "/index.html", "assetGroups": [ { "name": "app", "installMode": "prefetch", "resources": { "files": [ "/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js" ] } }, { "name": "assets", "installMode": "lazy", "updateMode": "prefetch", "resources": { "files": [ "/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)" ] } } ], "dataGroups": [ { "name": "api-freshness", "urls": [ "/api/**" ], "cacheConfig": { "maxSize": 100, "maxAge": "3d", "timeout": "10s", "strategy": "freshness" } } ] }

开发工具

1. Chrome DevTools

Service Worker 调试

javascript
// 在 DevTools Console 中 // 查看所有 Service Worker navigator.serviceWorker.getRegistrations().then(registrations => { registrations.forEach(registration => { console.log('SW:', registration); }); }); // 取消注册 Service Worker navigator.serviceWorker.getRegistrations().then(registrations => { registrations.forEach(registration => { registration.unregister(); }); });

Application 面板

  • Service Workers:查看和管理 Service Worker
  • Cache Storage:查看和管理缓存
  • Manifest:查看和验证 Manifest 文件
  • Background Services:查看后台服务状态

2. React DevTools

bash
# 安装 React DevTools npm install --save-dev react-devtools

3. Vue DevTools

bash
# 安装 Vue DevTools npm install --save-dev @vue/devtools

测试工具

1. Jest

javascript
// sw.test.js describe('Service Worker', () => { beforeEach(() => { return navigator.serviceWorker.register('/sw.js'); }); test('should cache static assets', async () => { const cache = await caches.open('static-cache'); const response = await cache.match('/styles/main.css'); expect(response).toBeDefined(); }); });

2. Cypress

javascript
// cypress/integration/pwa.spec.js describe('PWA', () => { it('should work offline', () => { cy.visit('/'); // 模拟离线 cy.window().then((win) => { win.navigator.serviceWorker.controller.postMessage({ type: 'OFFLINE' }); }); // 验证离线功能 cy.contains('Offline').should('be.visible'); }); });

3. Puppeteer

javascript
// test-pwa.js const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 检查 Service Worker await page.goto('https://your-pwa.com'); const sw = await page.evaluate(() => { return navigator.serviceWorker.getRegistration(); }); console.log('Service Worker:', sw); await browser.close(); })();

构建工具

1. Webpack

javascript
// webpack.config.js const { InjectManifest } = require('workbox-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const WebpackPwaManifest = require('webpack-pwa-manifest'); module.exports = { plugins: [ new CopyWebpackPlugin({ patterns: [ { from: 'public/manifest.json', to: 'manifest.json' } ] }), new WebpackPwaManifest({ name: 'My PWA', short_name: 'MyPWA', description: 'My Progressive Web App', background_color: '#ffffff', theme_color: '#4DBA87', icons: [ { src: 'src/assets/icon.png', sizes: [96, 128, 192, 256, 384, 512], destination: 'icons' } ] }), new InjectManifest({ swSrc: './src/sw.js', swDest: 'sw.js' }) ] };

2. Vite

javascript
// vite.config.js import { VitePWA } from 'vite-plugin-pwa'; export default { plugins: [ VitePWA({ registerType: 'autoUpdate', includeAssets: ['favicon.ico', 'apple-touch-icon.png'], manifest: { name: 'My PWA', short_name: 'MyPWA', description: 'My Progressive Web App', theme_color: '#ffffff', icons: [ { src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png' }, { src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png' } ] }, workbox: { runtimeCaching: [ { urlPattern: /^https:\/\/api\.example\.com\/.*/, handler: 'NetworkFirst', options: { cacheName: 'api-cache', expiration: { maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 } } } ] } }) ] };

部署工具

1. Netlify

toml
# netlify.toml [[headers]] for = "/*" [headers.values] X-Frame-Options = "DENY" X-XSS-Protection = "1; mode=block" Content-Security-Policy = "default-src 'self'" [[redirects]] from = "/*" to = "/index.html" status = 200

2. Vercel

json
// vercel.json { "headers": [ { "source": "/(.*)", "headers": [ { "key": "X-Frame-Options", "value": "DENY" }, { "key": "X-XSS-Protection", "value": "1; mode=block" } ] } ], "rewrites": [ { "source": "/(.*)", "destination": "/index.html" } ] }

3. Firebase Hosting

json
// firebase.json { "hosting": { "public": "dist", "headers": [ { "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000" } ] } ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } }

监控和分析

1. Google Analytics

javascript
// 在 Service Worker 中跟踪 self.addEventListener('fetch', event => { if (navigator.sendBeacon) { navigator.sendBeacon('/analytics', JSON.stringify({ url: event.request.url, timestamp: Date.now() })); } });

2. Sentry

javascript
// 在 Service Worker 中捕获错误 self.addEventListener('error', event => { Sentry.captureException(event.error); }); self.addEventListener('unhandledrejection', event => { Sentry.captureException(event.reason); });

最佳实践

  1. 使用 Workbox:简化 Service Worker 开发
  2. 自动化测试:使用 Jest、Cypress 等工具
  3. 性能监控:使用 Lighthouse 定期审计
  4. 错误追踪:使用 Sentry 等工具
  5. CI/CD 集成:自动化构建和部署
  6. 代码分割:使用 Webpack、Vite 等工具
  7. 缓存策略:根据资源类型选择合适的策略
  8. 渐进增强:确保在不支持 PWA 的浏览器中正常工作
标签:PWA