ليركسالمدونة
المقالاتسجل التحديثاتالتحديثاتالتوثيق
English
لوحة التحكم
ليركس

مدونة ليركس: أدلة لمطوري التطبيقات، وأخبار كل إصدار من ليركس وحزم SDK.

المدونة

المقالاتسجل التحديثات خلاصة RSS

ليركس

الرئيسيةالأسعارالتوثيقسياسة الاسترداد

© 2026 ليركس · جميع الحقوق محفوظة

ليركسالمدونة
المقالاتسجل التحديثاتالتحديثاتالتوثيق
English
لوحة التحكم
  1. مدونة ليركس
source mapswebcrash reporting

مسارات استدعاء مقروءة من JavaScript المصغّر: خرائط المصدر وتجميع الأخطاء

السطر index-8f3a1c.js:1:48213 لا يخبرك بشيء. ارفع خرائط المصدر من البناء ليشير كل خطأ إلى ملفك وسطرك ودالتك، وتعرّف على طريقة تجميع الأخطاء في مشكلات.

فريق ليركس

30 أكتوبر 20266 دقائق قراءة

مسار استدعاء مصغّر بجانب الخطأ نفسه بعد ردّه إلى شيفرة TypeScript الأصلية
محتويات المقال
  1. 1. اجعل البناء ينتج خرائط المصدر
  2. 2. ارفعها بعد كل بناء

اقرأ أيضًا

شاشة دفع في تطبيق Flutter تتعطل، ومسار الاستدعاء، والمشكلة المجمّعة في لوحة تحكم ليركس
flutterEN

تتبّع أعطال تطبيقات Flutter: دليل عملي للإعداد

معظم المستخدمين لا يبلّغون عن الأعطال، بل يغادرون. أعدّ تتبّع الأعطال في تطبيق Flutter خلال دقائق: ما الذي يُلتقط، وكيف تضيف السياق، وكيف تتخلص من الضجيج.

30 أكتوبر 20265 دقائق قراءة

مستخدم واحد في المنتصف يصله الإشعار نفسه على آيفون وهاتف أندرويد ومتصفح كروم وجهاز ماك
pushEN

أرسل الإشعار إلى شخص، لا إلى جهاز

لدى مستخدمك هاتف وحاسوب وتبويب في المتصفح. توقّف عن تخزين رموز الأجهزة: اربط الأجهزة بمعرّف المستخدم في نظامك وأرسل مرة واحدة إلى iOS وأندرويد والويب وmacOS.

ليركس

مدونة ليركس: أدلة لمطوري التطبيقات، وأخبار كل إصدار من ليركس وحزم SDK.

المدونة

المقالاتسجل التحديثات خلاصة RSS

ليركس

الرئيسيةالأسعارالتوثيقسياسة الاسترداد

