เรียนรู้วิธีใช้ฟีเจอร์ล่าสุดของ WebAssembly พร้อมรองรับผู้ใช้ในทุกเบราว์เซอร์
WebAssembly 1.0 เปิดตัวเมื่อ 4 ปีที่แล้ว แต่การพัฒนาไม่ได้หยุดอยู่แค่นั้น ระบบจะเพิ่มฟีเจอร์ใหม่ๆ ผ่านกระบวนการกำหนดมาตรฐานข้อเสนอ ลำดับการติดตั้งใช้งานและลำดับเวลาอาจแตกต่างกันไปสำหรับเครื่องมือค้นหาที่ต่างกัน เช่นเดียวกับกรณีของฟีเจอร์ใหม่ในเว็บ หากต้องการใช้ฟีเจอร์ใหม่ดังกล่าว คุณต้องตรวจสอบว่าไม่มีผู้ใช้ถูกละเลย ในบทความนี้ คุณจะได้ทราบแนวทางในการบรรลุเป้าหมายนี้
ฟีเจอร์ใหม่บางอย่างจะปรับปรุงขนาดโค้ดด้วยการเพิ่มวิธีการใหม่ๆ สำหรับการดำเนินการทั่วไป บางอย่างเพิ่มฟังก์ชันการทำงานดั้งเดิมที่มีประสิทธิภาพ และบางอย่างปรับปรุงประสบการณ์ของนักพัฒนาซอฟต์แวร์และการผสานรวมกับเว็บอื่นๆ
คุณดูรายการข้อเสนอทั้งหมดและขั้นตอนต่างๆ ในที่เก็บอย่างเป็นทางการหรือติดตามสถานะการติดตั้งใช้งานในเครื่องมือได้ในหน้าแผนกลยุทธ์สำหรับฟีเจอร์อย่างเป็นทางการ
เพื่อให้แน่ใจว่าผู้ใช้ทุกเบราว์เซอร์จะสามารถใช้แอปพลิเคชันของคุณได้ คุณต้องตัดสินใจว่าจะใช้ฟีเจอร์ใด จากนั้นจึงแบ่งกลุ่มตามการรองรับเบราว์เซอร์ จากนั้นคอมไพล์ฐานของโค้ดสำหรับแต่ละกลุ่มแยกกัน สุดท้าย ทางฝั่งเบราว์เซอร์ คุณจะต้องตรวจหาฟีเจอร์ที่รองรับและโหลดแพ็กเกจ JavaScript และ Wasm ที่เกี่ยวข้อง
ฟีเจอร์การเลือกและการจัดกลุ่ม
ลองดูขั้นตอนเหล่านั้นโดยเลือกชุดฟีเจอร์ที่ต้องการเป็นตัวอย่าง สมมติว่าฉันระบุว่าฉันต้องการใช้ SIMD, ชุดข้อความ และการจัดการข้อยกเว้นในไลบรารีด้วยเหตุผลด้านขนาดและประสิทธิภาพ การรองรับเบราว์เซอร์มีดังนี้
คุณสามารถแบ่งเบราว์เซอร์ออกเป็นกลุ่มประชากรตามรุ่นต่อไปนี้ได้เพื่อให้ผู้ใช้แต่ละรายได้รับประสบการณ์การใช้งานที่ดีที่สุด
- เบราว์เซอร์แบบ Chrome: รองรับเทรด, SIMD และการจัดการข้อยกเว้นทั้งหมด
- Firefox: รองรับเทรดและ SIMD แต่ไม่มีการจัดการข้อยกเว้น
- Safari: รองรับเทรด แต่จะไม่รองรับ SIMD และการจัดการข้อยกเว้น
- เบราว์เซอร์อื่นๆ: สมมติเฉพาะการรองรับ WebAssembly พื้นฐานเท่านั้น
รายละเอียดนี้จะแยกตามการสนับสนุนฟีเจอร์ในเวอร์ชันล่าสุดของแต่ละเบราว์เซอร์ เบราว์เซอร์ที่ทันสมัยเป็นเบราว์เซอร์ที่ใช้ได้ตลอดและอัปเดตอัตโนมัติ ดังนั้นในกรณีส่วนใหญ่ คุณเพียงแค่ต้องกังวลเรื่องรุ่นล่าสุดเท่านั้น อย่างไรก็ตาม ตราบใดที่คุณรวม WebAssembly พื้นฐานไว้เป็นกลุ่มประชากรตามรุ่นสำรอง คุณจะยังคงให้บริการแอปพลิเคชันที่ใช้งานได้แม้ว่าผู้ใช้ที่มีเบราว์เซอร์ที่ล้าสมัย
การรวบรวมฟีเจอร์สำหรับชุดฟีเจอร์ต่างๆ
WebAssembly ไม่มีวิธีในตัวสำหรับตรวจหาฟีเจอร์ที่รองรับในรันไทม์ จึงต้องรองรับคำสั่งทั้งหมดในโมดูลบนเป้าหมาย ด้วยเหตุนี้ คุณจึงต้องคอมไพล์ซอร์สโค้ดลงใน Wasm แยกกันสำหรับชุดฟีเจอร์แต่ละชุด
เชนเครื่องมือและระบบบิลด์แต่ละระบบแตกต่างกัน และคุณต้องศึกษาเอกสารของคอมไพเลอร์เพื่อดูวิธีปรับแต่งฟีเจอร์เหล่านั้น เพื่อให้เข้าใจง่าย ฉันจะใช้ไลบรารี C++ แบบไฟล์เดียวในตัวอย่างต่อไปนี้ และแสดงวิธีคอมไพล์ด้วย Emscripten
ฉันจะใช้ SIMD ผ่านโปรแกรมจำลอง SSE2, ชุดข้อความผ่านการรองรับไลบรารี Pthreads และเลือกระหว่างการจัดการข้อยกเว้น Wasm และการติดตั้งใช้งาน JavaScript สำรอง
# First bundle: threads + SIMD + Wasm exceptions
$ emcc main.cpp -o main.threads-simd-exceptions.mjs -pthread -msimd128 -msse2 -fwasm-exceptions
# Second bundle: threads + SIMD + JS exceptions fallback
$ emcc main.cpp -o main.threads-simd.mjs -pthread -msimd128 -msse2 -fexceptions
# Third bundle: threads + JS exception fallback
$ emcc main.cpp -o main.threads.mjs -pthread -fexceptions
# Fourth bundle: basic Wasm with JS exceptions fallback
$ emcc main.cpp -o main.basic.mjs -fexceptions
ตัวโค้ด C++ เองสามารถใช้ #ifdef __EMSCRIPTEN_PTHREADS__
และ #ifdef __SSE2__
เพื่อเลือกเงื่อนไขการใช้งานระหว่างการใช้งานแบบขนาน (ชุดข้อความและ SIMD) ของฟังก์ชันเดียวกันและการใช้งานซีเรียลในช่วงเวลาคอมไพล์ได้ ซึ่งจะมีลักษณะดังนี้
void process_data(std::vector<int>& some_input) {
#ifdef __EMSCRIPTEN_PTHREADS__
#ifdef __SSE2__
// …implementation using threads and SIMD for max speed
#else
// …implementation using threads but not SIMD
#endif
#else
// …fallback implementation for browsers without those features
#endif
}
การจัดการข้อยกเว้นไม่จำเป็นต้องมีคำสั่ง #ifdef
เนื่องจากสามารถใช้คำสั่งเดียวกันนี้จาก C++ ได้ ไม่ว่าจะเลือกการใช้งานที่จำเป็นผ่านแฟล็กการคอมไพล์หรือไม่ก็ตาม
กำลังโหลดแพ็กเกจที่ถูกต้อง
เมื่อสร้างกลุ่มสำหรับกลุ่มประชากรตามรุ่นฟีเจอร์ทั้งหมดแล้ว คุณต้องโหลดแพ็กเกจที่ถูกต้องจากแอปพลิเคชัน JavaScript หลัก ก่อนอื่น ให้หาฟีเจอร์ที่รองรับในเบราว์เซอร์ปัจจุบัน โดยใช้ไลบรารี wasm-feature-detect เมื่อรวมเข้ากับการนำเข้าแบบไดนามิก คุณจะโหลด Bundle ที่เพิ่มประสิทธิภาพมากที่สุดในเบราว์เซอร์ใดก็ได้ ดังนี้
import { simd, threads, exceptions } from 'https://unpkg.com/wasm-feature-detect?module';
let initModule;
if (await threads()) {
if (await simd()) {
if (await exceptions()) {
initModule = import('./main.threads-simd-exceptions.mjs');
} else {
initModule = import('./main.threads-simd.mjs');
}
} else {
initModule = import('./main.threads.mjs');
}
} else {
initModule = import('./main.basic.mjs');
}
const Module = await initModule();
// now you can use `Module` Emscripten object like you normally would
คำสุดท้าย
ในโพสต์นี้ เราได้แสดงวิธีเลือก สร้าง และสลับระหว่างแพ็กเกจสำหรับชุดฟีเจอร์ต่างๆ
เมื่อฟีเจอร์มีจำนวนเพิ่มขึ้น กลุ่มฟีเจอร์ที่มีมากขึ้นเรื่อยๆ อาจไม่สามารถรักษาได้ เพื่อลดปัญหานี้ คุณสามารถเลือกกลุ่มประชากรตามรุ่นฟีเจอร์ตามข้อมูลผู้ใช้จริง ข้ามเบราว์เซอร์ที่ได้รับความนิยมน้อยกว่า และให้เบราว์เซอร์เหล่านั้นกลับไปใช้กลุ่มประชากรตามรุ่นที่มีประสิทธิภาพน้อยกว่าเล็กน้อยได้ ตราบใดที่แอปพลิเคชันของคุณยังใช้ได้กับผู้ใช้ทุกคน วิธีนี้จะให้ความสมดุลที่สมเหตุสมผลระหว่างการเพิ่มประสิทธิภาพแบบต่อเนื่องและประสิทธิภาพรันไทม์
ในอนาคต WebAssembly อาจมีวิธีที่มีมาในตัวสำหรับตรวจหาฟีเจอร์ที่รองรับและสลับระหว่างการใช้งานฟังก์ชันเดียวกันในโมดูลต่างๆ อย่างไรก็ตาม กลไกดังกล่าวก็เป็นฟีเจอร์หลัง MVP ซึ่งคุณจะต้องตรวจหาและโหลดอย่างมีเงื่อนไขโดยใช้แนวทางข้างต้น ในระหว่างนี้ วิธีนี้ยังคงเป็นวิธีเดียวในการสร้างและโหลดโค้ดโดยใช้ฟีเจอร์ใหม่ของ WebAssembly ในทุกเบราว์เซอร์