Thực hành tốt nhất cho một ứng dụng Angular sạch sẽ và hiệu quả

Tôi đã làm việc trên một ứng dụng Angular quy mô lớn tại Trade Me, New Zealand trong một vài năm nay. Trong vài năm qua, nhóm của chúng tôi đã tinh chỉnh ứng dụng của chúng tôi cả về tiêu chuẩn và hiệu suất mã hóa để làm cho nó ở trạng thái tốt nhất có thể.

Bài viết này phác thảo các thực tiễn chúng tôi sử dụng trong ứng dụng của mình và có liên quan đến Angular, Typecript, RxJs và @ ngrx / store. Chúng tôi cũng sẽ thông qua một số hướng dẫn mã hóa chung để giúp làm cho ứng dụng sạch hơn.

1) trackBy

Khi sử dụng ngFor để lặp qua một mảng trong các mẫu, hãy sử dụng nó với chức năng trackBy sẽ trả về một định danh duy nhất cho mỗi mục.

Tại sao?

Khi một mảng thay đổi, Angular sẽ kết xuất lại toàn bộ cây DOM. Nhưng nếu bạn sử dụng trackBy, Angular sẽ biết phần tử nào đã thay đổi và sẽ chỉ thực hiện thay đổi DOM cho phần tử cụ thể đó.

Để được giải thích chi tiết về điều này, xin vui lòng tham khảo bài viết này của Netanel Basal.

