หากคุณเป็นนักพัฒนาเว็บที่ไม่รู้จักการพัฒนาแอป (อย่างผม!) บทความนี้คือสำหรับคุณ ผมจะสอนวิธีเปลี่ยนเว็บไซต์เป็นแอป native โดยไม่ต้องเรียนเฟรมเวิร์กหรือภาษาใหม่ คุณจะได้เรียนรู้วิธีแปลงเว็บไซต์เป็น PWA (Progressive Web App) ที่เผยแพร่บน Play Store ได้
ก่อนอื่น เราจะทำให้เว็บไซต์ของคุณกลายเป็น Progressive Web App (PWA) จากนั้นเราจะใช้เครื่องมือ CLI ฟรีจาก Google ที่ชื่อ Bubblewrap เพื่อแพ็กเกจ PWA นั้นเป็นแอป Android มาเริ่มกันเลย
ข้อกำหนดเบื้องต้น
หากคุณติดตามบทช่วยสอนนี้ มีข้อกำหนดเบื้องต้นบางอย่าง:
ความรู้พื้นฐานเกี่ยวกับการพัฒนาเว็บ
เว็บไซต์ของคุณควรเผยแพร่สาธารณะแล้ว และคุณต้องเข้าถึงซอร์สโค้ดได้
เราจะใช้ npm ติดตั้งเครื่องมือที่จำเป็น ตรวจสอบให้แน่ใจว่าคุณติดตั้ง Node.js แล้ว
หมายเหตุ: บทช่วยสอนนี้อิงตามโปรเจกต์ Vite แต่ขั้นตอนสุดท้ายกับ Bubblewrap เหมือนกันสำหรับเฟรมเวิร์กเว็บใดๆ
สารบัญ
PWA คืออะไร?
Bubblewrap คืออะไร?
TWA (Trusted Web Activity) คืออะไร?
TWA ยืนยันความเชื่อถืออย่างไร?
ขั้นตอน 1 – กำหนดค่า PWA ใน Vite
สร้างไอคอนแอป
ติดตั้งปลั๊กอิน Vite PWA
กำหนดค่าปลั๊กอิน
ขั้นตอน 2 – สร้างแอป Android
สร้างโฟลเดอร์ Build
ติดตั้ง Bubblewrap CLI
เริ่มต้นโปรเจกต์
มาดูวิธีแก้ปัญหาคำสั่ง init
ขั้นตอน 3 – ตอบคำถามของ Bubblewrap
ขั้นตอน 4 – สร้างแอป (Build)
ขั้นตอน 5 – ตั้งค่าการตรวจสอบ TWA
โฟลเดอร์ .well-known คืออะไร?
delegate_permission/common.handle_all_urls คืออะไร?
ขั้นตอน 6 (เพิ่มเติม) – ปรับแต่งประสบการณ์ในแอป
สรุป
PWA คืออะไร?
PWA ย่อมาจาก Progressive Web Application เป้าหมายคือทำให้เว็บไซต์ของคุณดูและรู้สึกเหมือนแอป native หากคุณเคยเข้าชมเว็บไซต์ในเบราว์เซอร์และเห็นไอคอนติดตั้งที่ให้ดาวน์โหลดไปที่โทรศัพท์หรือแลปท็อป คุณเคยใช้ PWA แล้ว
แต่มันไม่ได้เกี่ยวกับแค่ลักษณะนอก PWA ยังมีฟีเจอร์แบบแอป เช่น ทำงานออฟไลน์ ส่ง push notifications และอื่นๆ
PWA มี 2 ส่วนหลัก:
ไฟล์ Manifest อธิบายแอปของคุณ เช่น ชื่อ ไอคอน Start URL ฯลฯ
Service Worker คือไฟล์ JavaScript แบบพื้นหลังที่ทำหน้าที่เป็น proxy การแคชและ push notifications ถูกจัดการโดย service file ที่รันเป็นเธรดแยกจาก main thread
โดยไม่มีทั้งสองส่วนนี้ เบราว์เซอร์จะไม่ให้ผู้ใช้ดาวน์โหลดแอปในเครื่องได้
ไฟล์ Manifest และ Service Worker เหมือนเช็คลิสต์สำหรับเบราว์เซอร์ เมื่อคุณเข้าชมเว็บไซต์ เบราว์เซอร์จะมองหาทั้งสองส่วน หากมีอยู่และกำหนดค่าถูกต้อง เบราว์เซอร์จะรู้ว่าเป็น PWA จริง และจะแสดงไอคอน "ติดตั้ง" ให้ผู้ใช้ดาวน์โหลดแอปในเครื่อง โดยไม่มีทั้งสอง เบราว์เซอร์จะมองว่าเป็นเว็บไซต์ทั่วไป และตัวเลือกติดตั้งจะไม่ปรากฏ
Bubblewrap คืออะไร?
Bubblewrap เป็นเครื่องมือ CLI ที่ Google สร้างขึ้น รับ PWA ของคุณและเปลี่ยนเป็นแอป Android โดยใช้ Trusted Web Activity (TWA)
Bubblewrap ทำให้กระบวนการสร้าง TWA เรียบง่าย เปลี่ยนไฟล์ manifest ของ PWA ให้กลายเป็นแพ็กเกจแอป Android (APK หรือ AAB)
TWA (Trusted Web Activity) คืออะไร?
Trusted Web Activity (TWA) เป็นฟีเจอร์ Android สมัยใหม่ที่ให้คุณแสดงเว็บไซต์สดของคุณเต็มจอภายในแอป Android โดยพื้นฐานแล้ว มันรันเว็บไซต์บนเบราว์เซอร์ แต่ไม่แสดงแถบที่อยู่ (address bar) บนแอป นี่ช่วยให้รู้สึกเหมือนแอป native
เพื่อปลดล็อกฟีเจอร์เต็มจอนี้ แอปของคุณต้องได้รับการยืนยันว่า "Trusted" (เชื่อถือได้)
นี่คือที่มาของ "การคบมือลับ" (Secret Handshake) Android ต้องมั่นใจว่าผู้สร้างแอปและเจ้าของเว็บไซต์เป็นคนเดียวกัน โดยไม่มีหลักฐานการเป็นเจ้าของ TWA จะทำงานในโหมด fallback และแสดงแถบที่อยู่ของเบราว์เซอร์ด้านบน ทำให้ความรู้สึก native app หายไป
TWA ยืนยันความเชื่อถืออย่างไร?
ความเชื่อถือนี้ได้รับการยืนยันด้วยระบบที่เรียกว่า Digital Asset Links คุณวางไฟล์พิเศษบนเว็บไซต์ของคุณ (เราจะทำในส่วนการนำไปใช้) ที่มีลายนิ้วมือดิจิทัลเฉพาะของแอป เมื่อผู้ใช้เปิดแอป Android OS จะตรวจสอบไฟล์นี้ หากลายนิ้วมือตรงกัน มันจะให้สถานะ "trusted" กับแอปของคุณ ลบแถบที่อยู่ และเปิดใช้งานฟีเจอร์อื่นๆ เช่น deep linking
คุณสามารถตรวจสอบความสัมพันธ์นี้เองได้ด้วยเครื่องมือทดสอบทางการของ Google: Digital Asset Links Verifier
ตอนนี้คุณเข้าใจโปรเจกต์และเครื่องมือแล้ว มาเริ่มสร้างกัน
ขั้นตอน 1 – กำหนดค่า PWA ใน Vite
ขั้นตอนแรกคือเพิ่มสองส่วนหลักสำหรับ PWA: ไฟล์ manifest และ service worker นี่คือสิ่งที่จะทำให้เบราว์เซอร์รู้จักมันว่า "ติดตั้งได้"
คู่มือนี้อิงโปรเจกต์ที่สร้างด้วย Vite ซึ่งทำให้กระบวนการนี้ง่ายด้วยปลั๊กอินพิเศษ หากคุณใช้เครื่องมืออื่น แนวคิดเหมือนกัน แต่คุณต้องค้นหาทรัพยากรเฉพาะสำหรับสภาพแวดล้อมของคุณ
สร้างไอคอนแอปของคุณ
ก่อนที่เราจะสัมผัสโค้ด เราต้องการไอคอนสำหรับแอป Android ต้องการขนาดเฉพาะสำหรับไอคอน launcher (ที่คุณเห็นบนหน้าจอหลัก) และ splash screen (ที่คุณเห็นเมื่อแอปเริ่มต้น)
คุณต้องการ 2 ขนาดหลัก: 192x192 พิกเซล และ 512x512 พิกเซล คุณสามารถใช้ Favicon Generator นี้เพื่อสร้างโลโก้ในขนาดที่เหมาะสม อัปโหลดโลโก้หลัก และมันจะสร้างขนาดที่จำเป็นทั้งหมดให้คุณ
จากนั้นดาวน์โหลดไฟล์ที่สร้างขึ้น และวางไฟล์ 192x192 และ 512x512 ลงในโฟลเดอร์ public ของโปรเจกต์

