การสร้าง Progressive Web App หลายรายการในโดเมนเดียวกัน

วิธีสร้าง PWA หลายตัวโดยใช้ประโยชน์จากชื่อโดเมนเดียวกัน เพื่อแจ้งให้ผู้ใช้ทราบว่าตนเองเป็นขององค์กรหรือบริการเดียวกัน

Chase Phillips
Matt Giuca
Matt Giuca

ในบล็อกโพสต์เกี่ยวกับ Progressive Web App ในเว็บไซต์หลายแหล่งที่มา Demian ได้พูดถึงความท้าทายที่เว็บไซต์ที่สร้างในแหล่งที่มาหลายแห่งพบเมื่อพยายามสร้าง Progressive Web App รายการเดียวที่รวมเว็บไซต์ทั้งหมดไว้

ตัวอย่างโครงสร้างเว็บไซต์ประเภทนี้คือเว็บไซต์อีคอมเมิร์ซที่มีลักษณะดังนี้

  • หน้าแรกอยู่ที่ https://www.example.com
  • หน้าหมวดหมู่โฮสต์อยู่ที่ https://category.example.com
  • หน้ารายละเอียดผลิตภัณฑ์ที่ https://product.example.com

ดังที่ได้กล่าวไว้ในบทความ นโยบายต้นทางเดียวกันจะกำหนดข้อจำกัดหลายประการ ซึ่งป้องกันการแชร์ Service Worker, แคช และสิทธิ์ระหว่างต้นทาง ด้วยเหตุนี้ เราขอแนะนําอย่างยิ่งให้หลีกเลี่ยงการกําหนดค่าประเภทนี้ และสำหรับผู้ที่มีเว็บไซต์ที่สร้างด้วยวิธีนี้แล้ว ให้พิจารณาย้ายข้อมูลไปยังสถาปัตยกรรมเว็บไซต์ต้นทางเดียวเมื่อเป็นไปได้

แผนภาพแสดงเว็บไซต์ที่แบ่งออกเป็นหลายต้นทางและแสดงให้เห็นว่าเราไม่แนะนําให้ใช้เทคนิคนี้เมื่อสร้าง PWA
หลีกเลี่ยงการใช้ต้นทางที่แตกต่างกันสำหรับส่วนต่างๆ ของเว็บไซต์เดียวกันเมื่อพยายามสร้าง Progressive Web App แบบรวม

ในโพสต์นี้ เราจะดูกรณีที่ตรงข้ามกันแทน นั่นคือ เราจะวิเคราะห์กรณีของบริษัทที่ต้องการให้บริการ PWA หลายรายการ โดยใช้ประโยชน์จากชื่อโดเมนเดียวกัน และทำให้ผู้ใช้ทราบว่า PWA เหล่านั้นเป็นขององค์กรหรือบริการเดียวกัน

คุณอาจสังเกตเห็นว่าเราใช้คําที่ต่างกันแต่มีความเกี่ยวข้องกัน เช่น โดเมนและต้นทาง ก่อนดำเนินการต่อ เรามาทบทวนแนวคิดเหล่านี้กัน

คำศัพท์ทางเทคนิค

  • โดเมน: ลำดับป้ายกำกับตามที่กำหนดไว้ในระบบชื่อโดเมน (DNS) เช่น com และ example.com คือโดเมน
  • ชื่อโฮสต์: รายการ DNS ที่แปลเป็นที่อยู่ IP อย่างน้อย 1 รายการ ตัวอย่างเช่น www.example.com จะเป็นชื่อโฮสต์, example.com อาจเป็นชื่อโฮสต์ได้หากมีที่อยู่ IP และ com จะแก้ไขเป็นที่อยู่ IP ไม่ได้ จึงจะเป็นชื่อโฮสต์ไม่ได้
  • ต้นทาง: ชุดค่าผสมของรูปแบบ ชื่อโฮสต์ และพอร์ต (ไม่บังคับ) เช่น https://www.example.com:443 เป็นต้นทาง

นโยบายต้นทางเดียวกันจะกำหนดข้อจำกัดเกี่ยวกับต้นทาง ดังที่ชื่อของนโยบายบ่งบอกไว้ เราจึงจะใช้คํานี้ตลอดบทความ อย่างไรก็ตาม เราจะใช้ "โดเมน" หรือ "โดเมนย่อย" เป็นครั้งคราวเพื่ออธิบายเทคนิคที่ใช้ในการสร้าง "ต้นทาง" ที่แตกต่างกัน

