أفضل الممارسات لتطبيق الزاوي نظيفة وفعالة

لقد كنت أعمل على تطبيق Angular واسع النطاق في Trade Me ، نيوزيلندا منذ عامين. على مدار السنوات القليلة الماضية ، قام فريقنا بتحسين تطبيقنا من حيث معايير الترميز والأداء لجعله في أفضل حالاته الممكنة.

توضح هذه المقالة الممارسات التي نستخدمها في تطبيقنا وترتبط بـ Angular و Typescript و RxJs و @ ngrx / store. سنراجع أيضًا بعض إرشادات الترميز العامة للمساعدة في جعل التطبيق أكثر نظافة.

1) trackBy

عند استخدام ngFor للتكرار فوق صفيف في القوالب ، استخدمه مع دالة trackBy والتي ستُرجع معرفًا فريدًا لكل عنصر.

لماذا ا؟

عندما تتغير صفيف ، يعيد Angular إعادة عرض شجرة DOM بأكملها. ولكن إذا كنت تستخدم trackBy ، فستعرف Angular العنصر الذي تم تغييره وسوف تقوم فقط بإجراء تغييرات DOM لهذا العنصر المحدد.

للحصول على شرح مفصل حول هذا الموضوع ، يرجى الرجوع إلى هذا المقال من قبل نتنيل بصل.

