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

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

Chase Phillips
Demián Renzulli
Demián Renzulli
Matt Giuca
Matt Giuca

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

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

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

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

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

ในโพสต์นี้ เราจะมาดูกรณีตรงกันข้ามกัน นั่นคือแทนที่จะเป็น PWA เดียว ในต้นทางต่างๆ เราจะวิเคราะห์กรณีของบริษัทที่ต้องการ ให้บริการ 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 รายการที่แยกกันโดยใช้ชื่อโดเมนเดียวกันเพื่อสร้างความสัมพันธ์ระหว่างแอปเหล่านั้น

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

แนวทางที่แนะนําในกรณีเช่นนี้คือให้แต่ละแอปที่แตกต่างกันในเชิงแนวคิด ทํางานในต้นทางของตัวเอง

หากต้องการใช้ชื่อโดเมนเดียวกันในทุกเว็บไซต์ คุณสามารถทำได้โดย ใช้โดเมนย่อย ตัวอย่างเช่น บริษัทที่ให้บริการแอปหรือ บริการอินเทอร์เน็ตหลายอย่างสามารถโฮสต์แอปอีเมลที่ 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 ของตัวเองสำหรับขอบเขตที่ลงทะเบียน ไว้
  • สิทธิ์: สิทธิ์ยังกำหนดขอบเขตตามต้นทางด้วย ด้วยเหตุนี้ ผู้ใช้จึง ทราบได้อย่างชัดเจนว่าตนให้สิทธิ์แก่บริการใด และ ระบบจะระบุแหล่งที่มาของฟีเจอร์ต่างๆ เช่น การแจ้งเตือน ให้กับแต่ละแอปอย่างถูกต้อง

การสร้างระดับการแยกดังกล่าวเป็นสิ่งที่พึงประสงค์มากที่สุดในกรณีการใช้งาน 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 ช่วยให้คุณทำอย่างใดอย่างหนึ่งข้างต้นได้ โดยใช้การกำหนดขอบเขตระดับเส้นทาง อย่างไรก็ตาม ในทั้ง 2 กรณี การใช้ต้นทางเดียวกันจะทำให้เกิดปัญหาและข้อจำกัดมากมาย ซึ่งมีสาเหตุมาจากข้อเท็จจริงที่ว่าเบราว์เซอร์จะไม่ถือว่าสิ่งเหล่านี้เป็น "แอป" ที่แตกต่างกันอย่างแท้จริง ดังนั้นเราจึงไม่แนะนำให้ใช้วิธีนี้

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

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

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

ปัญหาที่พบบ่อยในการใช้งานจริงของทั้ง 2 วิธีการแบบโดเมนเดียวกันมีดังนี้

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

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

ดังที่กล่าวไปแล้ว ความท้าทายที่กล่าวถึงในส่วนนี้เป็นความท้าทายที่พบได้ทั่วไปในทั้ง 2 วิธีการแบบ Same-Origin ในส่วนถัดไป เราจะเจาะลึกรายละเอียด ว่าเหตุใดการใช้เส้นทางที่ทับซ้อนกัน/ซ้อนกันจึงเป็นกลยุทธ์ที่แนะนําน้อยที่สุด

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

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

ในทางปฏิบัติ ปัญหานี้ทำให้เกิดปัญหาต่อไปนี้

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

บทสรุป

ในบทความนี้ เราได้ดูวิธีต่างๆ ที่นักพัฒนาแอปสามารถสร้าง 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