ในบางกรณี คุณอาจต้องการสร้างแอปอิสระ แต่ยังคงระบุว่าแอปเหล่านั้นเป็นขององค์กรหรือ "แบรนด์" เดียวกัน การใช้ชื่อโดเมนเดียวกันซ้ำเป็นวิธีที่ดีในการสร้างความสัมพันธ์ดังกล่าว เช่น

  • เว็บไซต์อีคอมเมิร์ซต้องการสร้างประสบการณ์การใช้งานแบบสแตนด์อโลนเพื่อให้ผู้ขายจัดการสินค้าคงคลังได้ ในขณะเดียวกันก็ช่วยให้ผู้ขายเข้าใจว่าเว็บไซต์ดังกล่าวเป็นส่วนหนึ่งของเว็บไซต์หลักที่ผู้ใช้ซื้อผลิตภัณฑ์
  • เว็บไซต์ข่าวกีฬาต้องการสร้างแอปเฉพาะสำหรับการแข่งขันกีฬาที่สำคัญ เพื่อให้ผู้ใช้ได้รับสถิติเกี่ยวกับการแข่งขันที่ชื่นชอบผ่านการแจ้งเตือน และติดตั้งแอปเป็น Progressive Web App ในขณะเดียวกันก็ทำให้ผู้ใช้ทราบว่าแอปดังกล่าวเป็นแอปที่บริษัทข่าวสร้างขึ้น
  • บริษัทต้องการสร้างแอปแชท อีเมล และปฏิทินแยกกันและต้องการให้แอปดังกล่าวทำงานเป็นแอปเดี่ยวๆ ที่เชื่อมโยงกับชื่อบริษัท
หลีกเลี่ยงการใช้ต้นทางที่แตกต่างกันสำหรับส่วนต่างๆ ของเว็บไซต์เดียวกันเมื่อพยายามสร้าง Progressive Web App แบบรวม
บริษัทที่เป็นเจ้าของ example.com ต้องการให้บริการแอปหรือ PWA อิสระ 3 แอปโดยใช้ชื่อโดเมนเดียวกันเพื่อสร้างความสัมพันธ์ระหว่างแอปหรือ PWA เหล่านั้น

ใช้ต้นทางแยกกัน

ในกรณีเช่นนี้ วิธีที่แนะนำคือสำหรับแอปที่มีแนวคิดที่แตกต่างกันแต่ละแอปซึ่งเผยแพร่อยู่ในต้นทางของแอปนั้นๆ

หากต้องการใช้ชื่อโดเมนเดียวกันในโดเมนย่อยทั้งหมด ให้ใช้โดเมนย่อย ตัวอย่างเช่น บริษัทที่ให้บริการแอปอินเทอร์เน็ตหลายรายการหรือหลายบริการสามารถโฮสต์แอปอีเมลใน https://mail.example.com และแอปปฏิทินที่ https://calendar.example.com ในขณะที่ให้บริการหลักของธุรกิจที่ https://www.example.com อีกตัวอย่างหนึ่งคือเว็บไซต์กีฬาที่ต้องการสร้างแอปอิสระที่มุ่งเน้นการแข่งขันกีฬาที่สำคัญโดยเฉพาะ เช่น การแข่งขันฟุตบอลชิงแชมป์ที่ https://footballcup.example.com ซึ่งผู้ใช้สามารถติดตั้งและใช้แอปดังกล่าวได้โดยไม่เกี่ยวข้องกับเว็บไซต์กีฬาหลักที่โฮสต์ที่ https://www.example.com แนวทางนี้ยังอาจมีประโยชน์สําหรับแพลตฟอร์มที่อนุญาตให้ลูกค้าสร้างแอปอิสระของตนเองภายใต้แบรนด์ของบริษัทด้วย เช่น แอปที่ช่วยให้ผู้ขายสร้าง PWA ของตนเองได้ที่ https://merchant1.example.com, https://merchant2.example.com ฯลฯ

