Goodnote ได้ทุกที่

รูปภาพการตลาดของ Goodnotes แสดงภาพผู้หญิงกำลังใช้ผลิตภัณฑ์บน iPad

ในช่วง 2 ปีที่ผ่านมา ทีมวิศวกรของ Goodnotes ได้ทำงานในโครงการหนึ่งเพื่อนำแอปจดโน้ตของ iPad ที่ประสบความสำเร็จ ไปใช้ในแพลตฟอร์มอื่นๆ กรณีศึกษานี้ครอบคลุมวิธีที่แอป iPad ในปี 2022 ของปีนี้นำเทคโนโลยีเว็บ, ChromeOS, Android และ Windows ที่ขับเคลื่อนโดยเทคโนโลยีเว็บ และ WebAssembly นำโค้ด Swift เดิมที่ทีมพัฒนามาปรับใช้ซ้ำมาเป็นเวลากว่า 10 ปี

โลโก้ Goodnotes

ในปี 2021 Goodnotes มีให้บริการในรูปแบบแอปสำหรับ iOS และ iPad เท่านั้น ทีมวิศวกรของ Goodnotes ยอมรับความท้าทายทางเทคนิคที่ยิ่งใหญ่ นั่นคือการสร้าง Goodnotes เวอร์ชันใหม่ แต่สำหรับระบบปฏิบัติการและแพลตฟอร์มอื่นๆ เพิ่มเติม ผลิตภัณฑ์ควรเข้ากันได้อย่างสมบูรณ์และแสดงโน้ตเดียวกันกับแอปพลิเคชัน iOS หมายเหตุที่เขียนบน PDF หรือรูปภาพที่แนบมาควรเทียบเท่ากัน และแสดงเส้นโครงร่างเดียวกับที่แอป iOS แสดง เส้นที่เพิ่มเข้าไปควรเท่ากับรูปแบบที่ผู้ใช้ iOS สร้างได้ โดยไม่เกี่ยวข้องกับเครื่องมือที่ผู้ใช้ใช้อยู่ เช่น ปากกา ปากกาไฮไลต์ ปากกาหมึกซึม รูปร่าง หรือยางลบ

ตัวอย่างแอป Goodnotes พร้อมโน้ตและภาพร่างที่เขียนด้วยลายมือ

จากข้อกำหนดและประสบการณ์ของทีมวิศวกร ทีมงานได้ข้อสรุปสั้นๆ ว่าการใช้โค้ดเบสของ Swift ซ้ำจะเป็นวิธีที่ดีที่สุด เนื่องจากมีการเขียนไว้แล้วและได้รับการทดสอบอย่างดีมาหลายปีแล้ว แต่ทำไมไม่ย้ายแอปพลิเคชัน iOS/iPad ที่มีอยู่แล้วไปยังแพลตฟอร์มอื่น หรือเทคโนโลยีอื่นอย่าง Flutter หรือ Compose Multiplatform ล่ะ การย้ายไปยังแพลตฟอร์มใหม่ จะต้องมีการเขียน Goodnote ใหม่ การกระทำดังกล่าวอาจส่งผลให้เกิดการแข่งขันระหว่างการพัฒนาระหว่างแอปพลิเคชัน iOS ที่มีการใช้งานอยู่แล้วกับแอปพลิเคชันที่จะสร้างขึ้นจากแอปพลิเคชันใหม่ 0 รายการ หรืออาจต้องหยุดการพัฒนาใหม่ในแอปพลิเคชันเดิมในขณะที่โค้ดเบสใหม่เกิดขึ้น หาก Goodnotes นำโค้ด Swift มาใช้ซ้ำได้ ทีม iOS ก็จะได้ประโยชน์จากฟีเจอร์ใหม่ๆ ที่ทีม iOS นำมาใช้ ในขณะที่ทีมข้ามแพลตฟอร์มกำลังทำงานเกี่ยวกับหลักการพื้นฐานของแอปและความเท่าเทียมกันของฟีเจอร์การเข้าถึง

