EAS Submit iOS: ส่งแอป Expo ขึ้น App Store
โดย Mehdi Azizi
เผยแพร่เมื่อ , 8 นาที
EAS Submit ส่ง build iOS ไปยัง App Store Connect และเข้า TestFlight ส่วนการส่งรีวิวต้องทำเองใน App Store Connect พร้อมไฟล์ eas.json และข้อผิดพลาดที่ควรรู้
eas submit --platform ios จะส่ง build iOS ของคุณไปยัง App Store Connect และ build จะไปโผล่ใน TestFlight หลังจาก Apple ประมวลผลเสร็จ คำสั่งนี้ไม่ได้ส่งแอปของคุณเข้ารีวิวของ Apple: การเลือก build และการส่งเข้ารีวิวยังต้องทำเองใน App Store Connect ถ้าอยากให้ทำงานอัตโนมัติ คำสั่งนี้ต้องใช้หมายเลขหน้าแอปของคุณ (ascAppId) และคีย์ API ของ App Store Connect
ผมเผยแพร่แอป iOS ของผม ซึ่งรวมถึง Solys, TradaZen และ Nolera ด้วย Expo, EAS Build และ EAS Submit คู่มือนี้อ้างอิงเอกสารของ Expo เรื่องการส่งแอป iOS ซึ่งผมอ่านทวนล่าสุดเมื่อวันที่ 25 ตุลาคม 2026 ถ้าคุณไม่มี Mac ขั้นตอนทั้งหมดอยู่ในเผยแพร่แอป iOS โดยไม่ใช้ Mac ในบทความนี้เราจะโฟกัสที่การส่งแอปอย่างเดียว
สิ่งที่ต้องมีก่อนรันคำสั่งแรก
Expo ระบุสิ่งที่ต้องเตรียมไว้สามอย่าง:
- บัญชี Apple Developer แบบเสียเงิน ราคาและวิธีสมัครอยู่ในบัญชีนักพัฒนา Apple
- bundle identifier ใน
ios.bundleIdentifierตามเอกสารอ้างอิงการตั้งค่าของ Expo คุณตั้งเองได้ แต่ต้องไม่ซ้ำกับใครบน App Store - ติดตั้ง EAS CLI แล้วรัน
eas loginด้วยบัญชี Expo ของคุณ
คุณยังต้องมี build สำหรับ production ที่เซ็นแล้วด้วย EAS Build จะสร้างให้โดยใช้ certificate และ profile ที่มันจัดการให้คุณ ตามที่อธิบายไว้ในcertificate และ provisioning profile ของ iOS
หน้าแอปใน App Store Connect: สร้างเองหรือให้ EAS สร้าง?
EAS Submit จะส่งไฟล์ไบนารีไปยังแอปที่ต้องมีอยู่แล้วใน App Store Connect
คุณสร้างเองได้ หน้าช่วยเหลือของ Apple อธิบายหน้าต่าง New App ไว้: แพลตฟอร์ม, ชื่อ, ภาษาหลัก, bundle identifier, SKU และสิทธิ์การเข้าถึงของผู้ใช้ คุณต้องมีบทบาท Account Holder, Admin หรือ App Manager
หรือให้ EAS สร้างให้ตอนส่งครั้งแรกก็ได้ ตามหน้า TestFlight ของ Expo eas submit จะสร้างหน้าแอปให้เมื่อคุณส่ง build แรก และตามเอกสารอ้างอิงของ eas.json ถ้าใส่ ascAppId ไว้ ขั้นตอนนี้จะถูกข้ามไป ชื่อแอปจะมาจาก appName หรือถ้าไม่มีก็ใช้ name จากการตั้งค่าของคุณ ส่วนภาษาหลักมาจาก language ซึ่งค่าเริ่มต้นคือ en-US ถ้าแอปของคุณจะออกเป็นภาษาฝรั่งเศสก่อน ให้ใส่ language ก่อนส่งครั้งแรก
จากนั้นให้คัดลอกหมายเลขหน้าแอปไปใส่ใน ascAppId Expo บอกวิธีหาไว้: เปิดแอปของคุณใน App Store Connect แล้วไปที่ App Information จะเป็นช่อง Apple ID ใต้ General Information มันเป็นตัวเลข ไม่ใช่ bundle identifier ของคุณ
ทำไมควรใช้คีย์ API แทน Apple ID
EAS Submit เชื่อมต่อกับ Apple ได้สองแบบ คือใช้ Apple ID ของคุณ หรือใช้คีย์ API ของ App Store Connect
Apple ID จะติดปัญหาการยืนยันตัวตนสองขั้นตอน ซึ่งApple บังคับใช้กับผู้ใช้ App Store Connect ทุกคน: ต้องมีคนมายืนยันการเข้าสู่ระบบ รหัสผ่านเฉพาะแอปที่ใส่ใน EXPO_APPLE_APP_SPECIFIC_PASSWORD ช่วยข้ามขั้นตอนนี้ได้ แต่Expo มองว่าปลอดภัยน้อยกว่าคีย์ API ซึ่งเป็นวิธีเริ่มต้นและวิธีที่แนะนำ คีย์ช่วยให้ยืนยันตัวตนได้โดยไม่ต้องมีคนโต้ตอบเลย จึงทำให้การส่งเป็นแบบอัตโนมัติได้
มีสองทางในการได้คีย์มา:
- ให้ EAS จัดการให้ รัน
eas credentials --platform iosเลือก profileproductionล็อกอินบัญชี Apple แล้วเลือก "App Store Connect: Manage your API Key" - ใช้คีย์ของคุณเอง ใน App Store Connect: Users and Access แท็บ Integrations, App Store Connect API, Team Keys แล้วกด Generate API Key คุณต้องใช้บัญชี Admin และคู่มือของ Expo ให้สิทธิ์ Admin กับคีย์
ถ้าเลือกทางที่สอง ให้จด Key ID ที่แสดงในรายการคีย์ที่ใช้งานอยู่ และ Issuer ID ที่อยู่ด้านบนของหน้า Integrations ที่สำคัญที่สุดคือเก็บไฟล์ .p8 ไว้ให้ดี เพราะคุณดาวน์โหลดได้แค่ครั้งเดียว และ Apple ไม่เก็บสำเนาไว้เลย
ตามที่ Apple ระบุ คีย์ระดับ Admin สามารถสร้างและลบผู้ใช้ในบัญชีของคุณได้ Apple ขอให้ไม่เก็บคีย์ไว้ใน repository โค้ดเด็ดขาด
ไฟล์ eas.json ขั้นต่ำที่คัดลอกไปใช้ได้
ค่าทั้งหมดเป็นค่าสมมติ ให้แทนที่ด้วยค่าของคุณเอง
{
"cli": {
"appVersionSource": "remote"
},
"build": {
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {
"ios": {
"ascAppId": "1234567890",
"appleTeamId": "ABCDE12345",
"ascApiKeyPath": "./keys/AuthKey_XXXXXXXXXX.p8",
"ascApiKeyIssuerId": "your-issuer-id",
"ascApiKeyId": "XXXXXXXXXX"
}
}
}
}
appVersionSourceและautoIncrement: เซิร์ฟเวอร์ของ EAS จะเก็บหมายเลข build และเพิ่มให้ทุกครั้งที่สร้าง build สำหรับ production Expo แนะนำโหมด remote นี้ตั้งแต่ EAS CLI 12ascAppId: หมายเลขหน้าแอปของคุณ ถ้าไม่มี โหมด non-interactive จะล้มเหลวappleTeamId: รหัสทีม Apple Developer ของคุณascApiKeyPath,ascApiKeyIssuerId,ascApiKeyId: คีย์ API ของคุณ ทั้งสามช่องรับค่าจาก environment variable ได้ อย่าลืมเพิ่มโฟลเดอร์keysลงใน.gitignore
ช่อง appleId ใช้เฉพาะเมื่อคุณล็อกอินด้วย Apple ID และถ้า EAS จัดการคีย์ให้คุณอยู่แล้ว ก็ลบสามช่อง ascApiKey ออกได้เลย ในแอปทั้งสามตัวของผมที่ตรวจทานเมื่อ 25 ตุลาคม profile ส่งแอปสำหรับ production มีแค่ ascAppId และมี appleTeamId เพิ่มใน Solys: ไม่มีคีย์อยู่ในไฟล์เลย
สร้าง build แล้วส่ง
eas build --platform ios --profile production
eas submit --platform ios
ถ้าไม่ใส่ตัวเลือกอื่น eas submit จะให้คุณเลือก build ที่จะส่ง และในการรันครั้งแรกจะถาม Apple ID ของคุณ profile ส่งแอปชื่อ production จะถูกใช้เป็นค่าเริ่มต้นถ้ามีอยู่ เอกสารอ้างอิงของ EAS CLI ระบุตัวเลือกที่ช่วยให้ไม่ต้องเลือกเอง:
| ตัวเลือก | หน้าที่ |
|---|---|
--latest | ส่ง build iOS ล่าสุด |
--id | ส่ง build EAS ที่ระบุ |
--path | ส่งไฟล์ .ipa ในเครื่อง |
--url | ส่งไฟล์ archive ออนไลน์ |
--groups | เพิ่มเข้ากลุ่มผู้ทดสอบภายใน |
--what-to-test | กรอกช่อง "What to test" |
ถ้าอยากให้ทุกอย่างต่อกันอัตโนมัติ ให้เพิ่ม --auto-submit ในคำสั่ง build ตามหน้าของ Expo เรื่องการส่งอัตโนมัติ build ที่เสร็จแล้วจะถูกส่งไปยัง EAS Submit โดยใช้ profile ส่งแอปที่ชื่อเดียวกับ profile build ถ้าอยากใช้ profile อื่น: --auto-submit-with-profile=nom build จะไปที่ TestFlight ไม่ใช่ไปที่รีวิว
ถ้าใช้ CI ให้เพิ่ม --non-interactive และโทเค็น EXPO_TOKEN เมื่อคำสั่งถามอะไรคุณไม่ได้ ก็ต้องมี ascAppId ใน profile และคีย์ API ซึ่งจะเป็นคีย์ที่ EAS ผูกไว้กับแอป หรือคีย์ของคุณเองในสามช่อง ascApiKey ก็ได้
หลังส่งแล้วเกิดอะไรขึ้น
1. Apple ประมวลผล build build ต้องผ่านการประมวลผลนี้ก่อนจะโผล่ใน App Store Connect และApple จะส่งอีเมลถึงคุณเมื่อเสร็จ Expo บอกว่าโดยทั่วไปใช้เวลา 10 ถึง 15 นาทีกว่าจะเห็นใน TestFlight
2. การปฏิบัติตามข้อกำหนดการส่งออก (export compliance) สถานะ Missing Compliance หมายความว่ายังขาดการแจ้งเรื่องการเข้ารหัส App Store Connect จะถามคำถามเหล่านี้ทุกครั้งที่มีเวอร์ชันใหม่ เว้นแต่ Info.plist จะตอบไว้แล้ว ใน Expo คีย์นี้ชื่อ ios.config.usesNonExemptEncryption:
{
"expo": {
"ios": {
"config": {
"usesNonExemptEncryption": false
}
}
}
}
ตามที่Appleระบุ ค่า false ใช้ได้ถ้าแอปของคุณ รวมถึงไลบรารีต่างๆ ไม่ได้ใช้การเข้ารหัสเลย หรือใช้เฉพาะการเข้ารหัสที่ได้รับการยกเว้น การเข้ารหัสของระบบ เช่น HTTPS ผ่าน URLSession มักได้รับการยกเว้น ให้แจ้ง false ก็ต่อเมื่อเป็นความจริงสำหรับแอปของคุณเท่านั้น เพราะคุณต้องรับผิดชอบต่อสิ่งที่แจ้ง และเหมือนคีย์อื่นๆ ใน Info.plist ต้องสร้าง build ใหม่ถึงจะมีผล
3. TestFlight เมื่อถึงสถานะ Ready to Submit ตามที่ Apple ระบุ build สามารถส่งให้ผู้ทดสอบภายใน ผ่านรีวิวเบต้าสำหรับผู้ทดสอบภายนอก หรือส่งเข้ารีวิว App Store ได้ ช่อง groups ใน profile จะเพิ่ม build เข้ากลุ่มผู้ทดสอบภายในของคุณ ส่วนที่เหลืออยู่ในใช้ TestFlight ทดสอบแอป
การส่ง build ไม่ใช่การส่งเข้ารีวิว
Expo เขียนไว้ชัดว่า build ใน TestFlight จะไม่ถูกเผยแพร่บน App Store โดยอัตโนมัติ EAS Submit ไม่ได้กรอกหน้าแอปหรือใส่ภาพหน้าจอให้คุณ ยังเหลืออีกสี่ขั้นตอนใน App Store Connect ตามที่อธิบายไว้ในหน้าช่วยเหลือของ Apple เรื่องการส่งเข้ารีวิว:
- กรอก metadata ที่จำเป็นของเวอร์ชันนั้น
- เลือก build ในส่วน Build ของเวอร์ชัน
- กด "Add for Review" เวอร์ชันจะเปลี่ยนเป็น Ready for Review แต่ยังไม่มีอะไรถูกส่งเข้ารีวิว
- กด "Submit for Review" สถานะจะเปลี่ยนเป็น In Review เมื่อเริ่มรีวิว
ข้อผิดพลาดที่พบบ่อยและวิธีแก้
| ข้อผิดพลาดที่แสดง | สาเหตุ | วิธีแก้ |
|---|---|---|
| ITMS-90189 | หมายเลข build ถูกใช้ไปแล้ว | autoIncrement |
| ITMS-90062 หรือ 90186 | เวอร์ชันถูกปิดไปแล้ว | เพิ่ม version |
| "Set ascAppId" | ไม่มี ascAppId ใน CI | เพิ่ม ascAppId |
| "API Keys cannot" | ไม่มีคีย์ผูกไว้ | eas credentials |
| ITMS-90683 | ไม่มีข้อความอธิบายการขอสิทธิ์ | ios.infoPlist |
| ITMS-91053 | manifest ไม่ครบ | ios.privacyManifests |
| ITMS-90725 | iOS SDK เก่าเกินไป | อัปเดต Expo SDK |
| Missing Compliance | ไม่ได้แจ้งเรื่องการเข้ารหัส | usesNonExemptEncryption |
ตามที่ Expo ระบุ หมายเลข build ที่ถูกใช้ไปแล้วเป็นสาเหตุที่พบบ่อยของการถูกปฏิเสธตอนส่ง รายละเอียดทั้งหมดอยู่ในหมายเลข build และเวอร์ชัน ข้อผิดพลาดสามตัวมีคู่มือแยกของตัวเอง: ITMS-90683 กับ Expo, ITMS-91053 กับ Expo และ ITMS-90725
ข้อความสองอันที่อยู่ในเครื่องหมายคำพูดมาจาก EAS และแก้ได้ในการตั้งค่าของมัน ส่วน Missing Compliance แก้ได้อีกทางด้วยการตอบคำถามใน App Store Connect สำหรับแถวอื่นๆ ทั้งหมด การแก้ต้องเปลี่ยนที่ไบนารี: สร้าง build ใหม่แล้วส่งอีกครั้ง การอัปเดตจากระยะไกลไม่ได้เปลี่ยน Info.plist, manifest หรือหมายเลขต่างๆ
ส่งแอปแรกของคุณโดยไม่ต้องลองผิดลองถูก
คำสั่งนี้เป็นแค่ขั้นตอนหนึ่ง iOS Kit เริ่มจากโค้ดตั้งต้นของแอปผม รวมระบบสมัครสมาชิกด้วย และพาคุณผ่านสี่ขั้นตอนจนถึง App Store ตามจังหวะของคุณเอง
ถ้าคุณกำลังเตรียมเปิดตัวแอปแรก ทำแบบประเมินฟรี ซึ่งจะบอกว่าอะไรที่ขวางคุณอยู่จริงๆ และส่งเช็กลิสต์กันโดน Apple ปฏิเสธของผมให้คุณ ส่วนเรื่องหน้าแอป ภาพหน้าจอ และการผ่านรีวิว หน้าเผยแพร่แอปบน App Store ครอบคลุมทุกขั้นตอน
คำถามที่พบบ่อย
จะเผยแพร่แอป Expo บน App Store ได้อย่างไร?
สร้าง build สำหรับ production ด้วย EAS Build แล้วส่งด้วย eas submit --platform ios หลังจาก Apple ประมวลผลเสร็จ build จะโผล่ใน TestFlight จากนั้นใน App Store Connect ให้กรอกหน้าแอป เลือก build นี้ในเวอร์ชัน แล้วกด "Add for Review" และ "Submit for Review"
EAS Submit ส่งแอปของฉันเข้ารีวิวของ Apple หรือไม่?
ไม่ EAS Submit ส่งไบนารีไปยัง App Store Connect และ build จะเข้า TestFlight การส่งเข้ารีวิวต้องทำเองใน App Store Connect หลังจากกรอกหน้าแอปและเลือก build แล้ว
หา ascAppId ของแอปได้ที่ไหน?
ใน App Store Connect เปิดแอปของคุณ แล้วไปที่ App Information จะเป็นช่อง Apple ID ใต้ General Information มันเป็นตัวเลข อย่าสับสนกับ bundle identifier ของคุณ
ต้องใช้ Apple ID เพื่อใช้ eas submit หรือไม่?
ในการรันครั้งแรก คำสั่งจะถาม Apple ID ของคุณ หลังจากนั้น ถ้ามี ascAppId ใน profile และคีย์ API ของ App Store Connect คำสั่งจะรันได้โดยไม่ต้องโต้ตอบ แม้แต่ใน CI คีย์ API เป็นวิธีเริ่มต้นและวิธีที่ Expo แนะนำ
ต้องรอนานแค่ไหนกว่าจะเห็น build ใน TestFlight?
Expo บอกว่าโดยทั่วไป Apple ใช้เวลาประมวลผล 10 ถึง 15 นาที และจะส่งอีเมลถึงคุณเมื่อเสร็จ ถ้า build ค้างอยู่ที่สถานะ Missing Compliance ให้ตอบคำถามเรื่องการเข้ารหัส แล้วแจ้งค่านี้ไว้ในการตั้งค่าสำหรับ build ถัดไป