Trước

  • {{item}}
  • Sau

    // trong mẫu
  • {{item}}
  • // trong thành phần
    trackByFn (chỉ mục, mục) {
       trả lại hàng.id; // id duy nhất tương ứng với mục
    }

    2) const vs cho

    Khi khai báo các biến, sử dụng const khi giá trị sẽ không được gán lại.

    Tại sao?

    Sử dụng let và const khi thích hợp làm cho ý định của khai báo rõ ràng hơn. Nó cũng sẽ giúp xác định các vấn đề khi một giá trị được gán lại thành một hằng số vô tình bằng cách ném một lỗi thời gian biên dịch. Nó cũng giúp cải thiện khả năng đọc của mã.

    Trước

    let car = 'xe lố bịch';
    hãy để myCar = `$ của tôi {xe}`;
    hãy để yourCar = `$ {xe} của bạn;
    if (iHaveMoreThanOneCar) {
       myCar = `$ {myCar} s`;
    }
    if (youHaveMoreThanOneCar) {
       yourCar = `$ {youCar} s`;
    }

    Sau

    // giá trị của xe không được gán lại, vì vậy chúng ta có thể biến nó thành const
    const car = 'xe lố bịch';
    hãy để myCar = `$ của tôi {xe}`;
    hãy để yourCar = `$ {xe} của bạn;
    if (iHaveMoreThanOneCar) {
       myCar = `$ {myCar} s`;
    }
    if (youHaveMoreThanOneCar) {
       yourCar = `$ {youCar} s`;
    }

    3) Toán tử dễ uốn

    Sử dụng toán tử có thể điều chỉnh khi sử dụng toán tử RxJs.

    Tại sao?

    Các toán tử có thể thay đổi được có nghĩa là cây có thể chuyển đổi, chỉ có mã chúng ta cần thực thi sẽ được đưa vào khi chúng được nhập.

    Điều này cũng giúp dễ dàng xác định các toán tử không sử dụng trong các tệp.

    Lưu ý: Điều này cần phiên bản Angular 5.5+.

    Trước

    nhập 'rxjs / add / toán tử / bản đồ';
    nhập 'rxjs / add / toán tử / mất';
    iAmAnObservable
        .map (value => value.item)
        .take (1);

    Sau

    nhập {map, lấy} từ 'rxjs / toán tử';
    iAmAnObservable
        .ống(
           bản đồ (giá trị => value.item),
           lấy (1)
         );

    4) Cô lập API hack

    Không phải tất cả các API đều là bằng chứng đạn - đôi khi chúng ta cần thêm một số logic trong mã để bù đắp các lỗi trong API. Thay vì có các hack trong các thành phần cần thiết, tốt hơn là cách ly chúng ở một nơi - như trong một dịch vụ và sử dụng dịch vụ từ thành phần đó.

    Tại sao?

    Điều này giúp giữ cho các hack hack gần với API API, càng gần với nơi yêu cầu mạng được thực hiện càng tốt. Bằng cách này, ít mã của bạn đang xử lý mã không bị hack. Ngoài ra, đây là một nơi mà tất cả các hack sống và dễ dàng tìm thấy chúng hơn. Khi sửa các lỗi trong API, việc tìm kiếm chúng trong một tệp sẽ dễ dàng hơn thay vì tìm kiếm các bản hack có thể lây lan trên cơ sở mã.

    Bạn cũng có thể tạo các thẻ tùy chỉnh như API_FIX tương tự TODO và gắn thẻ các bản sửa lỗi với nó để dễ tìm hơn.

    5) Đăng ký trong mẫu

    Tránh đăng ký vào các đài quan sát từ các thành phần và thay vào đó đăng ký vào các đài quan sát từ mẫu.

    Tại sao?

    ống async tự hủy đăng ký và nó làm cho mã đơn giản hơn bằng cách loại bỏ nhu cầu quản lý đăng ký theo cách thủ công. Nó cũng làm giảm nguy cơ vô tình quên không đăng ký một thuê bao trong thành phần, điều này sẽ gây rò rỉ bộ nhớ. Rủi ro này cũng có thể được giảm thiểu bằng cách sử dụng quy tắc xơ xác để phát hiện các vật quan sát không được đăng ký.

    Điều này cũng ngăn các thành phần không ở trạng thái và đưa ra các lỗi trong đó dữ liệu bị đột biến bên ngoài đăng ký.

    Trước

    // bản mẫu

    {{textToDisplay}}

    // thành phần
    iAmAnObservable
        .ống(
           bản đồ (giá trị => value.item),
           TakeUntil (this._destroyed $)
         )
        .subscribe (item => this.textToDisplay = item);

    Sau

    // bản mẫu

    {{textToDisplay $ | không đồng bộ}}

    // thành phần
    this.textToDisplay $ = iAmAnObservable
        .ống(
           bản đồ (giá trị => value.item)
         );

    6) Dọn dẹp đăng ký

    Khi đăng ký vào các vật quan sát, luôn đảm bảo rằng bạn hủy đăng ký chúng một cách thích hợp bằng cách sử dụng các toán tử như Take, TakeUntil, v.v.

    Tại sao?

    Không hủy đăng ký khỏi các thiết bị quan sát sẽ dẫn đến rò rỉ bộ nhớ không mong muốn vì luồng có thể quan sát bị bỏ ngỏ, có khả năng ngay cả sau khi một thành phần đã bị hủy / người dùng đã điều hướng đến một trang khác.

    Thậm chí tốt hơn, tạo một quy tắc lint để phát hiện các vật quan sát không bị hủy đăng ký.

    Trước

    iAmAnObservable
        .ống(
           bản đồ (giá trị => value.item)
         )
        .subscribe (item => this.textToDisplay = item);

    Sau

    Sử dụng TakeUntil khi bạn muốn lắng nghe các thay đổi cho đến khi một giá trị quan sát khác phát ra một giá trị:

    riêng tư _destroyed $ = Chủ đề mới ();
    công ngOnInit (): void {
        iAmAnObservable
        .ống(
           bản đồ (giá trị => value.item)
          // Chúng tôi muốn nghe iAmAnObservable cho đến khi thành phần bị hủy,
           TakeUntil (this._destroyed $)
         )
        .subscribe (item => this.textToDisplay = item);
    }
    công ngOnDestroy (): void {
        this ._destroyed $ .next ();
        this ._destroyed $ .complete ();
    }

    Sử dụng một chủ đề riêng như thế này là một mẫu để quản lý hủy đăng ký nhiều vật quan sát trong thành phần.

    Sử dụng Take khi bạn chỉ muốn giá trị đầu tiên được phát ra bởi có thể quan sát được:

    iAmAnObservable
        .ống(
           bản đồ (giá trị => value.item),
           lấy (1),
           TakeUntil (this._destroyed $)
        )
        .subscribe (item => this.textToDisplay = item);

    Lưu ý việc sử dụng TakeUntil với Take here. Điều này là để tránh rò rỉ bộ nhớ gây ra khi đăng ký đã nhận được một giá trị trước khi thành phần bị phá hủy. Nếu không có TakeUntil ở đây, đăng ký vẫn sẽ tồn tại cho đến khi nhận được giá trị đầu tiên, nhưng vì thành phần này đã bị phá hủy, nó sẽ không bao giờ nhận được giá trị - dẫn đến rò rỉ bộ nhớ.

    7) Sử dụng các toán tử thích hợp

    Khi sử dụng toán tử làm phẳng với các vật quan sát của bạn, hãy sử dụng toán tử thích hợp cho tình huống.

    switchMap: khi bạn muốn bỏ qua các phát thải trước đó khi có phát thải mới

    mergeMap: khi bạn muốn xử lý đồng thời tất cả lượng khí thải

    concatMap: khi bạn muốn xử lý khí thải lần lượt khi chúng được phát ra

    DrainMap: khi bạn muốn hủy tất cả lượng khí thải mới trong khi xử lý một phát xạ trước đó

    Để được giải thích chi tiết hơn về điều này, xin vui lòng tham khảo bài viết này của Nicholas Jamieson.

    Tại sao?

    Sử dụng một toán tử duy nhất khi có thể thay vì kết hợp nhiều toán tử khác để đạt được hiệu quả tương tự có thể khiến ít mã được chuyển đến người dùng. Sử dụng các toán tử sai có thể dẫn đến hành vi không mong muốn, vì các toán tử khác nhau xử lý các quan sát theo những cách khác nhau.

    8) Tải chậm

    Khi có thể, hãy cố gắng lười tải các mô-đun trong ứng dụng Angular của bạn. Tải chậm là khi bạn tải một cái gì đó chỉ khi nó được sử dụng, ví dụ, chỉ tải một thành phần khi nó được nhìn thấy.

    Tại sao?

    Điều này sẽ giảm kích thước của ứng dụng sẽ được tải và có thể cải thiện thời gian khởi động ứng dụng bằng cách không tải các mô-đun không được sử dụng.

    Trước

    // app.routing.ts
    {path: 'not-lazy-load', thành phần: NotLazyLoadedComponent}

    Sau

    // app.routing.ts
    {
      đường dẫn: 'lười tải',
      loadChildren: 'lazy-load.module # LazyLoadModule'
    }
    // lazy-load.module.ts
    nhập {NgModule} từ '@ angular / core';
    nhập {CommonModule} từ '@ angular / common';
    nhập {RouterModule} từ '@ angular / router';
    nhập {LazyLoadComponent} từ './lazy-load.component';
    @NgModule ({
      nhập khẩu: [
        CommonModule,
        RouterModule.forChild ([
             {
                 con đường: '',
                 thành phần: LazyLoadComponent
             }
        ])
      ],
      tờ khai: [
        LazyLoadComponent
      ]
    })
    lớp xuất khẩu LazyModule {}

    9) Tránh có đăng ký bên trong đăng ký

    Đôi khi bạn có thể muốn các giá trị từ nhiều hơn một quan sát được để thực hiện một hành động. Trong trường hợp này, tránh đăng ký vào một người có thể quan sát được trong khối đăng ký của người khác có thể quan sát được. Thay vào đó, sử dụng các toán tử xích thích hợp. Toán tử chuỗi chạy trên các đài quan sát từ toán tử trước chúng. Một số toán tử chuỗi là: withLatestFrom, kết hợpLatest, v.v.

    Trước

    đầu tiên có thể quan sát được $ .pipe (
       lấy (1)
    )
    .subscribe (FirstValue => {
        secondObservable $ .pipe (
            lấy (1)
        )
        .subscribe (secondValue => {
            console.log (`Các giá trị kết hợp là: $ {firstValue} & $ {secondValue}`);
        });
    });

    Sau

    đầu tiên có thể quan sát được $ .pipe (
        withLatestFrom (secondObservable $),
        Đầu tiên()
    )
    .subscribe (([FirstValue, secondValue]) => {
        console.log (`Các giá trị kết hợp là: $ {firstValue} & $ {secondValue}`);
    });

    Tại sao?

    Mùi mã / độ dễ đọc / độ phức tạp của mã: Không sử dụng RxJ đến mức tối đa, cho thấy nhà phát triển không quen thuộc với diện tích bề mặt API của RxJs.

    Hiệu suất: Nếu các vật thể quan sát bị lạnh, nó sẽ đăng ký vào FirstObservable, đợi cho đến khi nó hoàn thành, THEN bắt đầu công việc thứ hai có thể quan sát được. Nếu đây là các yêu cầu mạng, nó sẽ hiển thị dưới dạng đồng bộ / thác nước.

    10) Tránh bất kỳ; gõ mọi thứ;

    Luôn luôn khai báo các biến hoặc hằng với một loại khác hơn bất kỳ.

    Tại sao?

    Khi khai báo các biến hoặc hằng trong Bản mô tả mà không cần gõ, việc gõ biến / hằng sẽ được suy ra bởi giá trị được gán cho nó. Điều này sẽ gây ra những vấn đề ngoài ý muốn. Một ví dụ kinh điển là:

    const x = 1;
    const y = 'a';
    const z = x + y;
    console.log (`Giá trị của z là: $ {z}`
    // Đầu ra
    Giá trị của z là 1a

    Điều này có thể gây ra các vấn đề không mong muốn khi bạn mong đợi y cũng là một số. Những vấn đề này có thể tránh được bằng cách gõ các biến một cách thích hợp.

    const x: số = 1;
    const y: số = 'a';
    const z: số = x + y;
    // Điều này sẽ đưa ra một lỗi biên dịch cho biết:
    Nhập '"a"' không thể gán cho loại 'số'.
    const y: số

    Bằng cách này, chúng ta có thể tránh các lỗi gây ra bởi các loại bị thiếu.

    Một ưu điểm khác của việc đánh máy tốt trong ứng dụng của bạn là nó giúp việc tái cấu trúc dễ dàng và an toàn hơn.

    Xem xét ví dụ này:

    công ngOnInit (): void {
        hãy để myFlashObject = {
            tên: 'Tên mát mẻ của tôi',
            tuổi: 'Tuổi mát mẻ của tôi',
            loc: 'Vị trí tuyệt vời của tôi'
        }
        this. processObject (myFlashObject);
    }
    công khai processObject (myObject: any): void {
        console.log (`Tên: $ {myObject.name}`);
        console.log (`Tuổi: $ {myObject.age}`);
        console.log (`Vị trí: $ {myObject.loc}`);
    }
    // Đầu ra
    Tên: Tên mát mẻ của tôi
    Tuổi: Tuổi mát mẻ của tôi
    Địa điểm: Vị trí tuyệt vời của tôi

    Hãy để chúng tôi nói, chúng tôi muốn đổi tên vị trí tài sản thành vị trí trong myFlashObject:

    công ngOnInit (): void {
        hãy để myFlashObject = {
            tên: 'Tên mát mẻ của tôi',
            tuổi: 'Tuổi mát mẻ của tôi',
            địa điểm: 'Vị trí tuyệt vời của tôi'
        }
        this. processObject (myFlashObject);
    }
    công khai processObject (myObject: any): void {
        console.log (`Tên: $ {myObject.name}`);
        console.log (`Tuổi: $ {myObject.age}`);
        console.log (`Vị trí: $ {myObject.loc}`);
    }
    // Đầu ra
    Tên: Tên mát mẻ của tôi
    Tuổi: Tuổi mát mẻ của tôi
    Địa điểm: không xác định

    Nếu chúng ta không gõ vào myFlashObject, nó nghĩ rằng vị trí thuộc tính trên myFlashObject chỉ là không xác định chứ không phải là thuộc tính hợp lệ.

    Nếu chúng ta có một kiểu gõ cho myFlashObject, chúng ta sẽ gặp một lỗi thời gian biên dịch đẹp như hình dưới đây:

    loại FlashObject = {
        tên: chuỗi,
        tuổi: chuỗi,
        vị trí: chuỗi
    }
    công ngOnInit (): void {
        hãy để myFlashObject: FlashObject = {
            tên: 'Tên mát mẻ của tôi',
            tuổi: 'Tuổi mát mẻ của tôi',
            // Dịch lỗi
            Nhập '{tên: chuỗi; tuổi: chuỗi; loc: chuỗi; } 'không được gán để nhập' FlashObjectType '.
            Đối tượng bằng chữ chỉ có thể chỉ định các thuộc tính đã biết và 'loc' không tồn tại trong loại 'FlashObjectType'.
            loc: 'Vị trí tuyệt vời của tôi'
        }
        this. processObject (myFlashObject);
    }
    công khai processObject (myObject: FlashObject): void {
        console.log (`Tên: $ {myObject.name}`);
        console.log (`Tuổi: $ {myObject.age}`)
        // Dịch lỗi
        Thuộc tính 'loc' không tồn tại trên loại 'FlashObjectType'.
        console.log (`Vị trí: $ {myObject.loc}`);
    }

    Nếu bạn đang bắt đầu một dự án mới, đáng để đặt nghiêm ngặt: true trong tệp tsconfig.json để cho phép tất cả các tùy chọn kiểm tra loại nghiêm ngặt.

    11) Sử dụng các quy tắc xơ vải

    tslint có nhiều tùy chọn khác nhau được xây dựng sẵn như không có, không có số ma thuật, không có bàn điều khiển, v.v. mà bạn có thể định cấu hình trong tslint.json để thực thi các quy tắc nhất định trong cơ sở mã của mình.

    Tại sao?

    Có các quy tắc lint tại chỗ có nghĩa là bạn sẽ gặp một lỗi tốt khi bạn đang làm điều gì đó mà bạn không nên làm. Điều này sẽ thực thi tính nhất quán trong ứng dụng và khả năng đọc của bạn. Vui lòng tham khảo tại đây để biết thêm các quy tắc mà bạn có thể cấu hình.

    Một số quy tắc lint thậm chí đi kèm với các bản sửa lỗi để khắc phục lỗi lint. Nếu bạn muốn cấu hình quy tắc lint tùy chỉnh của riêng bạn, bạn cũng có thể làm điều đó. Vui lòng tham khảo bài viết này của Craig Spence về cách viết quy tắc lint tùy chỉnh của riêng bạn bằng TSQuery.

    Trước

    công ngOnInit (): void {
        console.log ('Tôi là một thông điệp nhật ký giao diện điều khiển nghịch ngợm');
        console.warn ('Tôi là một thông điệp cảnh báo giao diện điều khiển nghịch ngợm');
        console.error ('Tôi là một thông báo lỗi console nghịch ngợm');
    }
    // Đầu ra
    Không có lỗi, in dưới đây trên cửa sổ giao diện điều khiển:
    Tôi là một tin nhắn điều khiển nghịch ngợm
    Tôi là một tin nhắn cảnh báo giao diện điều khiển nghịch ngợm
    Tôi là một thông báo lỗi console nghịch ngợm

    Sau

    // tslint.json
    {
        "quy tắc": {
            .......
            "không có bàn điều khiển": [
                 thật,
                 "log", // không cho phép console.log
                 "cảnh báo" // không cho phép console.warn
            ]
       }
    }
    // ..component.ts
    công ngOnInit (): void {
        console.log ('Tôi là một thông điệp nhật ký giao diện điều khiển nghịch ngợm');
        console.warn ('Tôi là một thông điệp cảnh báo giao diện điều khiển nghịch ngợm');
        console.error ('Tôi là một thông báo lỗi console nghịch ngợm');
    }
    // Đầu ra
    Lỗi lint cho các câu lệnh console.log và console.warn và không có lỗi cho console.error vì nó không được đề cập trong cấu hình
    Các cuộc gọi đến 'console.log' không được phép.
    Các cuộc gọi đến 'console.warn' không được phép.

    12) Các thành phần nhỏ có thể tái sử dụng

    Trích xuất các mảnh có thể được tái sử dụng trong một thành phần và làm cho nó một thành phần mới. Làm cho thành phần càng ngu ngốc càng tốt, vì điều này sẽ làm cho nó hoạt động trong nhiều tình huống hơn. Làm cho một thành phần câm có nghĩa là thành phần đó không có logic đặc biệt nào trong đó và hoạt động hoàn toàn dựa trên các đầu vào và đầu ra được cung cấp cho nó.

    Theo nguyên tắc chung, đứa trẻ cuối cùng trong cây thành phần sẽ là người ngu ngốc nhất trong tất cả.

    Tại sao?

    Các thành phần có thể tái sử dụng làm giảm sự trùng lặp mã do đó giúp duy trì và thay đổi dễ dàng hơn.

    Các thành phần câm đơn giản hơn, vì vậy chúng ít có khả năng có lỗi. Các thành phần ngu ngốc khiến bạn suy nghĩ nhiều hơn về API thành phần công cộng và giúp phát hiện các mối lo ngại lẫn lộn.

    13) Các thành phần chỉ nên đối phó với logic hiển thị

    Tránh có bất kỳ logic nào ngoài logic hiển thị trong thành phần của bạn bất cứ khi nào bạn có thể và làm cho thành phần đó chỉ xử lý logic hiển thị.

    Tại sao?

    Các thành phần được thiết kế cho mục đích trình bày và kiểm soát những gì chế độ xem nên làm. Bất kỳ logic kinh doanh nào cũng cần được trích xuất thành các phương thức / dịch vụ riêng của nó khi thích hợp, tách logic kinh doanh khỏi logic xem.

    Logic nghiệp vụ thường dễ dàng hơn để kiểm tra đơn vị khi được trích xuất ra một dịch vụ và có thể được sử dụng lại bởi bất kỳ thành phần nào khác cần cùng logic kinh doanh được áp dụng.

    14) Tránh các phương pháp dài

    Các phương pháp dài thường chỉ ra rằng họ đang làm quá nhiều thứ. Cố gắng sử dụng Nguyên tắc trách nhiệm duy nhất. Bản thân phương pháp có thể đang làm một việc, nhưng bên trong nó, có một vài hoạt động khác có thể xảy ra. Chúng ta có thể trích xuất các phương thức đó thành phương thức riêng của chúng và làm cho chúng thực hiện từng thứ một và sử dụng chúng thay thế.

    Tại sao?

    Các phương pháp dài khó đọc, hiểu và duy trì. Họ cũng dễ bị lỗi, vì thay đổi một điều có thể ảnh hưởng đến rất nhiều thứ khác trong phương pháp đó. Họ cũng làm cho việc tái cấu trúc (vốn là một điều quan trọng trong bất kỳ ứng dụng nào).

    Điều này đôi khi được đo là độ phức tạp cyclom phức tạp. Ngoài ra còn có một số quy tắc TSLint để phát hiện độ phức tạp theo chu kỳ / nhận thức, mà bạn có thể sử dụng trong dự án của mình để tránh lỗi và phát hiện mùi mã và các vấn đề về bảo trì.

    15) KHÔ

    Đừng tự biên tự diễn. Hãy chắc chắn rằng bạn không có cùng một mã được sao chép vào các vị trí khác nhau trong cơ sở mã. Trích xuất mã lặp lại và sử dụng nó thay cho mã lặp lại.

    Tại sao?

    Có cùng một mã ở nhiều nơi có nghĩa là nếu chúng ta muốn thay đổi logic trong mã đó, chúng ta phải thực hiện nó ở nhiều nơi. Điều này gây khó khăn cho việc bảo trì và cũng dễ bị lỗi trong đó chúng ta có thể bỏ lỡ việc cập nhật nó trong tất cả các lần xuất hiện. Phải mất nhiều thời gian hơn để thay đổi logic và kiểm tra nó cũng là một quá trình dài.

    Trong những trường hợp đó, trích xuất mã lặp lại và sử dụng nó để thay thế. Điều này có nghĩa là chỉ có một nơi để thay đổi và một điều để kiểm tra. Có ít mã trùng lặp được chuyển đến người dùng có nghĩa là ứng dụng sẽ nhanh hơn.

    16) Thêm cơ chế lưu trữ

    Khi thực hiện các cuộc gọi API, phản hồi từ một số trong số chúng không thay đổi thường xuyên. Trong những trường hợp đó, bạn có thể thêm một cơ chế lưu trữ và lưu trữ giá trị từ API. Khi một yêu cầu khác cho cùng API được thực hiện, hãy kiểm tra xem có giá trị nào cho nó trong bộ đệm không và nếu có, hãy sử dụng nó. Nếu không, hãy thực hiện cuộc gọi API và lưu trữ kết quả.

    Nếu các giá trị thay đổi nhưng không thường xuyên, bạn có thể đưa ra thời gian bộ đệm trong đó bạn có thể kiểm tra khi nó được lưu trong bộ nhớ cache lần cuối và quyết định có gọi API hay không.

    Tại sao?

    Có một cơ chế lưu trữ có nghĩa là tránh các cuộc gọi API không mong muốn. Bằng cách chỉ thực hiện các lệnh gọi API khi được yêu cầu và tránh trùng lặp, tốc độ của ứng dụng sẽ được cải thiện vì chúng tôi không phải chờ mạng. Điều đó cũng có nghĩa là chúng tôi không tải xuống cùng một thông tin nhiều lần.

    17) Tránh logic trong các mẫu

    Nếu bạn có bất kỳ loại logic nào trong các mẫu của mình, ngay cả khi đó là một mệnh đề && đơn giản, thì tốt nhất là trích xuất nó ra thành phần của nó.

    Tại sao?

    Có logic trong mẫu có nghĩa là không thể đơn vị kiểm tra nó và do đó nó dễ bị lỗi hơn khi thay đổi mã mẫu.

    Trước

    // bản mẫu
    

    Trạng thái: Nhà phát triển

    // thành phần
    công ngOnInit (): void {
        this .role = 'nhà phát triển';
    }

    Sau

    // bản mẫu
    

    Trạng thái: Nhà phát triển

    // thành phần
    công ngOnInit (): void {
        this .role = 'nhà phát triển';
        this .showDeveloperStatus = true;
    }

    18) Dây phải an toàn

    Nếu bạn có một biến chuỗi kiểu chỉ có thể có một tập hợp các giá trị, thay vì khai báo nó là kiểu chuỗi, bạn có thể khai báo danh sách các giá trị có thể là kiểu.

    Tại sao?

    Bằng cách khai báo loại biến một cách thích hợp, chúng ta có thể tránh được các lỗi trong khi viết mã trong thời gian biên dịch thay vì trong thời gian chạy.

    Trước

    riêng tư myStringValue: chuỗi;
    if (itShouldHaveFirstValue) {
       myStringValue = 'Đầu tiên';
    } khác {
       myStringValue = 'Thứ hai'
    }

    Sau

    riêng tư myStringValue: 'Đầu tiên' | 'Thứ hai';
    if (itShouldHaveFirstValue) {
       myStringValue = 'Đầu tiên';
    } khác {
       myStringValue = 'Khác'
    }
    // Điều này sẽ đưa ra lỗi dưới đây
    Loại '"Khác"' không thể gán cho loại '"Đầu tiên" | "Thứ hai"'
    (tài sản) AppComponent.myValue: "Đầu tiên" | "Thứ hai"

    Hình ảnh lớn hơn

    Quản lý nhà nước

    Cân nhắc sử dụng @ ngrx / store để duy trì trạng thái ứng dụng của bạn và @ ngrx / hiệu ứng làm mô hình hiệu ứng phụ cho cửa hàng. Thay đổi trạng thái được mô tả bằng các hành động và các thay đổi được thực hiện bởi các hàm thuần túy gọi là bộ giảm tốc.

    Tại sao?

    @ ngrx / store cô lập tất cả logic liên quan đến trạng thái ở một nơi và làm cho nó nhất quán trên ứng dụng. Nó cũng có cơ chế ghi nhớ khi truy cập thông tin trong cửa hàng dẫn đến một ứng dụng hiệu quả hơn. @ ngrx / store kết hợp với chiến lược phát hiện thay đổi của Angular dẫn đến một ứng dụng nhanh hơn.

    Trạng thái bất biến

    Khi sử dụng @ ngrx / store, hãy cân nhắc sử dụng ngrx-store-freeze để làm cho trạng thái bất biến. ngrx-store-freeze ngăn chặn trạng thái bị đột biến bằng cách ném một ngoại lệ. Điều này tránh sự đột biến ngẫu nhiên của nhà nước dẫn đến hậu quả không mong muốn.

    Tại sao?

    Trạng thái đột biến trong các thành phần dẫn đến ứng dụng hoạt động không nhất quán tùy thuộc vào các thành phần thứ tự được tải. Nó phá vỡ mô hình tinh thần của mô hình redux. Thay đổi có thể bị ghi đè nếu trạng thái cửa hàng thay đổi và phát lại. Tách các mối quan tâm - các thành phần là lớp xem, chúng không nên biết cách thay đổi trạng thái.

    Jest

    Jest là khung thử nghiệm đơn vị Facebook của JavaScript. Nó làm cho kiểm thử đơn vị nhanh hơn bằng cách kiểm tra song song chạy trên cơ sở mã. Với chế độ đồng hồ của nó, chỉ có các thử nghiệm liên quan đến các thay đổi được thực hiện, điều này làm cho vòng phản hồi cho cách thử nghiệm ngắn hơn. Jest cũng cung cấp phạm vi bảo hiểm mã của các bài kiểm tra và được hỗ trợ trên VS Code và Webstorm.

    Bạn có thể sử dụng một cài đặt trước cho Jest sẽ thực hiện hầu hết các công việc nặng nhọc cho bạn khi thiết lập Jest trong dự án của bạn.

    Nghiệp

    Karma là một người chạy thử nghiệm được phát triển bởi nhóm AngularJS. Nó đòi hỏi một trình duyệt / DOM thực sự để chạy thử nghiệm. Nó cũng có thể chạy trên các trình duyệt khác nhau. Jest doesn không cần chrome không đầu / ph Phantomjs để chạy các bài kiểm tra và nó chạy trong Node thuần túy.

    phổ cập

    Nếu bạn thiên đường biến ứng dụng của bạn thành một ứng dụng phổ quát, bây giờ là thời điểm tốt để làm điều đó. Angular Universal cho phép bạn chạy ứng dụng Angular của mình trên máy chủ và thực hiện kết xuất phía máy chủ (SSR) để phục vụ các trang html được kết xuất trước tĩnh. Điều này làm cho ứng dụng trở nên cực nhanh vì nó hiển thị nội dung trên màn hình gần như ngay lập tức, mà không phải chờ các gói JS tải và phân tích, hoặc để Angular khởi động.

    Nó cũng thân thiện với SEO, vì Angular Universal tạo nội dung tĩnh và giúp trình thu thập dữ liệu web dễ dàng hơn trong việc lập chỉ mục ứng dụng và làm cho nó có thể tìm kiếm mà không cần thực thi JavaScript.

    Tại sao?

    Universal cải thiện hiệu suất của ứng dụng của bạn một cách quyết liệt. Gần đây chúng tôi đã cập nhật ứng dụng của mình để thực hiện kết xuất phía máy chủ và thời gian tải trang web đã tăng từ vài giây đến hàng chục mili giây !!

    Nó cũng cho phép trang web của bạn hiển thị chính xác trong các đoạn xem trước phương tiện truyền thông xã hội. Sơn có ý nghĩa đầu tiên thực sự nhanh và làm cho nội dung hiển thị cho người dùng mà không có bất kỳ sự chậm trễ không mong muốn nào.

    Phần kết luận

    Xây dựng các ứng dụng là một hành trình không ngừng, và ở đó, luôn luôn có chỗ để cải thiện mọi thứ. Danh sách tối ưu hóa này là một nơi tốt để bắt đầu, và áp dụng các mô hình này một cách nhất quán sẽ làm cho nhóm của bạn hài lòng. Người dùng của bạn cũng sẽ yêu bạn vì trải nghiệm tốt đẹp với ứng dụng ít lỗi và hiệu suất của bạn.

    Cảm ơn bạn đã đọc! Nếu bạn thích bài viết này, xin vui lòng và giúp người khác tìm thấy nó. Xin đừng ngần ngại chia sẻ suy nghĩ của bạn trong phần bình luận bên dưới. Theo dõi tôi trên Medium hoặc Twitter để biết thêm bài viết. Chúc mọi người mã hóa vui vẻ !! ️