ผลิตภัณฑ์นี้แก้ปัญหาท้าทายที่น่าสนใจสำหรับ iOS ได้หลายอย่างในการเพิ่มฟีเจอร์ เช่น

  • การแสดงภาพโน้ต
  • การซิงค์เอกสารและโน้ต
  • การแก้ไขความขัดแย้งสำหรับโน้ตโดยใช้ประเภทข้อมูลจำลองที่ปราศจากข้อขัดแย้ง
  • การวิเคราะห์ข้อมูลสำหรับการประเมินโมเดล AI
  • การค้นหาเนื้อหาและการจัดทำดัชนีเอกสาร
  • ประสบการณ์การเลื่อนและภาพเคลื่อนไหวที่กําหนดเอง
  • ดูการใช้งานโมเดลสำหรับเลเยอร์ UI ทั้งหมด

ทั้งหมดนี้จะง่ายกว่าหากนำไปใช้กับแพลตฟอร์มอื่น หากทีมวิศวกรสามารถทำให้โค้ดเบสของ iOS ที่ทำงานสำหรับแอปพลิเคชัน iOS และ iPad ใช้งานได้อยู่แล้ว และนำไปใช้งานเป็นส่วนหนึ่งของโปรเจ็กต์ที่ Goodnotes สามารถให้บริการในรูปแบบ Windows, Android หรือเว็บแอปพลิเคชัน

ชุดซอฟต์แวร์โครงสร้างพื้นฐานของ Goodnotes

อย่างไรก็ตาม มีวิธีใช้โค้ด Swift ที่มีอยู่บนเว็บอีกครั้ง ซึ่งก็คือ WebAssembly (Wasm) Goodnotes สร้างต้นแบบโดยใช้ Wasm กับโปรเจ็กต์โอเพนซอร์สและโปรเจ็กต์ SwiftWasm ที่ดูแลโดยชุมชน ทีม Goodnotes ของ SwiftWasm สามารถสร้างไบนารี Wasm ด้วยโค้ด Swift ทั้งหมดที่ใช้ไปแล้ว ไบนารีนี้อาจรวมอยู่ในหน้าเว็บที่จัดส่งเป็นเว็บแอปพลิเคชันแบบโปรเกรสซีฟสำหรับ Android, Windows, ChromeOS และระบบปฏิบัติการอื่นๆ ทั้งหมด

ลำดับการเปิดตัวของ Goodnote จะขึ้นต้นด้วย Chrome ตามด้วย Windows ตามด้วย Android และแพลตฟอร์มอื่นๆ เช่น Linux ในตอนท้าย ทั้งหมดจะอิงตาม PWA

เป้าหมายคือการเผยแพร่ Goodnotes ในแบบ PWA และแสดงได้ใน App Store ทุกแพลตฟอร์ม นอกเหนือจาก Swift ภาษาโปรแกรมที่ใช้กับ iOS อยู่แล้ว และ WebAssembly ที่ใช้เพื่อเรียกใช้โค้ด Swift บนเว็บ โปรเจ็กต์นี้ใช้เทคโนโลยีต่อไปนี้

  • TypeScript: ภาษาโปรแกรมที่ใช้บ่อยที่สุดสำหรับเทคโนโลยีเว็บ
  • React และ Webpack: เฟรมเวิร์กและ Bundler ที่ได้รับความนิยมสูงสุดสำหรับเว็บ
  • PWA และ Service Worker: ปัจจัยขับเคลื่อนขนาดใหญ่สำหรับโปรเจ็กต์นี้ เนื่องจากทีมสามารถจัดส่งแอปของเราเป็นแอปพลิเคชันออฟไลน์ที่ทำงานเหมือนกับแอป iOS อื่นๆ และคุณจะติดตั้งจาก Store หรือเบราว์เซอร์เองก็ได้
  • PWABuilder: โปรเจ็กต์หลัก Goodnotes จะใช้เพื่อรวม PWA เป็นไบนารี Windows เพื่อให้ทีมสามารถเผยแพร่แอปของเราจาก Microsoft Store ได้
  • กิจกรรมบนเว็บที่เชื่อถือได้: เทคโนโลยี Android ที่สำคัญที่สุดที่บริษัทใช้เพื่อเผยแพร่ PWA เป็นแอปพลิเคชันที่มาพร้อมเครื่อง