การใช้แหล่งที่มาที่แตกต่างกันจะแยกแอปแต่ละแอปออกจากกัน ซึ่งหมายความว่าแอปแต่ละแอปจะจัดการฟีเจอร์ต่างๆ ของเบราว์เซอร์ได้อย่างอิสระ ซึ่งรวมถึง

  • ความสามารถในการติดตั้ง: แอปแต่ละแอปจะมีไฟล์ Manifest เป็นของตัวเองและมอบประสบการณ์การติดตั้งของตนเอง
  • พื้นที่เก็บข้อมูล: แอปแต่ละแอปมีแคช พื้นที่เก็บข้อมูลในเครื่อง และพื้นที่เก็บข้อมูลภายในอุปกรณ์ทุกรูปแบบโดยที่แอปไม่ต้องแชร์กับแอปอื่นๆ
  • Service Worker: แอปแต่ละแอปจะมี Service Worker ของตัวเองสำหรับขอบเขตที่ลงทะเบียนไว้
  • สิทธิ์: สิทธิ์ยังมีขอบเขตตามต้นทางด้วย ด้วยเหตุนี้ ผู้ใช้จึงทราบได้อย่างชัดเจนว่ากำลังให้สิทธิ์บริการใดอยู่ และฟีเจอร์ต่างๆ เช่น การแจ้งเตือนจะระบุแหล่งที่มาของแอปแต่ละแอปอย่างเหมาะสม

การสร้างการแยกระดับดังกล่าวเป็นสิ่งที่ต้องการมากที่สุดใน Use Case ของ PWA อิสระหลายรายการ ดังนั้นเราขอแนะนำแนวทางนี้อย่างยิ่ง

หากแอปในโดเมนย่อยต้องการแชร์ข้อมูลในเครื่องระหว่างกัน ก็จะยังคงแชร์ผ่านคุกกี้ได้อยู่ หรือในกรณีที่เป็นสถานการณ์ขั้นสูง ก็ลองซิงค์ข้อมูลพื้นที่เก็บข้อมูลผ่านเซิร์ฟเวอร์ได้

ALT_TEXT_HERE
การสร้าง PWA ที่แตกต่างกันในต้นทางที่แตกต่างกันโดยใช้โดเมนย่อยเป็นแนวทางปฏิบัติแนะนำ

ใช้ต้นทางเดียวกัน

แนวทางที่ 2 คือการสร้าง PWA ที่แตกต่างกันในต้นทางเดียวกัน ซึ่งรวมถึงสถานการณ์ต่อไปนี้

เส้นทางที่ไม่ซ้อนทับกัน

PWA หรือ "เว็บแอป" แนวความคิดหลายรายการที่โฮสต์ในต้นทางเดียวกันโดยมีเส้นทางที่ไม่ทับซ้อนกัน เช่น

  • https://example.com/app1/
  • https://example.com/app2/

เส้นทางซ้อน/ซ้อนกัน

PWA หลายรายการในต้นทางเดียวกัน โดยที่ขอบเขตของรายการหนึ่งฝังอยู่ภายในอีกรายการหนึ่ง

  • https://example.com/ ("แอปภายนอก")
  • https://example.com/app/ ("แอปภายใน")

API ของ Service Worker และรูปแบบไฟล์ Manifest ช่วยให้คุณทําอย่างใดอย่างหนึ่งข้างต้นได้โดยใช้การกําหนดขอบเขตระดับเส้นทาง อย่างไรก็ตาม ไม่ว่าในกรณีใดก็ตาม การใช้ต้นทางเดียวกันจะก่อให้เกิดปัญหาและข้อจํากัดมากมาย ซึ่งเกิดจากข้อเท็จจริงที่ว่าเบราว์เซอร์จะไม่ถือว่าแอปเหล่านี้เป็น "แอป" ที่แยกกัน ดังนั้นเราไม่แนะนําให้ใช้แนวทางนี้

ALT_TEXT_HERE
เราไม่แนะนำให้ใช้เส้นทาง (ทับซ้อนกันหรือไม่) เพื่อให้บริการ PWA อิสระ 2 รายการ ("app1" "app2") ภายใต้ต้นทางเดียวกัน

ในส่วนถัดไป เราจะวิเคราะห์ปัญหาเหล่านี้โดยละเอียดมากขึ้น รวมถึงสิ่งที่ทําได้หากใช้ต้นทางแยกกันไม่ได้

ความท้าทายสำหรับ PWA ที่มีต้นทางเดียวกันหลายรายการ

