# 🌐 Expo PWA 開發與測試完整指南 > 使用 Expo (React Native) 建立可安裝至手機/桌面的漸進式網頁應用程式(PWA) --- ## 🎯 目標 建立一個支援: - 安裝到主畫面 - 離線使用(離線快取) - 桌面與手機通用的 PWA --- ## 🧠 第一部分:核心概念 ### 1️⃣ manifest.json(應用程式資訊清單) - 告訴瀏覽器 App 的名稱、圖示、啟動畫面顏色、顯示模式等 - 讓網站具備「可安裝」的能力 ### 2️⃣ Service Worker(服務工作線程) - 背景執行的 JS 腳本,用來攔截網路請求 - 功能:離線快取、推播通知等 - 建議使用 Google 的 [Workbox](https://developer.chrome.com/docs/workbox/) 工具簡化設定 --- ## 🛠 第二部分:設定步驟(從零開始) > 前提:已有可正常運作的 Expo 專案 --- ### 📁 步驟 1:建立 public 資料夾與 PWA 靜態檔案 ```bash mkdir public ``` **建立 `public/manifest.json`:** ```json { "short_name": "您的App簡稱", "name": "您的App完整名稱", "icons": [ { "src": "logo192.png", "type": "image/png", "sizes": "192x192" }, { "src": "logo512.png", "type": "image/png", "sizes": "512x512" } ], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" } ``` **準備圖示:** - `logo192.png`(192x192) - `logo512.png`(512x512) --- ### 🧾 步驟 2:建立與編輯 `index.html` ```bash npx expo customize public/index.html ``` **編輯 `public/index.html` `<head>` 加入:** ```html <link rel="manifest" href="/manifest.json" /> <script> if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker .register('/sw.js') .then(registration => { console.log('Service Worker registered:', registration.scope); }) .catch(error => { console.error('Service Worker registration failed:', error); }); }); } </script> ``` --- ### 🔧 步驟 3:使用 Workbox 設定 Service Worker ```bash npm install workbox-cli --save-dev ``` **建置靜態網頁:** ```bash npx expo export -p web ``` **執行 Workbox 設定精靈:** ```bash npx workbox-cli wizard ``` 回答: - `Root of your web app`: `dist` - `Which file types`: 預設即可 - `Where to save service worker`: `dist/sw.js` - `Where to save config`: 預設即可(會產生 `workbox-config.js`) **產生 Service Worker:** ```bash npx workbox-cli generateSW workbox-config.js ``` --- ### 🧩 步驟 4:整合建置指令 **編輯 `package.json`:** ```json "scripts": { "build:web": "expo export -p web && npx workbox-cli generateSW workbox-config.js" } ``` > ✅ 未來只需 `npm run build:web` 即可建置並產生 Service Worker! --- ## 🧪 第三部分:本機測試與部署 --- ### 📱 步驟 5:手機本機測試 ```bash npx serve dist ``` - 查看終端顯示 `http://192.168.x.x:3000` - 手機與電腦同一 Wi-Fi - 手機瀏覽器輸入 IP,測試: - 加入主畫面 - 離線模式 ❗ 若失敗,請檢查防火牆設定 --- ### 🚀 步驟 6:部署到正式環境 上傳 `dist` 資料夾內容到任一靜態主機: - Netlify - Vercel - GitHub Pages --- ## 📂 附錄:核心檔案程式碼 --- ### `App.js` ```jsx import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; export default function App() { return ( <View style={styles.container}> <Text style={styles.title}>🌿 小農市集</Text> <Text>這是一個可以安裝到主畫面的 Web App!</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fffbe6', }, title: { fontSize: 28, fontWeight: 'bold', marginBottom: 20, }, }); ``` --- ### `app.json` ```json { "expo": { "name": "pwa_test", "slug": "pwa_test", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", "splash": { "image": "./assets/splash-icon.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "ios": { "supportsTablet": true }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, "edgeToEdgeEnabled": true }, "web": { "favicon": "./assets/favicon.png", "name": "PWA 測試", "shortName": "PWA", "display": "standalone", "startUrl": ".", "backgroundColor": "#ffffff", "themeColor": "#4CAF50" } } } ``` --- ### `public/index.html` ```html <!DOCTYPE html> <html lang="%LANG_ISO_CODE%"> <head> <link rel="manifest" href="/manifest.json" /> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>%WEB_TITLE%</title> <style id="expo-reset"> html, body { height: 100%; overflow: hidden; } #root { display: flex; height: 100%; flex: 1; } </style> <script> if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker .register('/sw.js') .then(reg => console.log('SW scope:', reg.scope)) .catch(err => console.error('SW error:', err)); }); } </script> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html> ``` --- 🧑‍💻 完成!您現在擁有一個可以「安裝、離線、跨平台」的 React Native PWA!