ชุดซอฟต์แวร์โครงสร้างพื้นฐานของ Goodnotes ประกอบด้วย Swift, Wasm, React และ PWA

ภาพต่อไปนี้แสดงการใช้งานที่ใช้ TypeScript และ React แบบดั้งเดิม ส่วนสิ่งที่ใช้งานโดย SwiftWasm และ Vanilla JavaScript, Swift และ WebAssembly โปรเจ็กต์นี้ใช้ JSKit ซึ่งเป็นไลบรารีความสามารถในการทำงานร่วมกันของ JavaScript สำหรับ Swift และ WebAssembly ที่ทีมใช้เพื่อจัดการ DOM ในหน้าจอเครื่องมือแก้ไขจากโค้ด Swift ของเราเมื่อจำเป็น หรืออาจใช้ API เฉพาะเบราว์เซอร์ก็ได้

ภาพหน้าจอของแอปบนอุปกรณ์เคลื่อนที่และเดสก์ท็อปแสดงพื้นที่ภาพวาดที่ Wasm ขับเคลื่อน และพื้นที่ UI ที่ขับเคลื่อนโดย React

ทำไมต้องใช้ Wasm และเว็บ

แม้ว่า Apple จะไม่รองรับ Wasm อย่างเป็นทางการ แต่ทีมวิศวกรของ Goodnotes ด้วยเหตุผลต่อไปนี้

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

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

การพัฒนาผลิตภัณฑ์ซ้ำ

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

ภาพหน้าจอแอป 2 ภาพเป็นสัญลักษณ์ว่าออกจากแบบอ่านอย่างเดียวไปเป็นไอเทมแนะนําเต็มรูปแบบ

เวอร์ชันแรกของผลิตภัณฑ์แบบอ่านอย่างเดียวใช้เวลาพัฒนา 6 เดือน อีก 9 เดือนต่อมาก็ทุ่มเทให้กับฟีเจอร์การแก้ไขชุดแรกและหน้าจอ UI ที่คุณสามารถตรวจสอบเอกสารทั้งหมดที่คุณสร้างหรือเมื่อมีคนแชร์กับคุณ นอกจากนี้ ฟีเจอร์ใหม่ๆ ของแพลตฟอร์ม iOS ก็ย้าย ไปยังโปรเจ็กต์ข้ามแพลตฟอร์มได้โดยง่ายด้วย SwiftWasm Toolchain อย่างเช่น ปากกาประเภทใหม่สร้างขึ้นและนำไปใช้ข้ามแพลตฟอร์มได้อย่างง่ายดายโดยใช้โค้ดหลายพันบรรทัดซ้ำ

การสร้างโปรเจ็กต์นี้เป็นประสบการณ์ที่น่าทึ่ง และ Goodnotes ก็ได้เรียนรู้สิ่งต่างๆ มากมาย ส่วนต่อไปนี้จะเน้นประเด็นทางเทคนิคที่น่าสนใจเกี่ยวกับการพัฒนาเว็บ รวมถึงการใช้ WebAssembly และภาษาต่างๆ เช่น Swift

อุปสรรคเริ่มแรก