ปัญหาที่พบได้ทั่วไปซึ่งเกิดขึ้นกับทั้ง 2 แนวทางแบบแหล่งที่มาเดียวกันมีดังนี้

  • พื้นที่เก็บข้อมูล: แอปต่างๆ จะแชร์คุกกี้ พื้นที่เก็บข้อมูลในเครื่อง และพื้นที่เก็บข้อมูลในเครื่องทุกรูปแบบ ด้วยเหตุนี้ หากผู้ใช้ตัดสินใจล้างข้อมูลในตัวเครื่องของแอปหนึ่ง จะเป็นการลบข้อมูลทั้งหมดจากต้นทาง ซึ่งจะไม่มีวิธีทำได้ในแอปเดียว โปรดทราบว่า Chrome และเบราว์เซอร์อื่นๆ จะแจ้งให้ผู้ใช้ล้างข้อมูลในเครื่องเมื่อถอนการติดตั้งแอปใดแอปหนึ่ง ซึ่งจะส่งผลกับข้อมูลของแอปอื่นๆ ในต้นทางนั้นด้วย ปัญหาอีกอย่างคือแอปจะต้องแชร์โควต้าพื้นที่เก็บข้อมูลด้วย ซึ่งหมายความว่าหากแอปใดแอปหนึ่งใช้พื้นที่มากเกินไป แอปอีกแอปจะได้รับผลกระทบเชิงลบ
  • สิทธิ์: สิทธิ์ของเบราว์เซอร์จะเชื่อมโยงกับต้นทาง ซึ่งหมายความว่าหากผู้ใช้ให้สิทธ์กับแอปหนึ่ง สิทธิ์ดังกล่าวจะมีผลกับทุกแอปในต้นทางนั้นพร้อมกัน นี่อาจฟังดูเข้าท่าดี (ไม่ต้องขอสิทธิ์หลายครั้ง) แต่อย่าลืมว่าหากผู้ใช้บล็อกสิทธิ์ของแอปนั้น ก็จะทำให้ผู้ใช้รายอื่นไม่สามารถขอสิทธิ์นั้นหรือใช้ฟีเจอร์นั้นได้ โปรดทราบว่าแม้ว่าจะต้องให้สิทธิ์เบราว์เซอร์เพียงครั้งเดียวต่อการให้สิทธิ์ต้นทาง แต่สิทธิ์ระดับระบบจะต้องให้สิทธิ์เพียงครั้งเดียวต่อแอป ไม่ว่าแอปหลายแอปจะชี้ไปยังต้นทางเดียวกันหรือไม่ก็ตาม
  • การตั้งค่าผู้ใช้: การตั้งค่าจะตั้งค่าตามต้นทางด้วย ตัวอย่างเช่น หากแอป 2 แอปมีขนาดตัวอักษรต่างกัน และผู้ใช้ต้องการปรับการซูมแอปเพียงแอปเดียวเพื่อชดเชย

ปัญหาเหล่านี้ทำให้การส่งเสริมแนวทางนี้เป็นเรื่องยาก อย่างไรก็ตาม หากใช้ต้นทางแยกต่างหากไม่ได้ (เช่น ซับโดเมน) ตามที่อธิบายไว้ในส่วนการใช้ต้นทางแยกต่างหาก จากตัวเลือกต้นทางเดียวกัน 2 รายการที่เรานำเสนอ เราขอแนะนําอย่างยิ่งให้ใช้เส้นทางที่ไม่ทับซ้อนกันแทนเส้นทางที่ทับซ้อนกัน/ซ้อนกัน

ดังที่ได้กล่าวไปแล้ว ปัญหาที่กล่าวถึงในส่วนนี้เกิดขึ้นได้กับทั้ง 2 วิธีข้างต้น ในส่วนถัดไป เราจะเจาะลึกรายละเอียด ว่าเหตุใดการใช้เส้นทางที่ทับซ้อนกัน/ซ้อนกันจึงเป็นกลยุทธ์ที่แนะนำน้อยที่สุด

ปัญหาเพิ่มเติมสำหรับเส้นทางที่ซ้อนทับ/ซ้อนกัน