ติดตั้งปลั๊กอิน Vite PWA
PWA ต้องการไฟล์ manifest และ service worker เราสามารถสร้างด้วยมือได้ แต่ปลั๊กอินนี้ทำให้กระบวนการทั้งหมดอัตโนมัติ มันจะสร้าง manifest.json และ service-worker.js ให้คุณโดยอัตโนมัติทุกครั้งที่คุณ build โปรเจกต์
npm install vite-plugin-pwa -D
กำหนดค่าปลั๊กอิน
ในขั้นตอนนี้ เราจะใช้ปลั๊กอินนี้และกำหนดค่า manifest ของแอป แก้ไขไฟล์ vite.config.ts การกำหนดค่านี้จะบอกปลั๊กอินว่าจะตั้งชื่อแอปอะไร ใช้ไอคอนไหน และอื่นๆ
ใน vite.config.ts:
export default defineConfig({
plugins: [
VitePWA({
registerType: "autoUpdate",
manifest: {
name: "your app name",
short_name: "your app short name",
description: "write any description",
theme_color: "#0d1117",
background_color: "#ffffff",
display: "standalone",
start_url: "/",
icons: [
{
src: "/web-app-manifest-192x192.png",
sizes: "192x192",
type: "image/png",
},
{
src: "/web-app-manifest-512x512.png",
sizes: "512x512",
type: "image/png",
},
],
},
}),
],
});
ตอนนี้ เมื่อคุณรัน npm run build ปลั๊กอินจะสร้างไฟล์ manifest และ service worker ให้โดยอัตโนมัติ ด้วยการนี้ ให้ deploy การเปลี่ยนแปลง ตอนนี้เว็บไซต์ของคุณเป็น PWA แล้ว
ขั้นตอน 2 – สร้างแอป Android
ตอนนี้เว็บไซต์ของคุณเป็น PWA แล้ว มาใช้ Bubblewrap แพ็กเกจมันเป็นแอป Android
สร้างโฟลเดอร์ Build
สร้างโฟลเดอร์เฉพาะสำหรับไฟล์โปรเจกต์ Android ในรูทของโปรเจกต์ สร้างโฟลเดอร์ใหม่ ผมจะตั้งชื่อว่า android
project/
├── client/
├── server/
└── android/
ตอนนี้.navigate ไปที่โฟลเดอร์ใหม่ที่คุณสร้าง
ติดตั้ง Bubblewrap CLI
npm install -g @bubblewrap/cli
เริ่มต้นโปรเจกต์ (Initialize)
ต่อไป รันคำสั่ง init Bubblewrap จะเชื่อมต่อกับเว็บไซต์สดของคุณ อ่านไฟล์ manifest.webmanifest ที่ Vite สร้าง และใช้ข้อมูลนั้นเพื่อสร้างโปรเจกต์ Android พื้นฐาน
bubblewrap init --manifest=https://your-website-domain/manifest.webmanifest
รันคำสั่ง แทนที่ your-website-domain ด้วย URL จริงของคุณ:
มาดูวิธีแก้ปัญหาคำสั่ง init
ขณะที่คุณรันคำสั่ง init Bubblewrap จะต้องการแพ็กเกจซอฟต์แวร์ 2 ตัวหลัก: Java Development Kit (JDK) และ Android SDK มันจะเสนอติดตั้งให้คุณ
การตั้งค่า JDK:
? Do you want Bubblewrap to install the JDK (recommended)? (Enter "No" to use your own JDK 17 installation) (Y/n)
ในกรณีของผม เมื่อให้ Bubblewrap ติดตั้ง JDK กระบวนการดาวน์โหลดไฟล์แต่ล้มเหลวที่ขั้น "decompressing" หากคุณเจอปัญหาเดียวกัน อย่ากลัว! วิธีแก้คือติดตั้งเอง
ตอบ No สำหรับ prompt
ดาวน์โหลดเวอร์ชันที่แนะนำ (มักเป็น JDK 17) จากแหล่งเช่น Adoptium
ติดตั้งและตั้งค่าตัวแปรสภาพแวดล้อมของระบบให้รวม path
binของ JDK หากคุณไม่แน่ใจวิธีตั้งค่า environment variables 可以查看这个网站: Set Environment Variablesเมื่อ Bubblewrap ขอ path ให้ระบุโดยตรง เช่น
C:\java\jdk-17.0.16.8-hotspot
การตั้งค่า Android SDK:
เมื่อ JDK ตั้งค่าสำเร็จ ขั้นตอนต่อไปคือกำหนดค่า Android SDK
? Do you want Bubblewrap to install the Android SDK (recommended)? (Enter "No" to use your own Android SDK installation) (Y/n)
เพราะผมไม่มี Android SDK ผมให้ Bubblewrap จัดการโดยเลือก Yes ผมไม่เจอปัญหาที่นี่
หากคุณเจอปัญหาในการตั้งค่า Android SDK ให้ตั้งค่าเองและระบุ path เหมือนการตั้งค่า JDK
ขั้นตอน 3 – ตอบคำถามของ Bubblewrap
หลังจากตั้งค่า SDK เสร็จ Bubblewrap จะถามชุดคำถามเพื่อกำหนดค่าแอปของคุณ ข้อมูลนี้ใช้สร้างไฟล์ twa-manifest.json ซึ่งเป็นแผนผังของแอปคุณ
Domain: กด Enter (กรอกอัตโนมัติจาก manifest)
Application name: ชื่อแอปเต็มของคุณ
Application ID: (เช่น chat.yourapp.twa)
Display mode: standalone
Orientation: portrait
Status bar color: กด Enter (ยอมค่าเริ่มต้น)
Splash screen color: กด Enter (ยอมค่าเริ่มต้น)
Icon URL: กด Enter (ยอมค่าเริ่มต้น)
Include support for Play Billing?: พิมพ์ Y หากแอปใช้ in-app purchases ของ Google Play มิฉะนั้น N
Request geolocation permission?: พิมพ์ Y หากแอปต้องการเข้าถึงตำแหน่ง มิฉะนั้น N
ในคำถามเหล่านี้ ส่วนสำคัญคือ key store และ key
First and Last names: ชื่อเต็มของคุณ
Organizational Unit: Developer หรืออะไรก็ได้
Organization: ชื่อองค์กรของคุณ
Country (2-letter code): รหัสประเทศ 2 ตัวอักษร
Password for key store: ใส่รหัสผ่านใหม่
Password for key: ใส่รหัสผ่านเดียวกันอีกครั้ง
หมายเหตุ: รหัสผ่านสำหรับ key store และ key ควรเหมือนกัน มิฉะนั้นจะเกิด error ดู issue นี้: Bubblewrap Issue
ขั้นตอน 4 – สร้างแอป (Build)
bubblewrap build --universalApk
คำสั่งนี้เริ่มสร้างแอปพลิเคชันของคุณ ที่นี่ flag universalApk จะผลิตไฟล์ .apk และ .aab หากคุณจะเผยแพร่บน Play Store ให้อัปโหลดไฟล์ .aab สำหรับการทดสอบเราต้องการไฟล์ APK ดังนั้น flag universalApk จะผลิตทั้งสองไฟล์ หากไม่ใส่ flag นี้ จะได้แค่ .aab
ขั้นตอน 5 – ตั้งค่าการตรวจสอบ TWA
เมื่อ build เสร็จ คุณจะได้ไฟล์ APK โอนไปที่โทรศัพท์และทดสอบ เมื่อเปิดแอป คุณจะเห็นแถบที่อยู่ของเบราว์เซอร์ เพราะเรายังไม่ได้ตั้งค่า "ความเชื่อถือ" ระหว่างแอปและเว็บไซต์ มาแก้ไขตอนนี้
ในโปรเจกต์ frontend ของคุณ ไปที่โฟลเดอร์ public สร้างโฟลเดอร์ใหม่ชื่อ .well-known และภายในสร้างไฟล์ชื่อ assetlinks.json
frontend/
├── public/
├── .well-known/
└── assetlinks.json
.well-known โฟลเดอร์คืออะไร?
โฟลเดอร์ well-known ใช้เก็บไฟล์ที่กำหนดคอนฟิกสำหรับโปรโตคอล ใช้สำหรับแหล่งภายนอกค้นหาการตรวจสอบสำหรับเว็บไซต์ของคุณ ในกรณีของเรา แอปของเราตรวจสอบโฟลเดอร์ well-known จากเว็บไซต์ของเราและยืนยันการตรวจสอบ
วางสิ่งต่อไปนี้ลงใน assetlinks.json:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "chat.yourapp.twa",
"sha256_cert_fingerprints": [
"your_sha256_fingerprint"
]
}
}
]
delegate_permission/common.handle_all_urls คืออะไร?
นี่คือ flag พิเศษที่เปิดลิงก์ทั้งหมดจากแอปแทนที่จะเปิดในโดเมน อย่างง่ายๆ มันทำหน้าที่เป็น deeplink หลังจากคุณติดตั้งแอป หากคุณคลิกลิงก์เว็บไซต์ของคุณจาก WhatsApp หรือที่ไหน มันจะเปิดแอปของคุณแทนที่จะเปิดในเบราว์เซอร์ ทำหน้าที่เป็น deeplink
ฟิลด์ package_name ควรเป็น packageId ซึ่งคุณได้จากโฟลเดอร์ build Android ใน twa-manifest.json
ตอนนี้ รับลายนิ้วมือของคุณ รันคำสั่งต่อไปนี้:
keytool -list -v -keystore android.keystore -alias android
ชื่อ alias ควรเป็นค่าที่คุณสร้าง เมื่อคุณรันคำสั่งนี้ จะขอรหัสผ่าน key store ใส่ไป และคุณจะได้ SHA256 fingerprint คัดลอกและวางลงในไฟล์ assetslinks.json ใน array sha256_cert_fingerprints ตอนนี้ push การเปลี่ยนแปลงไป production คุณสามารถตรวจสอบการตรวจสอบได้ใน Digital Asset Links
แค่นี้ก็เสร็จ! ตอนนี้คุณสามารถติดตั้งแอปและทดสอบได้
ขั้นตอน 6 (เพิ่มเติม) – ปรับแต่งประสบการณ์ในแอป
นอกจากนี้ จะมีกรณีที่เราอยากแสดงเนื้อหาต่างกันให้ผู้ใช้บนเว็บไซต์ vs แอปมือถือ ทำได้ไหม? ทำได้!
ในโฟลเดอร์ build Android ของคุณ ใน twa-manifest.json จะมีฟิลด์ชื่อ startUrl หากไม่มี ให้เพิ่มและใส่ค่า "startUrl": "/?twa=true" startUrl คือจุดเข้าผมมี query parameter ค่า twa=true
รัน build อีกครั้งด้วย bubblewrap build --universalApk
ตอนนี้ หากคุณเปิดแอป มันจะเปิดด้วย entry URL เป็น yourwebsitedomain.com/?twa=true
ใน frontend ของคุณ:
const twaParam = queryParams.get("twa");
const [isTwa, setIsTwa] = useState<boolean>(() => {
return localStorage.getItem("isTwa") === "true";
});
useEffect(() => {
if (twaParam === "true") {
localStorage.setItem("isTwa", "true");
setIsTwa(true);
}
}, [twaParam]);
{isTwa ? (
<Link to="/contact" className="underline hover:text-primary">
Contact
</Link>
) : (
<Link to="/download" className="underline hover:text-primary">
Download App
</Link>
)}
ในโค้ดด้านบน เราตรวจสอบ query parameter twa=true ใน URL หากมี เราบันทึกข้อมูลลง local storage และ render เนื้อหาเฉพาะสำหรับผู้ใช้ในแอป
แค่นี้เราสร้างแอปเสร็จแล้ว
หากต้องการเปลี่ยนชื่อ สี หรือ splash screen คุณสามารถเปลี่ยนได้ใน twa-manifest.json และรัน build อีกครั้ง
สรุป
Bubblewrap ใช้ได้กับ Android เท่านั้น หากต้องการแอปรองรับ cross-platform มีแพลตฟอร์มอื่น เช่น Capacitor ซึ่งผมจะเขียนในบทความอื่น
โดยทางคุณสามารถดูแอปที่ผมสร้างด้วย Bubblewrap ได้ที่นี่: Stranger Talk
หากมีข้อผิดพลาดหรือมีคำถาม ติดต่อผมได้ที่ LinkedIn หรือ Instagram
ขอบคุณที่อ่าน!
เรียนรู้การเขียนโค้ดฟรี หลักสูตรโอเพนซอร์สของ freeCodeCamp ช่วยให้ผู้คนมากกว่า 40,000 คนได้งานเป็นนักพัฒนา เริ่มต้นเลยวันนี้