การทำโปรเจ็กต์นี้จากหลายมุมมองมีความท้าทายอย่างมาก อุปสรรคแรกที่ทีมพบเกี่ยวข้องกับห่วงโซ่เครื่องมือ SwiftWasm เชนเครื่องมือเป็นเครื่องมือสำคัญที่ช่วยทีม แต่โค้ด iOS บางอย่างก็ใช้งานร่วมกับ Wasm ไม่ได้ ตัวอย่างเช่น โค้ดที่เกี่ยวข้องกับ IO หรือ UI เช่น การใช้งานข้อมูลพร็อพเพอร์ตี้ ไคลเอ็นต์ API หรือการเข้าถึงฐานข้อมูลไม่สามารถนำมาใช้ใหม่ได้ ทีมจึงต้องเริ่มเปลี่ยนโครงสร้างส่วนที่เฉพาะเจาะจงของแอปเพื่อให้สามารถใช้ซ้ำจากโซลูชันข้ามแพลตฟอร์มได้ PR ส่วนใหญ่ที่ทีมสร้างขึ้นเป็นแบบเปลี่ยนโครงสร้างเป็นทรัพยากร Dependency แบบแอบสแตรกต์ เพื่อให้ทีมแทนที่ทีมดังกล่าวในภายหลังได้โดยใช้การแทรกทรัพยากร Dependency หรือกลยุทธ์อื่นๆ ที่คล้ายกัน เดิมโค้ด iOS ผสมผสานตรรกะทางธุรกิจดิบที่สามารถติดตั้งใช้งานใน Wasm ได้ด้วยโค้ดที่รับผิดชอบอินพุต/เอาต์พุตและอินเทอร์เฟซผู้ใช้ซึ่งใช้งานใน Wasm ไม่ได้ เนื่องจาก Wasm ไม่รองรับ จึงต้องติดตั้งใช้งานโค้ด IO และ UI ใน TypeScript อีกครั้งเมื่อตรรกะทางธุรกิจของ Swift พร้อมนํามาใช้ซ้ำระหว่างแพลตฟอร์มต่างๆ

แก้ปัญหาด้านประสิทธิภาพแล้ว

เมื่อ Goodnotes เริ่มทำงานสำหรับบรรณาธิการ ทีมพบว่าประสบการณ์การตัดต่อและความท้าทายทางเทคโนโลยีได้กลายเป็นแผนกลยุทธ์ของเรา ปัญหาแรกเกี่ยวข้องกับประสิทธิภาพ JavaScript เป็น ภาษาแบบชุดข้อความเดียว ซึ่งหมายความว่าจะมีสแต็กการเรียกใช้ 1 รายการและหน่วยความจำฮีพ 1 หน่วย โดยจะเรียกใช้โค้ดตามลำดับและต้องเรียกใช้โค้ดชิ้นใดชิ้นหนึ่งให้เสร็จสิ้นก่อนที่จะไปยังหน้าถัดไป กรณีนี้เกิดขึ้นพร้อมกัน แต่บางครั้งก็อาจเป็นอันตรายได้ ตัวอย่างเช่น หากฟังก์ชันใช้เวลาสักพักหนึ่งเพื่อดำเนินการหรือต้องรอบางสิ่งบางอย่าง ฟังก์ชันจะหยุดทุกอย่างในระหว่างนั้น และนี่คือสิ่งที่วิศวกรต้องแก้ไข การประเมินเส้นทางบางเส้นทางในฐานของโค้ดที่เกี่ยวข้องกับเลเยอร์การแสดงผลหรืออัลกอริทึมที่ซับซ้อนอื่นๆ เป็นปัญหาสำหรับทีม เพราะอัลกอริทึมเหล่านี้ทำงานพร้อมกัน และการดำเนินการไปใช้บล็อกเทรดหลัก ทีม Goodnotes ได้เขียนสคริปต์ใหม่เพื่อทำให้เร็วขึ้น และปรับเปลี่ยนโครงสร้างบางส่วนใหม่เพื่อทำให้เป็นแบบไม่พร้อมกัน นอกจากนี้ พวกเขายังได้เปิดตัวกลยุทธ์ผลตอบแทนเพื่อให้แอปสามารถหยุดการดำเนินการของอัลกอริทึมและดำเนินการต่อในภายหลัง โดยให้เบราว์เซอร์อัปเดต UI และหลีกเลี่ยงการปล่อยเฟรม กรณีนี้ไม่ใช่ปัญหาสำหรับแอปพลิเคชัน iOS เนื่องจากสามารถใช้เทรดและประเมินอัลกอริทึมเหล่านี้ในเบื้องหลังได้ ขณะที่เทรดหลักของ iOS จะอัปเดตอินเทอร์เฟซผู้ใช้

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