ปัญหาเพิ่มเติมเกี่ยวกับแนวทางเส้นทางที่ซ้อนทับ/ฝัง (โดยที่ https://example.com/ เป็นแอปด้านนอกและ https://example.com/app/ เป็นแอปด้านใน) คือ URL ทั้งหมดในแอปด้านในจะถือว่าเป็นส่วนหนึ่งของทั้งแอปด้านนอกและแอปด้านใน

ในทางปฏิบัติ ปัญหาที่อาจเกิดขึ้นมีดังนี้

  • โปรโมชันการติดตั้ง: หากผู้ใช้เข้าชมแอปด้านใน (เช่น ในเว็บเบราว์เซอร์) เมื่อติดตั้งแอปด้านนอกในอุปกรณ์ของผู้ใช้แล้ว เบราว์เซอร์จะไม่แสดงแบนเนอร์โปรโมชันการติดตั้ง และเหตุการณ์ BeforeInstallPrompt จะไม่ทริกเกอร์ สาเหตุคือเบราว์เซอร์จะตรวจสอบว่าหน้าปัจจุบันเป็นของแอปที่ติดตั้งไว้แล้วหรือไม่ และสรุปว่าใช่ วิธีแก้ปัญหานี้คือให้ติดตั้งแอปภายในด้วยตนเอง (ผ่านตัวเลือกเมนู "สร้างทางลัด" ของเบราว์เซอร์) หรือติดตั้งแอปภายในก่อนแอปภายนอก
  • การแจ้งเตือนและ Badging API: หากติดตั้งแอปด้านนอกแล้ว แต่ไม่ได้ติดตั้งแอปด้านใน การแจ้งเตือนและป้ายที่มาจากแอปด้านในจะได้รับการระบุแหล่งที่มาเป็นแอปด้านนอกอย่างไม่ถูกต้อง (ซึ่งเป็นขอบเขตที่ใกล้ที่สุดของแอปที่ติดตั้ง) ฟีเจอร์นี้จะทำงานอย่างถูกต้องในกรณีที่ติดตั้งทั้ง 2 แอปในอุปกรณ์ของผู้ใช้
  • การบันทึกลิงก์: แอปภายนอกอาจบันทึก URL ที่เป็นของแอปภายใน ซึ่งเป็นไปได้อย่างยิ่งหากติดตั้งแอปด้านนอกแล้วแต่ไม่มีแอปภายใน ในทํานองเดียวกัน ลิงก์ภายในแอปภายนอกที่ลิงก์ไปยังแอปภายในจะไม่บันทึกลิงก์ไปยังแอปภายใน เนื่องจากระบบจะถือว่าลิงก์ดังกล่าวอยู่ภายในขอบเขตของแอปภายนอก นอกจากนี้ ใน ChromeOS และ Android หากแอปเหล่านี้เพิ่มลงใน Play Store (เป็นกิจกรรมบนเว็บที่เชื่อถือได้) แอปภายนอกจะบันทึกลิงก์ทั้งหมด แม้ว่าจะติดตั้งแอปภายในแล้ว แต่ระบบปฏิบัติการจะยังคงให้ตัวเลือกแก่ผู้ใช้ในการเปิดแอปภายในในแอปภายนอก

บทสรุป

ในบทความนี้เราพูดถึงวิธีต่างๆ ที่นักพัฒนาแอปสามารถสร้าง Progressive Web App หลายรายการให้สัมพันธ์กันภายในโดเมนเดียวกัน

โดยสรุป เราขอแนะนำให้ใช้ต้นทางอื่น (เช่น โดยใช้โดเมนย่อย) เพื่อโฮสต์ PWA อิสระ การโฮสต์แอปเหล่านี้ในแหล่งที่มาเดียวกันจะทำให้เกิดปัญหาหลายประการ สาเหตุหลักคือเบราว์เซอร์จะไม่ถือว่าแอปเหล่านี้เป็นแอปที่แตกต่างกันอย่างสมบูรณ์

  • แยกต้นทาง: แนะนํา
  • ต้นทางเดียวกัน เส้นทางไม่ทับซ้อนกัน: ไม่แนะนำ
  • เส้นทางที่มีต้นทางเดียวกัน ทับซ้อนกัน/ซ้อนกัน: ไม่แนะนำ

หากใช้ต้นทางอื่นไม่ได้ เราขอแนะนําอย่างยิ่งให้ใช้เส้นทางที่ไม่ทับซ้อนกัน (เช่น https://example.com/app1/ และ https://example.com/app2/) แทนการใช้เส้นทางที่ทับซ้อนกันหรือซ้อนกัน เช่น https://example.com/ (สําหรับแอปด้านนอก) และ https://example.com/app/ (สําหรับแอปด้านใน)

แหล่งข้อมูลเพิ่มเติม

ขอขอบคุณอย่างยิ่งสำหรับรีวิวและคำแนะนำทางเทคนิค: Joe Medley, Dominick Ng, Alan Cutter, Daniel Murphy, Penny McLachlan, Thomas Steiner และ Darwin Huang

รูปภาพโดย Tim Mossholder จาก Unsplash