Angular와 함께 HMR을 사용할 때 주의할 점

7093 단어 angularrxjswebdev
Angular v11은 몇 주 전에 출시되었습니다. 이 릴리스의 주요 기능 중 하나는 앱 개발 중에 보다 쉽게 ​​활성화Hot Module Replacement (HMR)할 수 있다는 것입니다. --hmr 플래그를 사용하기만 하면 됩니다.
ng serve --hmr
release post을 인용하자면:

Now during development the latest changes to components, templates and styles will be instantly updated into the running application. All without requiring a full page refresh. Data typed into forms are preserved as well as scroll position providing a boost to developer productivity.



나는 그것을 시도하게되어 기뻤다! 최신 앱Angular CLI을 신속하게 설치하고 새로운 앱을 새로 생성했습니다.

내 초기 반응은 . HMR은 마술처럼 작동합니다!

하지만 HMR이 활성화된 상태에서 더 복잡한 앱이 어떻게 작동할지 궁금하기 시작했습니다. 나는 Angular’s Discord channel에서 이 질문을 하고 really good explanation by Lars Gyrup Brink Nielsen을 받았습니다. 인용하자면:

If the application hasn’t been built with Hot Module Replacement in mind from the beginning, it might need some work. The issue with HMR is when application state gets stale or memory leaks occur. This can happen for application- and platform-wide dependencies. We usually don’t think about cleaning up resources such as RxJS subscriptions, open Websockets, and so on at this level. But when we use HMR, the AppModule and all singleton services are asked to be destroyed. If the code doesn’t account for this, the same side effects can be triggered/active multiple times which causes different things to get out of sync.



정말 좋은 점!

HMR을 활성화하려면 다른 사고 방식이 필요합니다. 이는 앱을 개발하는 동안 수명이 긴 RxJS 구독, setInterval 기능, WebSockets 연결 등에 주의해야 할 필요성을 강조합니다. 또한 이 동작은 개발 단계에서만 발생한다는 점도 염두에 두어야 합니다.

문제를 설명하겠습니다.
AppComponent에 이 코드가 있다고 가정해 보겠습니다(앱의 "라이브"내내 파괴되지 않는 수명이 긴 구성 요소).

@Component({ ... })
export class AppComponent {
  ngOnInit() {
    interval(1000).subscribe(value => {
      console.log('value', value);
    });
  }
}

--hmr가 활성화된 상태에서 앱을 실행하면 다음과 같은 결과가 나타납니다.



여기 콘솔에 값을 기록하는 RxJS 구독이 있습니다. 구독이 지워지지는 않지만 구성 요소가 절대 파괴되지 않으므로 문제가 되지 않습니다. 지금까지 모든 것이 예상대로 작동합니다.

이제 코드를 약간 변경하고 파일을 저장하면 예전처럼 앱이 다시 빌드되지 않고 브라우저에서 전체 페이지를 강제로 새로고침합니다. 오히려 수정된 부분만 다시 빌드하고 실행 중인 앱에서 교체합니다.



그러나 이제 콘솔에 여러 구독의 로그가 표시됩니다. 왜 그런 겁니까? 이는 백그라운드에서 여전히 활성 상태인 이전 구독으로 인해 효과적으로 메모리 누수가 발생하기 때문입니다. HMR이 없었다면 앱이 다시 빌드되고 강제로 전체 브라우저 페이지가 새로 고쳐졌을 것이기 때문에 문제가 되지 않았을 것입니다.

위의 코드가 프로덕션에서 예상대로 실행된다는 점을 여기서 다시 강조하는 것이 중요합니다. 활성 구독은 하나만 있습니다. 이 문제는 HMR을 켠 상태에서 개발할 때만 발생합니다.

이 문제를 해결하려면 해당 구성 요소에 대한 ngOnDestroy 후크에서 구독을 지워야 합니다.

@Component({ ... })
export class AppComponent {
  sub: Subscription | undefined;

  ngOnInit() {
    this.sub = interval(1000).subscribe(value => {
      console.log('values', value);
    });
  }

  ngOnDestroy() {
    this.sub?.unsubscribe();
  }
}




이 변경 후에는 파일을 여러 번 저장해도 이전 구독이 제대로 지워졌기 때문에 콘솔에 기록되지 않습니다.

요약



나는 HMR을 좋아한다!

흥미롭고 훌륭하게 작동하며 개발자 경험을 향상시킵니다. 그러나 비용 없이는 오지 않습니다. HMR을 활성화하려면 애플리케이션을 개발할 때 사고방식을 약간 바꿔야 합니다. 우리는 다음을 기억해야 합니다.
  • 수명이 긴 RxJS 구독 지우기
  • 지우기setInterval 함수
  • WebSocket 연결 종료
  • 앱 및 플랫폼 전체 종속성(예: 구성 요소 및 서비스)을 적절하게 관리

  • 그렇게 하지 않으면 예상치 못한 결과와 메모리 누수가 발생하여 디버그하기 어려울 수 있습니다.

    HMR을 켤 때 주의해야 할 다른 사항이 있나요?


    사진 제공: Philip Brown on Unsplash

    좋은 웹페이지 즐겨찾기