ทีมวิศวกรระบุว่าการเปลี่ยนแปลงต่อไปนี้ช่วยลดปัญหาที่พบได้ โดยลงมือแก้ไขตั้งแต่เริ่มต้นโครงการ

  • ลดภาระงานของเทรดหลักให้มากขึ้นโดยใช้โปรแกรมทำงานบนเว็บเป็นประจำสำหรับอัลกอริทึมขนาดใหญ่
  • ใช้ฟังก์ชันที่ส่งออกและฟังก์ชันที่นำเข้าแทนไลบรารีการทำงานร่วมกันของ JS-Swift ตั้งแต่เริ่มต้น เพื่อที่จะลดผลกระทบด้านประสิทธิภาพเมื่อออกจากบริบท Wasm ไลบรารีการทำงานร่วมกันของ JavaScript นี้เป็นประโยชน์ในการรับสิทธิ์เข้าถึง DOM หรือเบราว์เซอร์ แต่ช้ากว่าฟังก์ชันที่ส่งออกมาจาก Wasm แบบเนทีฟ
  • ตรวจสอบว่าโค้ดทำให้มีการใช้งาน OffscreenCanvas ขั้นสูงเพื่อให้แอปโหลดเทรดหลักได้และย้ายการใช้งาน Canvas API ทั้งหมดไปยัง Web Worker เพื่อเพิ่มประสิทธิภาพของแอปพลิเคชันเมื่อเขียนบันทึก
  • ย้ายการดำเนินการทั้งหมดที่เกี่ยวข้องกับ Wasm ไปยัง Web Worker หรือแม้กระทั่งกลุ่ม Web Worker เพื่อให้แอปลดภาระงานของเทรดหลักได้

เครื่องมือแก้ไขข้อความ

ปัญหาอื่นที่น่าสนใจเกี่ยวข้องกับเครื่องมือหนึ่งอย่างเครื่องมือแก้ไขข้อความ การใช้งาน iOS สำหรับเครื่องมือนี้อิงตาม NSAttributedString ซึ่งเป็นชุดเครื่องมือขนาดเล็กที่ใช้ RTF ในตัว อย่างไรก็ตาม การติดตั้งใช้งานนี้ใช้ไม่ได้กับ SwiftWasm ระบบจึงต้องบังคับให้ทีมข้ามแพลตฟอร์มสร้างโปรแกรมแยกวิเคราะห์ที่กำหนดเองตามไวยากรณ์ RTF ก่อน จากนั้นจึงนำประสบการณ์การแก้ไขไปใช้โดยการแปลง RTF เป็น HTML และในทางกลับกัน ในขณะเดียวกัน ทีม iOS ก็เริ่มติดตั้งใช้งานใหม่ให้กับเครื่องมือนี้แทนการใช้งาน RTF ด้วยโมเดลที่กำหนดเอง เพื่อให้แอปนำเสนอข้อความที่มีการจัดรูปแบบได้อย่างเป็นมิตรในทุกแพลตฟอร์มที่ใช้โค้ด Swft เดียวกัน

เครื่องมือแก้ไขข้อความของ Goodnotes

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

การเผยแพร่ซ้ำ

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

งานออฟไลน์

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

