{"id":"l-rn-5-3","courseId":"react-native-apps","lang":"ar","kind":"lesson","summary":"اضبط هوية Trailhead وإصداراته، وأنشئ builds للتطوير والمعاينة والإنتاج باستخدام EAS Build، وأرسلها إلى TestFlight وGoogle Play باستخدام EAS Submit، واستعدّ لمراجعة المتاجر.","html":"<p>حتى الآن عمل Trailhead عبر Expo Go والـ development builds، مع حاسوبك المحمول يقدّم كود JavaScript. أما المستخدمون الحقيقيون فيحتاجون إلى شيء آخر: تطبيق يُثبَّت من متجر، ويبدأ دون خادم تطوير، وموقَّع بحيث يثق به هاتفهم. يصنع <strong>EAS Build</strong> هذه الـ builds في السحابة، فلا تحتاج إلى Mac من أجل iOS، ويرفعها <strong>EAS Submit</strong> إلى المتاجر.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">الهوية والإصدارات في app.json</h2>\n<p>قبل أول build، احسم بضعة حقول:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"json\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">app.json</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"expo\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"name\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Trailhead\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"slug\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"trailhead\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"version\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"1.0.0\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"scheme\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"trailhead\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"icon\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"./assets/images/icon.png\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"ios\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"bundleIdentifier\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"com.example.trailhead\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"android\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"package\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"com.example.trailhead\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p><strong>معرّف الحزمة</strong> (bundle identifier في iOS) و<strong>اسم الحزمة</strong> (package name في Android) هما الهوية الدائمة لتطبيقك في المتاجر. غيّرهما بعد النشر فيرى المتجر تطبيقًا مختلفًا: لا تحديثات للمستخدمين الحاليين، ولا انتقال للمراجعات. استخدم نطاقًا معكوسًا تملكه.</p>\n<p>هناك نوعان من الإصدارات. <code dir=\"ltr\">version</code> هو ما يراه المستخدمون (“1.0.0”)؛ وترفعه مع كل إصدار عام. وكل رفع يحتاج أيضًا إلى رقم داخلي فريد ومتزايد (رقم البناء في iOS، ورمز الإصدار في Android). دع EAS يدير هذه الأرقام نيابةً عنك، كما سترى أدناه.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الـ build profiles</h2>\n<p>ثبّت الـ CLI، وسجّل الدخول إلى حساب Expo، وولّد ملف الإعدادات:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">npm</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> install</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -g</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> eas-cli</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">eas</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> login</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">eas</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> build:configure</span></span></code></pre></div>\n<p>هذا ينشئ <code dir=\"ltr\">eas.json</code> بثلاثة profiles:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"json\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">eas.json</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"cli\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"appVersionSource\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"remote\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"build\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"development\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"developmentClient\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">true</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"distribution\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"internal\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"preview\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"distribution\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"internal\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"production\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"autoIncrement\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">true</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"submit\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"production\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {} }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<ul>\n<li><strong>development</strong> يبني عميل التطوير الخاص بك (الـ development build من القسم 1)، مع قائمة التطوير، ويحمّل JavaScript من Metro.</li>\n<li><strong>preview</strong> يبني تطبيقًا مستقلًا للمختبِرين، يُثبَّت من رابط أو رمز QR (توزيع داخلي). وعلى iOS يجب أولًا تسجيل أجهزة المختبِرين باستخدام <code dir=\"ltr\">eas device:create</code>، لأن هذه builds من نوع ad hoc.</li>\n<li><strong>production</strong> يبني للمتاجر. ومع <code dir=\"ltr\">appVersionSource: &quot;remote&quot;</code> و<code dir=\"ltr\">autoIncrement</code>، يخزّن EAS رقم البناء ويرفعه مع كل production build.</li>\n</ul>\n<p>ثم ابنِ:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">eas</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> build</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --platform</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> android</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --profile</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> preview</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">eas</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> build</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --platform</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> all</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --profile</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> production</span></span></code></pre></div>\n<p>يعمل البناء على خوادم EAS؛ ويطبع الـ CLI رابطًا إلى السجلّات، وفي النهاية رابطًا إلى الـ build نفسه.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 690 220\" role=\"img\" aria-labelledby=\"l-rn-5-3-t1\"><defs><marker id=\"arrow-l-rn-5-3-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-rn-5-3-t1\">يمرّ الكود المصدري عبر eas build ليصبح ملفًا تنفيذيًا موقّعًا. تذهب builds المعاينة إلى المختبِرين عبر رابط. وتمرّ builds الإنتاج عبر eas submit إلى TestFlight أو مسار اختبار في Google Play، ثم مراجعة المتجر، ثم الإطلاق.</title>\n  <rect class=\"d-box\" x=\"10\" y=\"80\" width=\"100\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"60\" y=\"113\" text-anchor=\"middle\">الكود</text>\n  <path class=\"d-arrow\" d=\"M110 108 L150 108\" marker-end=\"url(#arrow-l-rn-5-3-1)\"/>\n  <rect class=\"d-box-primary\" x=\"155\" y=\"80\" width=\"120\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"215\" y=\"113\" text-anchor=\"middle\">eas build</text>\n  <path class=\"d-arrow\" d=\"M275 95 L330 45\" marker-end=\"url(#arrow-l-rn-5-3-1)\"/>\n  <rect class=\"d-box-accent\" x=\"335\" y=\"18\" width=\"150\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"410\" y=\"48\" text-anchor=\"middle\">preview للمختبِرين</text>\n  <path class=\"d-arrow\" d=\"M275 120 L330 160\" marker-end=\"url(#arrow-l-rn-5-3-1)\"/>\n  <rect class=\"d-box-primary\" x=\"335\" y=\"140\" width=\"120\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"395\" y=\"170\" text-anchor=\"middle\">eas submit</text>\n  <path class=\"d-arrow\" d=\"M455 165 L490 165\" marker-end=\"url(#arrow-l-rn-5-3-1)\"/>\n  <rect class=\"d-box-warn\" x=\"495\" y=\"140\" width=\"85\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"537\" y=\"162\" text-anchor=\"middle\">TestFlight</text>\n  <text class=\"d-label\" x=\"537\" y=\"180\" text-anchor=\"middle\">/ track</text>\n  <path class=\"d-arrow\" d=\"M580 165 L605 165\" marker-end=\"url(#arrow-l-rn-5-3-1)\"/>\n  <rect class=\"d-box-success\" x=\"610\" y=\"140\" width=\"75\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"647\" y=\"162\" text-anchor=\"middle\">المراجعة</text>\n  <text class=\"d-label\" x=\"647\" y=\"180\" text-anchor=\"middle\">ثم الإطلاق</text>\n</svg><figcaption>من الكود المصدري إلى المتاجر</figcaption></figure>\n<h2 id=\"sec-3\" tabindex=\"-1\">بيانات الاعتماد</h2>\n<p>كل build قابل للتثبيت يكون <strong>موقَّعًا</strong>. يحتاج iOS إلى شهادة توزيع (distribution certificate) وملف تجهيز (provisioning profile)؛ ويحتاج Android إلى upload keystore. يستطيع EAS توليدها وتخزينها وإعادة استخدامها مع كل build؛ ويسألك الـ CLI في المرة الأولى. ولـ iOS تحتاج إلى عضوية مدفوعة في Apple Developer Program؛ ولـ Google Play إلى رسم تسجيل مطوّر يُدفع مرة واحدة. وتعامل مع الـ keystore الخاص بـ Android بحرص: EAS يحتفظ به لك، لكن إن أدرته بنفسك وأضعته، يصبح تحديث التطبيق مؤلمًا.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">الإرسال إلى المتاجر</h2>\n<p>أنشئ أولًا سجلّ التطبيق في App Store Connect وفي Google Play Console. ثم ارفع آخر production build:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">eas</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> submit</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --platform</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> ios</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">eas</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> submit</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --platform</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> android</span></span></code></pre></div>\n<p>على iOS يذهب الـ build إلى App Store Connect، حيث يصبح متاحًا في <strong>TestFlight</strong> للمختبِرين بعد المعالجة. وعلى Android يصل إلى مسار اختبار (الداخلي افتراضيًا)؛ ويحتاج EAS إلى مفتاح حساب خدمة (service account) من Google ليرفعه نيابةً عنك. ويمكنك الجمع بين الخطوتين باستخدام <code dir=\"ltr\">eas build --auto-submit</code>.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>اختبر الـ build الإنتاجي، لا build التطوير فقط</span></p>\n<p>builds الإصدار تتصرّف بشكل مختلف: لا قائمة تطوير، وكود مصغّر، ونصوص أذونات حقيقية، ولا Metro يغطّي على ملف مفقود. ثبّت build من TestFlight أو من المسار الداخلي على هاتف حقيقي، وامشِ عبر المسارات الرئيسية قبل أن تضغط زرّ الإطلاق.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">اجتياز المراجعة</h2>\n<p>يراجع المتجران التطبيقات، وApple أكثر صرامة. ستملأ صفحة المتجر (الاسم، والوصف، ولقطات الشاشة لأحجام الأجهزة المطلوبة)، ورابط سياسة الخصوصية، وتفاصيل الخصوصية: قسم App Privacy لدى Apple ونموذج Data safety لدى Google Play، ويجب أن يطابقا ما يجمعه Trailhead فعلًا، مثل الموقع والصور.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>الإرسال دون طريقة يدخل بها المراجِع</span></p>\n<p>يتطلّب Trailhead حسابًا. وإن لم يستطع المراجِع تسجيل الدخول، يُرفض التطبيق، مهما كان مصقولًا. قدّم حسابًا تجريبيًا في ملاحظات المراجعة. أما حالات الرفض الشائعة الأخرى في المرة الأولى: انهيارات عند التشغيل، وأوصاف أذونات لا تذكر السبب، وميزات لا تعمل، مثل روابط معطوبة أو شاشات مؤقتة فارغة.</p>\n</aside>\n<p>تستغرق المراجعات عادةً من بضع ساعات إلى يومين. وبعد الموافقة، تختار أنت متى تطلق. ثم تتكرّر الدورة مع كل تغيير أصلي: إصدار جديد، ثم build، ثم إرسال، ثم مراجعة. أما الإصلاحات التي تقتصر على JavaScript فلها طريق أسرع، وهو موضوع الدرس الأخير.</p>\n","toc":[{"id":"sec-1","text":"الهوية والإصدارات في app.json","level":2},{"id":"sec-2","text":"الـ build profiles","level":2},{"id":"sec-3","text":"بيانات الاعتماد","level":2},{"id":"sec-4","text":"الإرسال إلى المتاجر","level":2},{"id":"sec-5","text":"اجتياز المراجعة","level":2}],"takeaways":["يترجم build الإصدار التطبيق الأصلي، ويجمّع كود JavaScript ويصغّره، ويوقّعه ببيانات اعتماد تثق بها المتاجر.","معرّف الحزمة (bundle identifier) في iOS واسم الحزمة (package name) في Android دائمان بعد النشر؛ فاخترهما بتأنٍّ.","تصف الـ profiles في eas.json أنواع الـ builds: <code dir=\"ltr\">development</code> لعميل التطوير الخاص بك، و<code dir=\"ltr\">preview</code> للمختبِرين، و<code dir=\"ltr\">production</code> للمتاجر.","يرفع <code dir=\"ltr\">eas submit</code> الـ build الإنتاجي إلى App Store Connect أو Google Play؛ ويحصل عليه المختبِرون عبر TestFlight أو مسار اختبار (testing track) قبل المراجعة.","معظم حالات الرفض الأولى تأتي من الانهيارات، أو نصوص أذونات مبهمة، أو تفاصيل خصوصية ناقصة، أو غياب حساب تجريبي في تطبيق يتطلّب تسجيل الدخول."],"further":[{"title":"EAS Build","url":"https://docs.expo.dev/build/introduction/"},{"title":"Configure EAS Build with eas.json","url":"https://docs.expo.dev/build/eas-json/"},{"title":"EAS Submit","url":"https://docs.expo.dev/submit/introduction/"},{"title":"App Store Review Guidelines","url":"https://developer.apple.com/app-store/review/guidelines/"}],"quiz":[{"q":"<p>بعد أن أصبح Trailhead على الـ App Store، يريد زميل تغيير معرّف الحزمة في iOS ليطابق اسم شركة جديد. ماذا يحدث إن فعلت؟</p>","options":[{"text":"يعامله المتجر بوصفه تطبيقًا جديدًا تمامًا، فلا يحصل المستخدمون الحاليون على التحديث، وتبقى مراجعاتك وتقييماتك مع الصفحة القديمة.","why":"صحيح. معرّف الحزمة (واسم الحزمة في Android) هو الهوية الدائمة للتطبيق في المتاجر."},{"text":"يعيد الـ App Store تسمية الصفحة تلقائيًا بعد المراجعة.","why":"أسماء العرض يمكن أن تتغيّر؛ أما المعرّفات فلا. والمعرّف الجديد يعني تطبيقًا جديدًا."},{"text":"لا شيء، ما دام رقم الإصدار يرتفع.","why":"الإصدارات ترتّب إصدارات التطبيق نفسه. والمعرّف المختلف ليس التطبيق نفسه."}],"answer":0},{"q":"<p>تريد أن يجرّب خمسة متنزّهين من ناديك Trailhead قبل أن يصل إلى المتاجر، مثبّتين إياه من رابط. أيّ build يناسب؟</p>","options":[{"text":"build من نوع <code dir=\"ltr\">development</code>، لأن فيه قائمة التطوير لإبداء الملاحظات.","why":"الـ development builds تحتاج إلى خادم Metro الخاص بك لتحميل JavaScript، فلا يستطيع المختبِرون استخدامها وحدهم."},{"text":"build من نوع <code dir=\"ltr\">production</code> يُثبَّت من الـ App Store.","why":"الـ production builds تمرّ بمراجعة المتجر والإطلاق العام؛ وهذه هي الخطوة التي تلي الاختبار."},{"text":"Expo Go مع رمز QR الخاص بمشروعك.","why":"لا يستطيع Expo Go أن يضمّ الإعدادات الأصلية لـ Trailhead، مثل مخطّط الـ URL ونصوص الأذونات، وسيحتاج المختبِرون إلى خادم التطوير الخاص بك."},{"text":"build من نوع <code dir=\"ltr\">preview</code> مع توزيع داخلي، يُشارَك عبر الرابط الذي يعطيك إياه EAS.","why":"صحيح. التوزيع الداخلي مصمّم لهذا؛ وعلى iOS يجب تسجيل أجهزة المختبِرين أولًا للـ builds من نوع ad hoc."}],"answer":3},{"q":"<p>ما الذي يتولّاه <code dir=\"ltr\">autoIncrement</code> في الـ production profile؟</p>","options":[{"text":"يرفع الإصدار الظاهر للمستخدم، مثل 1.2.0 إلى 1.3.0، مع كل build.","why":"الإصدار الظاهر للمستخدم تختاره أنت؛ أما <code dir=\"ltr\">autoIncrement</code> فيتولّى رقم البناء الداخلي."},{"text":"يرفع رقم البناء في iOS ورمز الإصدار (version code) في Android مع كل build، وتشترط المتاجر أن يكونا فريدين.","why":"صحيح. كل رفع يحتاج إلى رقم بناء أعلى حتى حين يبقى الإصدار الظاهر كما هو."},{"text":"يرفع إصدار Expo SDK مع كل build.","why":"ترقيات الـ SDK تغييرات مقصودة على اعتمادياتك، ولا تكون تلقائية أبدًا."}],"answer":1}],"exercise":{"kind":"order","items":["set-identity","configure","preview","production-build","submit","store-test","review","release"],"title":"رتّب الإصدار الأول من Trailhead","prompt":"<p>اكتملت ميزات Trailhead 1.0.0 واختُبرت. رتّب خطوات إصداره الأول على الـ App Store وGoogle Play بالترتيب الذي ستنفّذها به.</p>\n","hints":["لا تستطيع بناء أي شيء حتى يعرف التطبيق هويته الدائمة، ويعرف EAS الـ profiles الموجودة.","يرى المختبِرون build من نوع preview قبل أن يذهب أي شيء إلى المتاجر.","مراجعة المتجر تحدث بعد رفع الـ production build والتحقّق منه على هواتف حقيقية."],"explanation":"<p>الهوية أولًا لأنها دائمة، ثم ينشئ <code dir=\"ltr\">eas build:configure</code> الـ profiles التي يستخدمها كل أمر لاحق. يتيح build المعاينة لمتنزّهين حقيقيين اكتشاف المشكلات قبل إشراك المتاجر. يُرفع الـ production build باستخدام <code dir=\"ltr\">eas submit</code>، ويُتحقَّق منه مرة أخرى بوصفه build إصدار حقيقيًا عبر TestFlight أو المسار الداخلي، وعندها فقط يُرسَل للمراجعة مع اكتمال صفحة المتجر وتفاصيل الخصوصية والحساب التجريبي. والإطلاق هو الخطوة الأخيرة المقصودة: الموافقة لا تعني بالضرورة الإطلاق في تلك الدقيقة.</p>\n","checkLabels":{},"itemText":{"set-identity":"اضبط <code dir=\"ltr\">ios.bundleIdentifier</code> و<code dir=\"ltr\">android.package</code> و<code dir=\"ltr\">version</code> في app.json","configure":"شغّل <code dir=\"ltr\">eas build:configure</code> لإنشاء eas.json مع الـ build profiles","preview":"اصنع build من نوع <code dir=\"ltr\">preview</code> وشاركه مع بضعة متنزّهين عبر التوزيع الداخلي","production-build":"شغّل <code dir=\"ltr\">eas build --platform all --profile production</code>","submit":"شغّل <code dir=\"ltr\">eas submit</code> لرفع الـ builds إلى App Store Connect وGoogle Play","store-test":"ثبّت builds من TestFlight والمسار الداخلي على هواتف حقيقية وامشِ عبر المسارات الرئيسية","review":"أكمل صفحة المتجر وتفاصيل الخصوصية والحساب التجريبي، ثم أرسل للمراجعة","release":"أطلق الإصدار الموافق عليه للمستخدمين"}},"words":599,"readMinutes":4}