นากสีเขียวต้นฉบับกำลังเทียบเฟือง JavaScript กับเฟือง native สองฝั่งบนโต๊ะสว่าง โดยมีชิ้นหนึ่งเหลื่อมกันชัดเจน

ReactNativeVersion: แยกเวอร์ชัน JavaScript ออกจาก Native ให้ชัด

พี่โชว์Engineering

เวลาแอป React Native อัปเดต JavaScript bundle ผ่านระบบ OTA แต่ binary native ในเครื่องผู้ใช้ยังเป็นรุ่นเดิม อาการผิดปกติอาจโผล่เฉพาะบางเครื่องครับ การบันทึกคำว่า “React Native 0.87” ค่าเดียวจึงเหมือนจดรุ่นเครื่องยนต์ แต่ไม่จดว่าเกียร์ที่ประกอบอยู่เป็นรุ่นไหน

เอกสาร ReactNativeVersion ที่อัปเดต 10 กันยายน 2026 เพิ่มมุมมองฝั่งแพ็กเกจ JavaScript โดยตรง ต่างจาก Platform.constants.reactNativeVersion ซึ่งเป็นเวอร์ชันที่ native platform รายงาน การมีสองค่าช่วยให้เราเห็น drift แทนที่จะเดาจาก stack trace

WHY: เวอร์ชันเดียวอธิบายระบบสองชั้นไม่ได้

React Native app มีอย่างน้อยสองชั้นที่เดินคนละจังหวะ: npm package และ bundle ฝั่ง JavaScript กับ iOS/Android binary ที่คอมไพล์ native module มาแล้ว หาก JS เรียก API ที่ binary เก่ายังไม่มี การเช็กเพียงเวอร์ชัน package ตอน build ไม่บอกสภาพจริงบนอุปกรณ์

แนวทางที่ปลอดภัยคือส่งทั้งสองค่าเข้า telemetry พร้อม app build number และ OTA bundle identifier จากนั้นแจ้งเตือนเมื่อ major/minor ต่างกันนอกคู่ที่ทีมรับรอง อย่าใช้ตัวเลขนี้เปิดฟีเจอร์สำคัญเพียงลำพัง เพราะ library บางตัวมี capability check ที่ตรงกว่า

ตัวอย่างต่อไปนี้เป็น React Native fragment ที่ตรวจ syntax และชื่อ API เทียบเอกสารทางการแล้ว แต่ไม่ได้รันบน simulator หรืออุปกรณ์จริง

import {Platform, ReactNativeVersion} from 'react-native';

export function collectRuntimeVersions() {
  const nativeVersion = Platform.constants.reactNativeVersion;
  const packageVersion = ReactNativeVersion.getVersionString();

  return {
    packageVersion,
    packageParts: {
      major: ReactNativeVersion.major,
      minor: ReactNativeVersion.minor,
      patch: ReactNativeVersion.patch,
      prerelease: ReactNativeVersion.prerelease,
    },
    nativeVersion,
  };
}

HOW: เปลี่ยนข้อมูลให้เป็นสัญญา rollout

เริ่มจาก dashboard แยกตาม OS, app build และ bundle version แล้วดูคู่เวอร์ชันที่เกิดจริงหนึ่งสัปดาห์ กำหนด allowlist ของคู่ที่ผ่าน integration test เช่น JS 0.87.1 กับ native 0.87.x อย่าปิดแอปทันทีเมื่อไม่ตรง เพราะผู้ใช้อาจอยู่ในช่วงดาวน์โหลด update ควรลดความสามารถเฉพาะส่วนที่ต้องพึ่ง native API ใหม่และบันทึกเหตุผล

ถ้า library ต้องรองรับหลายรุ่น ให้ตรวจ property หรือ native module ที่ต้องใช้ก่อน แล้วใช้ ReactNativeVersion เป็นข้อมูลประกอบและข้อความวินิจฉัย การเปรียบเทียบ string ตรง ๆ อาจผิดเมื่อมี prerelease; แยก major, minor, patch หรือใช้ semver parser ที่ทีมทดสอบแล้ว

Recap

  • เก็บเวอร์ชัน package และ native แยกกัน
  • ผูกค่าเหล่านั้นกับ app build และ OTA bundle
  • ใช้ capability check ก่อน version gate
  • ทำ allowlist จากคู่เวอร์ชันที่ทดสอบจริง
  • เฝ้าดู drift ก่อนเปิด rollout เต็มกลุ่ม

พรุ่งนี้ลองเพิ่มสองค่านี้ใน crash breadcrumb หนึ่งจุด แล้วดูว่า incident เก่าตอบได้เร็วขึ้นหรือไม่ครับ