แอป Goodnotes ทำงานแบบออฟไลน์ได้

ยิ่งไปกว่านั้น การเปิดเว็บแอป Goodnotes ทำให้มีค่าใช้จ่ายในการดาวน์โหลดล่วงหน้าเบื้องต้นประมาณ 40 MB เนื่องจากขนาดไบนารีของ Wasm ในช่วงแรก ทีม Goodnotes อาศัยแคชของเบราว์เซอร์ทั่วไปสำหรับ App Bundle และปลายทาง API ส่วนใหญ่ที่ใช้กันเป็นหลัก แต่เมื่อมองย้อนกลับไปก็อาจได้รับประโยชน์จาก Cache API และ Service Worker ที่เชื่อถือได้มากกว่า เดิมทีมได้แยกตัวออกจากงานนี้เพราะคิดว่างานมีความซับซ้อน แต่ในท้ายที่สุด พบว่า Workbox ทำให้การทำงานน่ากลัวน้อยลงมาก

คําแนะนําเมื่อใช้ Swift บนเว็บ

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

  • ตรวจสอบรหัสที่คุณต้องการใช้ซ้ำ หากนำตรรกะทางธุรกิจของแอปมาใช้ในฝั่งเซิร์ฟเวอร์ ก็น่าจะขอแนะนำให้คุณนำโค้ด UI มาใช้ซ้ำ แต่ Wasm จะไม่ช่วยแก้ปัญหาในส่วนนี้ ทีมได้ศึกษา Tokamak ซึ่งเป็นเฟรมเวิร์กที่ใช้ร่วมกับ SwiftUI ได้เป็นระยะเวลาสั้นๆ ในการสร้างแอปเบราว์เซอร์ด้วย WebAssembly แต่ก็ยังทำงานได้ไม่หลากหลายมากพอ แต่หากแอปมีตรรกะทางธุรกิจหรืออัลกอริทึมที่รัดกุมซึ่งนำมาใช้เป็นส่วนหนึ่งของรหัสไคลเอ็นต์ Wasm จะเป็นเพื่อนที่ดีที่สุดของคุณ
  • ตรวจสอบว่าฐานของโค้ด Swift พร้อมแล้ว รูปแบบการออกแบบซอฟต์แวร์สำหรับเลเยอร์ UI หรือสถาปัตยกรรมที่เฉพาะเจาะจงซึ่งสร้างการแยกที่ชัดเจนระหว่างตรรกะ UI กับตรรกะทางธุรกิจของคุณจะมีประโยชน์อย่างมาก เพราะคุณจะไม่สามารถนำการติดตั้งเลเยอร์ UI มาใช้ซ้ำได้ สถาปัตยกรรมสะอาดหรือหลักการสถาปัตยกรรมหกเหลี่ยมก็ถือเป็นรากฐานเช่นกัน เนื่องจากคุณจะต้องแทรกโค้ดที่เกี่ยวข้องกับ IO ทั้งหมดและขึ้นต่อกัน รวมทั้งจะง่ายขึ้นหากคุณทำตามสถาปัตยกรรมเหล่านี้ซึ่งกำหนดให้รายละเอียดการใช้งานเป็นนามธรรมและมีการใช้หลักการการกลับขึ้นบรรทัดใหม่อย่างมาก
  • Wasm ไม่มีรหัส UI ดังนั้นคุณจึงควรตัดสินใจเกี่ยวกับ กรอบการทำงาน UI ที่ต้องการใช้สำหรับเว็บ
  • JSKit จะช่วยคุณผสานรวมโค้ด Swift กับ JavaScript แต่โปรดทราบว่าหากคุณมี Hotpath การข้ามบริดจ์ JS–Swift อาจมีค่าใช้จ่ายสูงและคุณจะต้องเปลี่ยนไปใช้ฟังก์ชันที่ส่งออกแทน คุณสามารถดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทํางานภายในของ JSKit ได้ในเอกสารอย่างเป็นทางการ และโพสต์การค้นหาสมาชิกแบบไดนามิกใน Swift ซึ่งเป็นเครื่องมือลับ
  • คุณจะนำสถาปัตยกรรมกลับมาใช้ใหม่ได้หรือไม่นั้นจะขึ้นอยู่กับสถาปัตยกรรมที่แอปใช้และไลบรารีกลไกการดำเนินการโค้ดแบบไม่พร้อมกันที่คุณใช้ รูปแบบ เช่น MVVP หรือ สถาปัตยกรรม Composable จะช่วยให้คุณนำโมเดลมุมมองและส่วนหนึ่งของ ตรรกะ UI มาใช้ซ้ำได้โดยไม่ต้องเชื่อมโยงกับทรัพยากร Dependency ของ UIKit ที่ ไม่สามารถใช้กับ Wasm ได้ RXSwift และไลบรารีอื่นๆ อาจใช้งานกับ Wasm ไม่ได้ คุณจึงควรคำนึงถึงเรื่องนี้เสมอเพราะจะต้องใช้ OpenCombine, ไม่ซิงค์/รอ และสตรีมในโค้ด Swift ของ Goodnotes
  • บีบอัดไบนารี Wasm โดยใช้ gzip หรือ Brotli โปรดทราบว่าขนาดของไบนารีนั้นค่อนข้างใหญ่สำหรับเว็บแอปพลิเคชันแบบคลาสสิก
  • แม้คุณจะใช้ Wasm โดยไม่มี PWA ก็ได้ แต่อย่างน้อยคุณต้องใส่ Service Worker ไว้ แม้ว่าเว็บแอปจะไม่มีไฟล์ Manifest หรือคุณไม่ต้องการให้ผู้ใช้ติดตั้งก็ตาม Service Worker จะบันทึกและแสดงไบนารี Wasm ฟรี รวมถึงทรัพยากรแอปทั้งหมดเพื่อให้ผู้ใช้ไม่ต้องดาวน์โหลดทุกครั้งที่เปิดโปรเจ็กต์
  • โปรดทราบว่าการจ้างงานอาจยากกว่าที่คาดไว้ คุณอาจต้องจ้างนักพัฒนาซอฟต์แวร์เว็บที่แข็งแกร่งที่มีประสบการณ์กับ Swift หรือนักพัฒนา Swift ที่มีประสบการณ์บางส่วนบนเว็บ ถ้ามีวิศวกรทั่วไปที่มีความรู้ ในทั้ง 2 แพลตฟอร์มก็จะดีมากเลย

บทสรุป

การสร้างโปรเจ็กต์เว็บโดยใช้ชุดซอฟต์แวร์โครงสร้างพื้นฐานที่ซับซ้อนในขณะที่สร้างปัญหาที่ท้าทายนั้นเต็มไปด้วยความท้าทายถือเป็นประสบการณ์ที่น่าทึ่ง อาจจะทำได้ยาก แต่ก็คุ้มค่าแน่นอน Goodnotes ไม่ได้เผยแพร่เวอร์ชันสำหรับ Windows, Android, ChromeOS และเว็บในขณะที่พัฒนาฟีเจอร์ใหม่ๆ สำหรับแอปพลิเคชัน iOS แม้จะไม่ได้ใช้วิธีนี้ก็ตาม ด้วยชุดซอฟต์แวร์โครงสร้างพื้นฐานนี้และทีมวิศวกรของ Goodnotes ทำให้ตอนนี้ Goodnotes ได้ทุกที่ และทีมงานก็พร้อมรับมือความท้าทายต่อไปแล้ว หากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์นี้ โปรด ดูพูดคุยกับทีม Goodnotes ที่มอบให้ในงาน NS Spain 2023 อย่าลืมลองใช้ Goodnote สำหรับเว็บ