PWA development requires a series of tools and frameworks to improve development efficiency and code quality. Here are commonly used PWA development tools and frameworks:
Core Development Tools
1. Workbox
Workbox is a PWA development toolset provided by Google that simplifies Service Worker development.
Installation
bashnpm install workbox-cli --global npm install workbox-webpack-plugin --save-dev
Using Workbox CLI
bash# Generate Service Worker workbox generateSW workbox-config.js # Pre-cache files workbox wizard
Workbox Configuration
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 } } } ] };
Using Workbox in Webpack
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 is a tool provided by Microsoft that can package PWA as native apps.
bash# Install PWA Builder CLI npm install -g pwabuilder # Package app pwabuilder package
3. Lighthouse
Lighthouse is a website performance and quality audit tool provided by Google.
bash# Install Lighthouse npm install -g lighthouse # Run audit lighthouse https://your-pwa.com --view
Using Lighthouse CI
bash# Install Lighthouse CI npm install -g @lhci/cli # Initialize configuration lhci autorun # Run CI lhci autorun --collect.url=https://your-pwa.com
Frameworks and Libraries
1. React PWA
Create React App
bash# Create PWA project npx create-react-app my-pwa --template cra-template-pwa
Using 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 Plugin
bash# Create PWA project vue create my-pwa # Select PWA plugin
Configure 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# Add PWA support ng add @angular/pwa
Configure 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" } } ] }
Development Tools
1. Chrome DevTools
Service Worker Debugging
javascript// In DevTools Console // View all Service Workers navigator.serviceWorker.getRegistrations().then(registrations => { registrations.forEach(registration => { console.log('SW:', registration); }); }); // Unregister Service Worker navigator.serviceWorker.getRegistrations().then(registrations => { registrations.forEach(registration => { registration.unregister(); }); });
Application Panel
- Service Workers: View and manage Service Workers
- Cache Storage: View and manage caches
- Manifest: View and validate Manifest file
- Background Services: View background service status
2. React DevTools
bash# Install React DevTools npm install --save-dev react-devtools
3. Vue DevTools
bash# Install Vue DevTools npm install --save-dev @vue/devtools
Testing Tools
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('/'); // Simulate offline cy.window().then((win) => { win.navigator.serviceWorker.controller.postMessage({ type: 'OFFLINE' }); }); // Verify offline functionality 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(); // Check 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(); })();
Build Tools
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 } } } ] } }) ] };
Deployment Tools
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" } ] } }
Monitoring and Analytics
1. Google Analytics
javascript// Track in Service Worker self.addEventListener('fetch', event => { if (navigator.sendBeacon) { navigator.sendBeacon('/analytics', JSON.stringify({ url: event.request.url, timestamp: Date.now() })); } });
2. Sentry
javascript// Capture errors in Service Worker self.addEventListener('error', event => { Sentry.captureException(event.error); }); self.addEventListener('unhandledrejection', event => { Sentry.captureException(event.reason); });
Best Practices
- Use Workbox: Simplify Service Worker development
- Automated Testing: Use Jest, Cypress and other tools
- Performance Monitoring: Regularly audit with Lighthouse
- Error Tracking: Use Sentry and other tools
- CI/CD Integration: Automate build and deployment
- Code Splitting: Use Webpack, Vite and other tools
- Cache Strategy: Choose appropriate strategy based on resource type
- Progressive Enhancement: Ensure normal operation in browsers that don't support PWA