© 2026 ليركس · جميع الحقوق محفوظة

  • 3. أعطِ الحزمة البرمجية الإصدار نفسه
  • في GitHub Actions
  • 4. ما الذي يتغير في لوحة التحكم
  • 5. كيف تتحول الأخطاء إلى مشكلات
  • 6. استبعد الضجيج
  • قائمة مراجعة
  • شيفرة JavaScript في بيئة الإنتاج مصغّرة (minified): تتقلص أسماء المتغيرات إلى حرف واحد، وتُدمج الملفات في أجزاء (chunks) بأسماء مشتقة من محتواها، وكثيراً ما يصبح الملف كله سطراً واحداً. هذا ممتاز لسرعة التحميل وسيئ جداً لتتبّع الأخطاء. يصلك الخطأ من الإنتاج هكذا:

    TypeError: Cannot read properties of undefined (reading 'id')
        at e.r (index-8f3a1c.js:1:48213)
        at Object.o (index-8f3a1c.js:1:51007)
    

    لا ملف تعرفه، ولا اسم دالة، ولا سطر يمكنك فتحه. خرائط المصدر (source maps) تحلّ هذه المشكلة. أداة البناء تعرف أصلاً كيف يقابل كل حرف في الناتج شيفرتك الأصلية؛ ارفع هذه الخريطة، فيصلك الخطأ نفسه على أنه الدالة submitOrder في الملف src/checkout/submit.ts السطر 42، مع الشيفرة المحيطة به.

    يشرح هذا الدليل الإعداد مع Vite وCreate React App وNext.js وAngular وFlutter Web، ثم يوضح كيف يجمع ليركس الأخطاء الناتجة في مشكلات.

    1. اجعل البناء ينتج خرائط المصدر

    فعّل الخرائط، ويُفضّل أن تكون مخفية (hidden): تُكتب ملفات .map لكن الحزمة لا تشير إليها، فلا يحمّلها المتصفح أبداً.

    الإعداد الخيار مجلد البناء
    ‏Vite ‏(React وVue وSvelte…) ‏build: { sourcemap: 'hidden' } في vite.config.ts dist
    ‏Create React App مفعّلة افتراضياً (ما لم تضبط GENERATE_SOURCEMAP=false) build
    ‏Next.js ‏productionBrowserSourceMaps: true في next.config .next
    ‏Angular ‏"sourceMap": { "scripts": true, "hidden": true } في angular.json قيمة outputPath للمشروع
    ‏Flutter Web ‏flutter build web --source-maps build/web

    2. ارفعها بعد كل بناء

    أمر واحد يُشغَّل مباشرة بعد البناء:

    npx @lerix-dev/lerix-cli upload
    

    تجد الأداة مجلد البناء بنفسها (outputPath في Angular، أو .next أو build/web أو dist أو build أو out)، وترفع كل ملف .js.map تجده (وتتجاوز خرائط CSS وnode_modules)، ثم تحذف الخرائط من ناتج البناء حتى لا تُنشر شيفرتك الأصلية أبداً.

    وتقرأ إعداداتها من متغيرات البيئة:

    المتغير ما هو
    LERIX_API_KEY مفتاح الـ API العام لمشروعك
    LERIX_PROJECT_ID الاسم المختصر (slug) للمشروع
    LERIX_SECRET_KEY مفتاح خاص بصلاحية رفع خرائط المصدر، من إعدادات المشروع ← مفاتيح API
    LERIX_RELEASE الإصدار الذي يُنشر به هذا البناء؛ وافتراضياً قيمة version في package.json (أو pubspec.yaml)

    لماذا مفتاح خاص؟ المفتاح العام موجود داخل كل حزمة ويب، ولو اكتُفي به لاستطاع أي شخص استبدال خرائطك وتزوير مسارات الاستدعاء. احتفظ بالمفتاح الخاص في بيئة CI لا داخل التطبيق.

    أضِف --optional لتشغيل الرفع من سكربت postbuild: على جهاز المطوّر الذي لا يحوي LERIX_SECRET_KEY يُتجاوز الرفع بدل أن يفشل البناء. ومع pnpm أو Yarn 2+، اللذين لا يشغّلان postbuild، اربطه بأمر البناء: "build": "vite build && lerix upload --optional".

    لا تُحذف الخرائط إلا إذا نجح رفعها كلها، فيمكنك إعادة تشغيل الأمر كما هو عند الفشل. استخدم --keep-maps للإبقاء عليها، و--dry-run لترى ما سيُرسل دون إرساله.

    3. أعطِ الحزمة البرمجية الإصدار نفسه

    يطابق ليركس الخرائط أولاً حسب اسم ملف السكربت، ولأن أسماء الأجزاء مشتقة من محتواها فهذا يكفي في أغلب الحالات. تمرير الإصدار نفسه إلى الحزمة البرمجية يجعل المطابقة دقيقة، ويوسم كل خطأ بالإصدار الذي جاء منه:

    <LerixProvider
      options={{
        apiKey: 'your-api-key',
        projectId: 'your-project-slug',
        release: import.meta.env.VITE_LERIX_RELEASE,
      }}
    >
      <App />
    </LerixProvider>
    

    في Next.js يقرأ LerixNextProvider المتغير NEXT_PUBLIC_LERIX_RELEASE بنفسه، وفي Angular هو الخيار release في provideLerix(). استخدم قيمة لا تكتبها يدوياً: قيمة version في package.json أو معرّف الـ commit.

    إذا كنت تستخدم أيضاً التحكم بالإصدارات من ليركس على الويب (تنبيهات التحديث)، فاستخدم إصداراً مرقّماً مثل 1.4.0 بدل معرّف الـ commit، لأن قواعد التحديث تقارن الإصدارات كأرقام.

    في GitHub Actions

    jobs:
      deploy:
        runs-on: ubuntu-latest
        env:
          LERIX_RELEASE: ${{ github.sha }}
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with:
              node-version: 20
          - run: npm ci
    
          # The same release, available to the app at build time
          - run: npm run build
            env:
              VITE_LERIX_RELEASE: ${{ github.sha }}
    
          - run: npx @lerix-dev/lerix-cli upload
            env:
              LERIX_API_KEY: ${{ secrets.LERIX_API_KEY }}
              LERIX_PROJECT_ID: ${{ secrets.LERIX_PROJECT_ID }}
              LERIX_SECRET_KEY: ${{ secrets.LERIX_SECRET_KEY }}
    
          # Deploy dist here. It no longer contains .map files.
    

    4. ما الذي يتغير في لوحة التحكم

    يتم ربط الخرائط على الخادم لحظة وصول الخطأ. تعرض الأخطاء الجديدة الملف الأصلي والسطر والدالة، مع خمسة أسطر من الشيفرة قبل السطر المتعطل وبعده. وزر Show minified يعرض مسار الاستدعاء كما أرسله المتصفح تماماً.

    ومسار الاستدعاء المقروء هو أيضاً ما يراه مساعد الذكاء الاصطناعي ومشكلات GitHub وخادم MCP. أمران يجب معرفتهما:

    • لا تُربط إلا الأخطاء التي تصل بعد الرفع؛ الأخطاء الأقدم تبقى بمسارها المصغّر.
    • ربط الخرائط لا يؤخر أي تقرير أبداً. إذا غابت الخريطة أو تأخرت يُحفظ الخطأ كما وصل.

    5. كيف تتحول الأخطاء إلى مشكلات

    عشرة آلاف تقرير عن خلل واحد يجب أن تكون سطراً واحداً في صندوقك، لا عشرة آلاف سطر. يعطي ليركس كل خطأ بصمة من جزأين:

    1. السطر الأول من الرسالة بعد إخفاء الأجزاء المتغيرة: الأرقام والمعرّفات UUID والمعرّفات الست عشرية الطويلة والبريد والروابط. أما رموز الأخطاء الملتصقة بالنص مثل PGRST202 أو #441 فتبقى كما هي.
    2. أول إطار في مسار الاستدعاء من شيفرتك أنت، مختصراً إلى اسم الدالة والملف: بلا رقم سطر ولا عمود، وبلا الجزء المشتق من المحتوى في اسم الملف. وتُتجاوز إطارات node_modules والمتصفح والحزمة البرمجية.

    خمسة أخطاء

    ولأن رقم السطر واسم الجزء مستبعدان، يبقى الخطأ المشكلةَ نفسها عبر عمليات النشر بدل أن يبدأ من الصفر مع كل بناء. ولأن مسار الاستدعاء يُربط بالخرائط قبل أخذ البصمة، يعتمد التجميع على أسماء دوالك الحقيقية.

    تتتبّع كل مشكلة عدد مرات حدوثها والمستخدمين المتأثرين وأول ظهور وآخر ظهور. والحالة تسري على كل التكرارات:

    • المشكلات المحلولة تُفتح من جديد تلقائياً إذا عاد الخطأ، وتصلك رسالة بريد عن هذا الخلل العائد.
    • المشكلات المتجاهلة يستمر عدّها لكن دون تنبيهات، وتُخفى من القائمة الافتراضية.

    6. استبعد الضجيج

    بعض أخطاء المتصفح لا تحمل أي معلومة. يُسقطها الخادم لكل المشاريع:

    • ‏ResizeObserver loop limit exceeded وResizeObserver loop completed with undelivered notifications
    • ‏Script error.، وهي الرسالة البديلة التي يعرضها المتصفح لخطأ في سكربت من نطاق آخر، بلا رسالة ولا مسار
    • الأخطاء التي يقع مسارها بالكامل داخل إضافات المتصفح

    وللضجيج الخاص بتطبيقك، صفِّ على الجهاز قبل أن يُرسل أي شيء:

    <LerixProvider
      options={{
        apiKey: 'your-api-key',
        projectId: 'your-project-slug',
        ignoreErrors: ['ResizeObserver loop', /^ChunkLoadError/],
        beforeSend: (event) =>
          event.message.includes('extension://') ? null : event,
      }}
    >
    

    النصوص تطابق أي جزء من الرسالة دون تمييز حالة الأحرف، والتعابير النمطية تُختبر كما كُتبت. وإرجاع null من beforeSend يُسقط الحدث. وكلاهما يعمل في المتصفح قبل أن يربط الخادم مسار الاستدعاء بالخرائط، فطابِق على نص الرسالة لا على أسماء الملفات.

    قائمة مراجعة

    1. خرائط مصدر مخفية مفعّلة في أداة البناء.
    2. ‏npx @lerix-dev/lerix-cli upload مباشرة بعد البناء، مع LERIX_SECRET_KEY في بيئة CI.
    3. الإصدار نفسه في أداة الرفع وفي الحزمة البرمجية.
    4. انشر مجلد البناء بعد الرفع فقط، حتى تكون الخرائط قد حُذفت منه.
    5. ارمِ خطأً واحداً في الإنتاج عمداً وتأكد أنه يشير إلى ملفك.

    يحتفظ ليركس بأحدث 5,000 خريطة لكل مشروع، بحجم يصل إلى 50 ميغابايت للخريطة.

    source mapswebcrash reporting
    شارك المقال X LinkedIn

    محتويات المقال

    1. 1. اجعل البناء ينتج خرائط المصدر
    2. 2. ارفعها بعد كل بناء
    3. 3. أعطِ الحزمة البرمجية الإصدار نفسه
    4. في GitHub Actions
    5. 4. ما الذي يتغير في لوحة التحكم
    6. 5. كيف تتحول الأخطاء إلى مشكلات
    7. 6. استبعد الضجيج
    8. قائمة مراجعة

    30 أكتوبر 20265 دقائق قراءة

    شاشة 'تحديث مطلوب' وإعدادات التحكم بالإصدارات وشاشة صيانة 'نعود قريباً'
    release controlEN

    افرض تحديث التطبيق أو فعّل وضع الصيانة دون نشر إصدار جديد

    إصدار قديم يتعطل مع الـ API الجديدة، أو الخادم يحتاج ساعة صيانة. اضبط قواعد التحديث ونوافذ الصيانة من لوحة التحكم وستلتزم بها كل التطبيقات خلال دقائق.

    30 أكتوبر 20266 دقائق قراءة

    اكتشف العطل القادم قبل أن يبلّغك عنه المستخدمون

    تتبّع الأعطال والإشعارات والتحليلات ومساعد ذكاء اصطناعي يقرأ شيفرتك. ابدأ مجانًا.

    ابدأ مجانًا