قبل

  • {{item}}
  • بعد

    // في القالب
  • {{item}}
  • // في المكون
    trackByFn (فهرس ، عنصر) {
       return item.id ؛ // معرف فريد مطابق للعنصر
    }

    2) const مقابل اسمحوا

    عند التصريح عن المتغيرات ، استخدم const عندما لا يتم إعادة تعيين القيمة.

    لماذا ا؟

    استخدام let و const عند الاقتضاء يجعل نية الإعلانات أكثر وضوحًا. سيساعد ذلك أيضًا في تحديد المشكلات عند إعادة تعيين قيمة إلى ثابت بطريق الخطأ عن طريق رمي خطأ وقت الترجمة. كما أنه يساعد على تحسين قراءة التعليمات البرمجية.

    قبل

    دع السيارة = 'سيارة مثيرة للسخرية' ؛
    دع myCar = `My $ {car}`؛
    دع yourCar = `Your $ {car}؛
    if (iHaveMoreThanOneCar) {
       myCar = `$ {myCar} s`؛
    }
    if (youHaveMoreThanOneCar) {
       yourCar = `$ {youCar} s`؛
    }

    بعد

    / / لم يتم إعادة تعيين قيمة السيارة ، حتى نتمكن من جعلها const
    سيارة const = 'سيارة مضحكة' ؛
    دع myCar = `My $ {car}`؛
    دع yourCar = `Your $ {car}؛
    if (iHaveMoreThanOneCar) {
       myCar = `$ {myCar} s`؛
    }
    if (youHaveMoreThanOneCar) {
       yourCar = `$ {youCar} s`؛
    }

    3) مشغلي الأنابيب

    استخدم مشغلي الأنابيب عند استخدام مشغلي RxJs.

    لماذا ا؟

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

    هذا يسهل أيضًا تحديد العوامل غير المستخدمة في الملفات.

    ملاحظة: هذا يحتاج إلى الإصدار الزاوي 5.5+.

    قبل

    استيراد "rxjs / add / operator / map" ؛
    استيراد "rxjs / add / operator / take" ؛
    iAmAnObservable
        .map (value => value.item)
        .تأخذ 1)؛

    بعد

    استيراد {map ، take} من 'rxjs / operator' ؛
    iAmAnObservable
        .يضخ(
           الخريطة (value => value.item) ،
           تأخذ 1)
         )؛

    4) عزل الخارقة API

    ليست جميع واجهات برمجة التطبيقات دليلًا على الرصاص - نحتاج أحيانًا إلى إضافة بعض المنطق في الكود لتعويض الأخطاء في واجهات برمجة التطبيقات. بدلاً من وجود الاختراقات في المكونات حيث تكون هناك حاجة إليها ، من الأفضل عزلها في مكان واحد - كما هو الحال في الخدمة واستخدام الخدمة من المكون.

    لماذا ا؟

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

    يمكنك أيضًا إنشاء علامات مخصصة مثل API_FIX تشبه TODO ووضع علامة على الإصلاحات معها حتى يسهل العثور عليها.

    5) الاشتراك في القالب

    تجنب الاشتراك في الملاحظات من المكونات ، وبدلاً من ذلك يمكنك الاشتراك في الملاحظات من القالب.

    لماذا ا؟

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

    هذا أيضًا يمنع المكونات من أن تكون في حالة جيدة وإدخال الأخطاء حيث يتم تحور البيانات خارج الاشتراك.

    قبل

    // قالب

    {{textToDisplay}}

    // مكون
    iAmAnObservable
        .يضخ(
           الخريطة (value => value.item) ،
           takeUntil (this._destroyed $)
         )
        .subscribe (item => this.textToDisplay = item) ؛

    بعد

    // قالب

    {{textToDisplay $ | async}}

    // مكون
    this.textToDisplay $ = iAmAnObservable
        .يضخ(
           خريطة (قيمة => value.item)
         )؛

    6) تنظيف الاشتراكات

    عند الاشتراك في الملاحظات ، تأكد دائمًا من إلغاء اشتراكك فيها بشكل مناسب باستخدام عوامل التشغيل مثل take و takeUntil ، إلخ.

    لماذا ا؟

    سيؤدي الفشل في إلغاء الاشتراك في عناصر الملاحظة إلى حدوث تسرب غير مرغوب فيه للذاكرة نظرًا لترك الدفق المرئي مفتوحًا ، حتى بعد تدمير أحد المكونات / انتقال المستخدم إلى صفحة أخرى.

    أفضل من ذلك ، قم بعمل قاعدة الوبر لاكتشاف الملاحظات التي لم يتم إلغاء اشتراكها.

    قبل

    iAmAnObservable
        .يضخ(
           خريطة (قيمة => value.item)
         )
        .subscribe (item => this.textToDisplay = item) ؛

    بعد

    باستخدام takeUntil عندما ترغب في الاستماع إلى التغييرات حتى يتم رصد قيمة أخرى يمكن ملاحظتها:

    private _destroyed $ = new Subject ()؛
    ngOnInit () العامة: void {
        iAmAnObservable
        .يضخ(
           خريطة (قيمة => value.item)
          // نريد الاستماع إلى iAmAnObservable حتى يتم إتلاف المكون ،
           takeUntil (this._destroyed $)
         )
        .subscribe (item => this.textToDisplay = item) ؛
    }
    ngOnDestroy () العامة: void {
        this._destroyed $ .next ()؛
        this._destroyed $ .complete ()؛
    }

    يعد استخدام موضوع خاص مثل هذا نمطًا لإدارة إلغاء اشتراك العديد من الملاحظات في المكون.

    استخدام تأخذ عندما تريد فقط القيمة الأولى المنبعثة من الملاحظة:

    iAmAnObservable
        .يضخ(
           الخريطة (value => value.item) ،
           تأخذ 1)،
           takeUntil (this._destroyed $)
        )
        .subscribe (item => this.textToDisplay = item) ؛

    لاحظ استخدام takeUntil مع take هنا. هذا لتجنب تسرب الذاكرة الناتج عن عدم تلقي الاشتراك قيمة قبل إتلاف المكون. بدون takeUntil هنا ، سيظل الاشتراك معلقًا حتى تحصل على القيمة الأولى ، ولكن بما أن المكون قد تم إتلافه بالفعل ، فلن يحصل على قيمة - مما يؤدي إلى حدوث تسرب للذاكرة.

    7) استخدام العوامل المناسبة

    عند استخدام عوامل تشغيل التسوية مع أدوات الملاحظة الخاصة بك ، استخدم المشغل المناسب لهذا الموقف.

    switchMap: عندما تريد تجاهل الانبعاثات السابقة عندما يكون هناك انبعاث جديد

    mergeMap: عندما تريد التعامل مع جميع الانبعاثات بشكل متزامن

    concatMap: عندما تريد التعامل مع الانبعاثات واحدة تلو الأخرى عند إطلاقها

    exhaustMap: عندما تريد إلغاء جميع الانبعاثات الجديدة أثناء معالجة إصدار سابق

    للحصول على شرح أكثر تفصيلاً حول هذا الموضوع ، يرجى الرجوع إلى هذه المقالة التي كتبها نيكولاس جاميسون.

    لماذا ا؟

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

    8) حمولة كسول

    حاول ، عند الإمكان ، تحميل الوحدات في تطبيق الزاوي الكسول. التحميل الكسول هو عندما تقوم بتحميل شيء فقط عند استخدامه ، على سبيل المثال ، يتم تحميل أحد المكونات فقط عندما يتم عرضه.

    لماذا ا؟

    سيؤدي ذلك إلى تقليل حجم التطبيق الذي سيتم تحميله ويمكن أن يحسن وقت تشغيل التطبيق من خلال عدم تحميل الوحدات النمطية غير المستخدمة.

    قبل

    // app.routing.ts
    {path: 'not-lazy-load' ، المكون: NotLazyLoadedComponent}

    بعد

    // app.routing.ts
    {
      المسار: "الحمل الكسول" ،
      loadChildren: 'lazy-load.module # LazyLoadModule'
    }
    // كسول load.module.ts
    استيراد {NgModule} من '@ angular / core' ؛
    استيراد {CommonModule} من '@ angular / common' ؛
    استيراد {RouterModule} من '@ angular / router' ؛
    قم باستيراد {LazyLoadComponent} من './lazy-load.component' ؛
    NgModule ({
      الواردات: [
        CommonModule،
        RouterModule.forChild ([
             {
                 المسار: '' ،
                 المكون: LazyLoadComponent
             }
        ])
      ]،
      التصريحات:
        LazyLoadComponent
      ]
    })
    فئة التصدير LazyModule {}

    9) تجنب وجود اشتراكات داخل الاشتراكات

    في بعض الأحيان قد تحتاج إلى قيم من أكثر من ملاحظة يمكن تنفيذها. في هذه الحالة ، تجنب الاشتراك في واحدة يمكن ملاحظتها في كتلة الاشتراك الخاصة بأخرى يمكن ملاحظتها. بدلاً من ذلك ، استخدم عوامل التشغيل المناسبة. يعمل المشغلون التسلسليون على مشاهدات من المشغل قبلهم. بعض مشغلي السلاسل هم: withLatestFrom ، و combineLatest ، إلخ

    قبل

    $ firstObservable .pipe (
       تأخذ 1)
    )
    .subscribe (firstValue => {
        $ secondObservable .pipe (
            تأخذ 1)
        )
        .subscribe (secondValue => {
            console.log (`القيم المدمجة هي: $ {firstValue} & $ {secondValue}`)؛
        })؛
    })؛

    بعد

    $ firstObservable .pipe (
        withLatestFrom (secondObservable $)،
        أول()
    )
    .subscribe (([[firstValue، secondValue]) => {
        console.log (`القيم المدمجة هي: $ {firstValue} & $ {secondValue}`)؛
    })؛

    لماذا ا؟

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

    الأداء: إذا كانت الملاحظات باردة ، فسوف تشترك في أول ما يمكن ملاحظته ، انتظر حتى يكتمل ، ثم تبدأ أعمال الملاحظة الثانية. إذا كانت هذه طلبات شبكة ، فستظهر على أنها متزامن / شلال.

    10) تجنب أي ؛ اكتب كل شيء

    قم دائمًا بتعريف المتغيرات أو الثوابت بنوع آخر بخلاف أي.

    لماذا ا؟

    عند التصريح عن المتغيرات أو الثوابت في Typescript دون كتابة ، سيتم استنتاج كتابة المتغير / الثابت بالقيمة التي يتم تخصيصها لها. هذا سوف يسبب مشاكل غير مقصودة. مثال كلاسيكي هو:

    const س = 1 ؛
    const ص = 'أ' ؛
    const ض = س + ص ؛
    console.log (`قيمة z هي: $ {z}`
    // انتاج
    قيمة z هي 1a

    هذا يمكن أن يسبب مشاكل غير مرغوب فيها عندما تتوقع أن يكون y عددًا أيضًا. يمكن تجنب هذه المشكلات عن طريق كتابة المتغيرات بشكل مناسب.

    const x: رقم = 1 ؛
    const y: number = 'a'؛
    const z: number = x + y؛
    // هذا سيعطي خطأ ترجمة يقول:
    اكتب "" a "" غير قابل للتعيين لكتابة "number".
    const ص: العدد

    بهذه الطريقة ، يمكننا تجنب الأخطاء التي تسببها الأنواع المفقودة.

    ميزة أخرى من وجود كتابة جيدة في التطبيق الخاص بك هو أنه يجعل إعادة بيع العقارات أسهل وأكثر أمانًا.

    النظر في هذا المثال:

    ngOnInit () العامة: void {
        دع myFlashObject = {
            الاسم: "اسمي رائع" ،
            العمر: "عمري بارد" ،
            loc: "موقعي الرائع"
        }
        this.processObject (myFlashObject)؛
    }
    processObject العامة (myObject: any): void {
        console.log (`Name: $ {myObject.name}`)؛
        console.log (`Age: $ {myObject.age}`)؛
        console.log (`الموقع: $ {myObject.loc}`) ؛
    }
    // انتاج
    الاسم: اسمي رائع
    العمر: عمري بارد
    الموقع: موقعي الرائع

    دعنا نقول ، نريد إعادة تسمية مكان العقار إلى موقع في myFlashObject:

    ngOnInit () العامة: void {
        دع myFlashObject = {
            الاسم: "اسمي رائع" ،
            العمر: "عمري بارد" ،
            الموقع: "موقعي الرائع"
        }
        this.processObject (myFlashObject)؛
    }
    processObject العامة (myObject: any): void {
        console.log (`Name: $ {myObject.name}`)؛
        console.log (`Age: $ {myObject.age}`)؛
        console.log (`الموقع: $ {myObject.loc}`) ؛
    }
    // انتاج
    الاسم: اسمي رائع
    العمر: عمري بارد
    الموقع: غير محدد

    إذا لم يكن لدينا كتابة على myFlashObject ، فهي تعتقد أن خاصية loc الموجودة على myFlashObject ليست معرَّفة فقط وليست خاصية صالحة.

    إذا كان لدينا كتابة لـ myFlashObject ، فسنحصل على خطأ وقت ترجمة لطيف كما هو موضح أدناه:

    اكتب FlashObject = {
        الاسم: سلسلة ،
        العمر: سلسلة ،
        الموقع: سلسلة
    }
    ngOnInit () العامة: void {
        دع myFlashObject: FlashObject = {
            الاسم: "اسمي رائع" ،
            العمر: "عمري بارد" ،
            // خطأ في التحويل
            اكتب '{name: string؛ العمر: سلسلة ؛ loc: string؛ } 'غير قابل للتعيين لكتابة "FlashObjectType".
            قد يحدد الكائن الحرفي فقط الخصائص المعروفة ، و "loc" غير موجود في النوع "FlashObjectType".
            loc: "موقعي الرائع"
        }
        this.processObject (myFlashObject)؛
    }
    processObject العامة (myObject: FlashObject): void {
        console.log (`Name: $ {myObject.name}`)؛
        console.log (`Age: $ {myObject.age}`)
        // خطأ في التحويل
        الخاصية "loc" غير موجودة في النوع "FlashObjectType".
        console.log (`الموقع: $ {myObject.loc}`) ؛
    }

    إذا كنت تبدأ مشروعًا جديدًا ، فإن الأمر يستحق الإعداد الصارم: صحيح في ملف tsconfig.json لتمكين جميع خيارات التحقق من النوع الصارمة.

    11) الاستفادة من قواعد الوبر

    تحتوي tslint على العديد من الخيارات المضمنة بالفعل مثل no-any ، و no-magic-no ، و no-console ، إلخ ، والتي يمكنك تهيئتها في tslint.json لفرض قواعد معينة في قاعدة الشفرة الخاصة بك.

    لماذا ا؟

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

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

    قبل

    ngOnInit () العامة: void {
        console.log ('أنا رسالة سجل وحدة تحكم غير مطيع') ؛
        console.warn ('أنا رسالة تحذير وحدة التحكم المشاغب') ؛
        console.error ('أنا رسالة خطأ وحدة التحكم المشاغب') ؛
    }
    // انتاج
    لا أخطاء ، يطبع أدناه على نافذة وحدة التحكم:
    أنا رسالة وحدة المشاغب
    أنا رسالة تحذير وحدة التحكم المشاغب
    أنا رسالة خطأ وحدة التحكم المشاغب

    بعد

    // tslint.json
    {
        "قواعد": {
            .......
            "عدم وحدة التحكم": [
                 صحيح،
                 "سجل" ، / / لا يسمح console.log
                 "تحذير" // no console.warn مسموح به
            ]
       }
    }
    // ..component.ts
    ngOnInit () العامة: void {
        console.log ('أنا رسالة سجل وحدة تحكم غير مطيع') ؛
        console.warn ('أنا رسالة تحذير وحدة التحكم المشاغب') ؛
        console.error ('أنا رسالة خطأ وحدة التحكم المشاغب') ؛
    }
    // انتاج
    أخطاء الوبر عن عبارات console.log و console.warn وعدم وجود خطأ لوحدة console.error حيث لم يتم ذكرها في التوصيف
    لا يُسمح بالمكالمات إلى "console.log".
    لا يُسمح بالمكالمات إلى "console.warn".

    12) مكونات صغيرة قابلة لإعادة الاستخدام

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

    كقاعدة عامة ، فإن الطفل الأخير في شجرة المكون سيكون أغبى الجميع.

    لماذا ا؟

    المكونات القابلة لإعادة الاستخدام تقلل من ازدواجية التعليمات البرمجية وبالتالي تسهل الحفاظ عليها وإجراء التغييرات.

    المكونات الغبية هي أبسط ، لذلك فهي أقل عرضة لوجود أخطاء. المكونات البكم تجعلك تفكر أكثر في API للمكون العمومي ، وتساعد في استنشاق المخاوف المختلطة.

    13) يجب أن تتعامل المكونات مع منطق العرض فقط

    تجنب وجود أي منطق بخلاف منطق العرض في المكون الخاص بك كلما استطعت واجعل المكون يتعامل فقط مع منطق العرض.

    لماذا ا؟

    تم تصميم المكونات لأغراض العرض التقديمي والتحكم في ما يجب أن تفعله طريقة العرض. يجب استخراج أي منطق أعمال في أساليبه / خدماته الخاصة عند الاقتضاء ، مع فصل منطق العمل عن منطق العرض.

    عادة ما يكون منطق العمل أسهل لوحدة الاختبار عند استخراجه إلى إحدى الخدمات ، ويمكن إعادة استخدامه بواسطة أي مكونات أخرى تحتاج إلى نفس منطق العمل المطبق.

    14) تجنب الطرق الطويلة

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

    لماذا ا؟

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

    يقاس هذا أحيانًا كـ "التعقيد السيكلوماتي". هناك أيضًا بعض قواعد TSLint للكشف عن التعقيد السيكلوماتي / المعرفي ، والتي يمكنك استخدامها في مشروعك لتجنب الأخطاء واكتشاف رائحة التعليمات البرمجية ومشكلات الصيانة.

    15) جاف

    لا تكرر ما قلته أو فعلته سابقا. تأكد من عدم وجود نفس الرمز المنسوخ في أماكن مختلفة في قاعدة البيانات. استخرج الكود المكرر واستخدمه بدلاً من الكود المكرر.

    لماذا ا؟

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

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

    16) إضافة آليات التخزين المؤقت

    عند إجراء مكالمات API ، لا تتغير ردود بعضها كثيرًا. في هذه الحالات ، يمكنك إضافة آلية للتخزين المؤقت وتخزين القيمة من API. عند تقديم طلب آخر إلى نفس واجهة برمجة التطبيقات ، تحقق مما إذا كانت هناك قيمة له في ذاكرة التخزين المؤقت وإذا كان الأمر كذلك ، فاستخدمه. خلاف ذلك ، قم بإجراء استدعاء API وذاكرة التخزين المؤقت النتيجة.

    إذا تغيرت القيم ولكن ليس بشكل متكرر ، يمكنك تقديم وقت ذاكرة التخزين المؤقت حيث يمكنك التحقق من آخر مرة تم فيها تخزينها مؤقتًا وتحديد ما إذا كان يجب استدعاء API أم لا.

    لماذا ا؟

    وجود آلية للتخزين المؤقت يعني تجنب مكالمات API غير المرغوب فيها. من خلال إجراء مكالمات واجهة برمجة التطبيقات (API) فقط عند الحاجة وتجنب الازدواجية ، تتحسن سرعة التطبيق نظرًا لأننا لا نضطر إلى انتظار الشبكة. وهذا يعني أيضًا أننا لا نقوم بتنزيل نفس المعلومات مرارًا وتكرارًا.

    17) تجنب المنطق في القوالب

    إذا كان لديك أي نوع من المنطق في القوالب الخاصة بك ، حتى لو كان عبارة بسيطة && ، فمن الجيد استخراجه إلى مكونه.

    لماذا ا؟

    يعني وجود منطق في القالب أنه لا يمكن إجراء اختبار وحدة عليه ومن ثم يكون أكثر عرضة للأخطاء عند تغيير رمز القالب.

    قبل

    // قالب
    

    الحالة: مطور

    // مكون
    ngOnInit () العامة: void {
        this.role = 'developer'؛
    }

    بعد

    // قالب
    

    الحالة: مطور

    // مكون
    ngOnInit () العامة: void {
        this.role = 'developer'؛
        this.showDeveloperStatus = true؛
    }

    18) يجب أن تكون سلاسل آمنة

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

    لماذا ا؟

    بإعلان نوع المتغير بشكل مناسب ، يمكننا تجنب الأخطاء أثناء كتابة التعليمات البرمجية أثناء وقت الترجمة بدلاً من وقت التشغيل.

    قبل

    myStringValue الخاص: string؛
    if (itShouldHaveFirstValue) {
       myStringValue = 'الأول' ؛
    } آخر {
       myStringValue = 'Second'
    }

    بعد

    myStringValue الخاص: "الأول" | 'ثانيا'؛
    if (itShouldHaveFirstValue) {
       myStringValue = 'الأول' ؛
    } آخر {
       myStringValue = 'الآخر'
    }
    // هذا سيعطي الخطأ أدناه
    لا يمكن التنازل عن النوع "الآخر" للكتابة "أولاً" | "ثانيا"'
    (خاصية) AppComponent.myValue: "الأول" | "ثانيا"

    الصورة الاكبر

    إدارة الدولة

    فكر في استخدام @ ngrx / store للحفاظ على حالة التطبيق الخاص بك و @ ngrx / effects كنموذج التأثير الجانبي للمتجر. يتم وصف التغييرات التي تم إجراؤها على الحالة من خلال الإجراءات ويتم إجراء التغييرات بواسطة وظائف خالصة تسمى المخفضات.

    لماذا ا؟

    @ ngrx / store يعزل كل المنطق المتعلق بالحالة في مكان واحد ويجعله ثابتًا عبر التطبيق. كما أن لديها آلية تحفيظ في المكان عند الوصول إلى المعلومات في المتجر مما يؤدي إلى تطبيق أكثر فعالية. @ ngrx / store بالإضافة إلى إستراتيجية اكتشاف التغيير الخاصة بـ Angular تؤدي إلى تطبيق أسرع.

    حالة غير قابلة للتغيير

    عند استخدام @ ngrx / store ، فكر في استخدام تجميد ngrx-store لتجعل الحالة غير قابلة للتغيير. يمنع ngrx-store-freeze تجميد الحالة من خلال طرح استثناء. هذا يتجنب طفرة عرضية للدولة مما يؤدي إلى عواقب غير مرغوب فيها.

    لماذا ا؟

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

    المزاح

    Jest هو إطار اختبار وحدة Facebook لجافا سكريبت. يجعل اختبار الوحدة أسرع عن طريق موازاة الاختبار عبر قاعدة الكود. من خلال وضع المراقبة الخاص به ، يتم تشغيل الاختبارات المتعلقة بالتغييرات التي تم إجراؤها فقط ، مما يجعل حلقة التعليقات للاختبار أقصر. يوفر Jest أيضًا تغطية الشفرة للاختبارات وهو مدعوم على VS Code و Webstorm.

    يمكنك استخدام إعداد مسبق لـ Jest والذي سيقوم بمعظم الرفع الثقيل لك عند إعداد Jest في مشروعك.

    الكرمة

    الكرمة هي عداء اختبار طوره فريق AngularJS. يتطلب متصفحًا حقيقيًا / DOM لإجراء الاختبارات. يمكن أن تعمل أيضا على متصفحات مختلفة. Jest لا يحتاج إلى chrome مقطوعة الرأس / phantomjs لإجراء الاختبارات ويتم تشغيله في Node النقي.

    عالمي

    إذا لم تجعل تطبيقك تطبيقًا عالميًا ، فقد حان الوقت الآن للقيام بذلك. يتيح لك Angular Universal تشغيل تطبيق Angular الخاص بك على الخادم ويقوم بالعرض من جانب الخادم (SSR) والذي يقدم صفحات HTML ثابتة سابقة التقديم. هذا يجعل التطبيق سريعًا جدًا حيث يعرض المحتوى على الشاشة على الفور تقريبًا ، دون الحاجة إلى الانتظار حتى يتم تحميل حزم JS والتحليل ، أو تحميل Angular.

    كما أنها صديقة لكبار المسئولين الاقتصاديين ، لأن Angular Universal يولد محتوى ثابتًا ويسهل على متتبعات الويب فهرسة التطبيق وجعله قابلاً للبحث دون تنفيذ JavaScript.

    لماذا ا؟

    العالمي يحسن أداء التطبيق الخاص بك بشكل كبير. لقد قمنا مؤخرًا بتحديث تطبيقنا للقيام بالعرض من جانب الخادم وذهب وقت تحميل الموقع من عدة ثوانٍ إلى عشرات الميلي ثانية!

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

    خاتمة

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

    شكرا لقرائتك! إذا استمتعت بهذا المقال ، فلا تتردد في to ومساعدة الآخرين في العثور عليه. لا تتردد في مشاركة أفكارك في قسم التعليقات أدناه. اتبعني على متوسط ​​أو تويتر لمزيد من المقالات. الناس الترميز سعيد! ️