나는 ( Pete Hunt : React : Rethinking best practice-JSConf EU 2013 ) 에서 React dev 강연을 보았고 발표자는 모델의 더러운 확인이 느릴 수 있다고 언급했습니다. 그러나 대부분의 경우 가상 DOM이 모델보다 커야하므로 가상 DOM 간의 차이를 계산하는 것이 실제로 성능이 떨어 집니까?
Virtual DOM (특히 서버 측 렌더링)의 잠재력을 정말 좋아하지만 모든 장단점을 알고 싶습니다.
나는 ( Pete Hunt : React : Rethinking best practice-JSConf EU 2013 ) 에서 React dev 강연을 보았고 발표자는 모델의 더러운 확인이 느릴 수 있다고 언급했습니다. 그러나 대부분의 경우 가상 DOM이 모델보다 커야하므로 가상 DOM 간의 차이를 계산하는 것이 실제로 성능이 떨어 집니까?
Virtual DOM (특히 서버 측 렌더링)의 잠재력을 정말 좋아하지만 모든 장단점을 알고 싶습니다.
답변:
저는 virtual-dom 모듈 의 기본 저자 이므로 귀하의 질문에 대답 할 수 있습니다. 실제로 해결해야 할 두 가지 문제가 있습니다.
React에서 각 구성 요소는 상태를 갖습니다. 이 상태는 녹아웃 또는 다른 MVVM 스타일 라이브러리에서 볼 수있는 관찰 가능과 같습니다. 기본적으로 반작용이 알고있는 경우 가 때이 데이터 변경 관찰 할 수 있기 때문에 장면을 다시 렌더링 할 수 있습니다. 정기적으로 데이터를 폴링하고 데이터 구조의 모든 값을 재귀 적으로 확인해야하기 때문에 더티 검사는 관찰 가능 항목보다 느립니다. 이에 비해 상태 값을 설정하면 일부 상태가 변경되었음을 리스너에게 알릴 수 있으므로 React는 단순히 상태에서 변경 이벤트를 수신하고 다시 렌더링을 대기시킬 수 있습니다.
가상 DOM은 DOM을 효율적으로 다시 렌더링하는 데 사용됩니다. 이것은 실제로 데이터 더러운 검사와 관련이 없습니다. 더티 검사가 있거나없는 가상 DOM을 사용하여 다시 렌더링 할 수 있습니다. 두 가상 트리 사이의 차이를 계산하는 데 약간의 오버 헤드가 있지만 가상 DOM 차이는 데이터가 변경되었는지 여부와 관계없이 DOM에서 업데이트해야 할 사항을 이해하는 것입니다. 실제로 diff 알고리즘은 더티 체커 자체 이지만 DOM이 더티인지를 확인하는 데 사용됩니다.
상태가 변경 될 때만 가상 트리를 다시 렌더링하는 것이 목표입니다. 따라서 옵저버 블을 사용하여 상태가 변경되었는지 확인하는 것은 불필요한 다시 렌더링을 방지하는 효율적인 방법으로, 불필요한 트리 차이가 많이 발생합니다. 아무것도 바뀌지 않았다면, 우리는 아무것도하지 않습니다.
가상 DOM은 마치 전체 장면을 다시 렌더링하는 것처럼 코드를 작성할 수 있기 때문에 좋습니다. 뒤에서 우리는 DOM을 업데이트하여 우리가 기대하는 방식을 보이는 패치 작업을 계산하려고합니다. 따라서 가상 DOM diff / patch 알고리즘 은 최적의 솔루션이 아니지만 응용 프로그램을 표현할 수있는 아주 좋은 방법입니다. 우리는 단지 우리가 원하는 것을 정확하게 선언하고 React / virtual-dom은 장면을 이렇게 보이게 만드는 방법을 연습 할 것입니다. 수동 DOM 조작을하거나 이전 DOM 상태에 대해 혼동하지 않아도됩니다. 전체 장면을 다시 렌더링 할 필요가 없으므로 패치하는 것보다 효율성이 떨어질 수 있습니다.
unnecessary re-renders
무엇입니까?
this.state.cats = 99
수 있었다면 Angular dirty가 $ scope 트리를 점검하는 것처럼 모델 변경을 점검하기 위해 dirty 점검이 여전히 필요합니다. 이것은 두 기술의 속도를 비교 한 것이 아니며, 백본 스타일 설정자가 있기 때문에 React가 더티 검사를하지 않는다는 진술 일뿐입니다.
최근에 React의 diff 알고리즘에 대한 자세한 기사를 읽었습니다 : http://calendar.perfplanet.com/2013/diff/ . 내가 이해 한 것에서 React를 빠르게 만드는 것은 다음과 같습니다.
더티 체크와 비교하여 IMO의 주요 차이점은 다음과 같습니다.
모델 더티 검사 : React 컴포넌트는 setState
호출 될 때마다 명시 적으로 더티로 설정 되므로 여기에 데이터를 비교할 필요가 없습니다. 더티 검사의 경우 모델의 비교는 항상 각 다이제스트 루프에서 발생합니다.
DOM 업데이트 : DOM을 수정하면 CSS 스타일, 레이아웃을 적용하고 계산하기 때문에 DOM 작업이 매우 비쌉니다. 불필요한 DOM 수정으로 절약 된 시간은 가상 DOM을 비교하는 데 소요되는 시간보다 길 수 있습니다.
두 번째 요점은 많은 양의 필드가 있거나 큰 목록이있는 것과 같은 사소한 모델에 훨씬 더 중요합니다. 복잡한 모델의 하나의 필드 변경으로 인해 전체 뷰 / 템플릿 대신 해당 필드와 관련된 DOM 요소에 필요한 조작 만 발생합니다.
$scope.$digest
다이제스트 사이클 당 여러 번 실행되므로 전체 데이터 비교의 여러 시간과 부분 가상 DOM 트리 비교의 단일 시간입니다.
Virtual DOM (특히 서버 측 렌더링)의 잠재력을 정말 좋아하지만 모든 장단점을 알고 싶습니다.
-OP
리 액트 만이 DOM 조작 라이브러리가 아닙니다. 자세한 설명과 벤치 마크가 포함 된 Auth0 의이 기사를 읽고 대안을 이해하는 것이 좋습니다 . 나는 당신이 요구 한대로 여기에 그들의 장단점을 강조하겠습니다 :
React.js의 가상 DOM
찬성
- 빠르고 효율적인 "확산"알고리즘
- 다중 프론트 엔드 (JSX, 하이퍼 스크립트)
- 휴대 기기에서 실행할 수있을 정도로 가벼움
- 많은 견인력과 마음가짐
- React없이 사용할 수 있습니다 (예 : 독립 엔진으로)
단점
- DOM의 전체 메모리 사본 (더 높은 메모리 사용)
- 정적 요소와 동적 요소를 구분하지 않음
Ember.js의 글 림머
찬성
- 빠르고 효율적인 디핑 알고리즘
- 정적 요소와 동적 요소의 차별화
- Ember의 API와 100 % 호환 (기존 코드를 크게 업데이트하지 않고도 이점을 얻을 수 있음)
- DOM의 가벼운 인 메모리 표현
단점
- Ember에서만 사용되는 의미
- 하나의 프론트 엔드 만 사용 가능
증분 DOM
찬성
- 메모리 사용량 감소
- 간단한 API
- 많은 프론트 엔드 및 프레임 워크와 쉽게 통합 (처음부터 템플릿 엔진 백엔드로 의미)
단점
- 다른 라이브러리만큼 빠르지 않습니다 (논쟁의 여지가 있습니다. 아래 벤치 마크 참조).
- 적은 정신 공유 및 커뮤니티 사용
다음은 React 팀 멤버 Sebastian Markbåge의 의견입니다.
React는 출력에서 diffing을 수행합니다 (이것은 알려진 직렬화 가능 형식 인 DOM 속성). 즉, 소스 데이터는 모든 형식이 될 수 있습니다. 변경 불가능한 데이터 구조 및 클로저 내부 상태 일 수 있습니다.
각도 모델은 참조 투명도를 유지하지 않으므로 본질적으로 변경 가능합니다. 기존 모델을 변경하여 변경 사항을 추적합니다. 데이터 소스가 변경 불가능한 데이터이거나 매번 새로운 데이터 구조 (예 : JSON 응답) 인 경우 어떻게해야합니까?
더티 검사 및 Object.observe가 클로저 범위 상태에서 작동하지 않습니다.
이 두 가지는 기능 패턴에 매우 제한적입니다.
또한 모델의 복잡성이 커지면 더티 트래킹을 수행하는 데 점점 더 많은 비용이 듭니다. 그러나 React와 같은 시각적 트리에서만 차이를 내면 주어진 지점에서 화면에 표시 할 수있는 데이터 양이 UI에 의해 제한되기 때문에 그 수가 커지지 않습니다. 위의 피트 링크는 더 많은 퍼포먼스 혜택을 다룹니다.
Virtual Dom은 반응에 의해 발명되지 않습니다. HTML dom의 일부입니다. 가볍고 브라우저 별 구현 세부 사항에서 분리됩니다.
가상 DOM을 React의 로컬 및 단순화 된 HTML DOM 사본으로 생각할 수 있습니다. React가이 추상 세계 내에서 계산을 수행하고 "실제"DOM 작업을 생략 할 수 있습니다 (종종 느리고 브라우저에 따라 다름). 실제로 DOM과 가상 DOM 사이에는 큰 차이가 없습니다.
다음은 Virtual Dom이 사용되는 이유입니다 ( ReactJS의 소스 Virtual DOM ).
할 때 :
document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
- 브라우저는 HTML을 파싱해야합니다
- elementId의 자식 요소를 제거합니다
- DOM 값을 새로운 값으로 업데이트
- 부모와 자식의 CSS를 다시 계산하십시오.
- 레이아웃을 업데이트합니다. 즉, 화면에서 각 요소의 정확한 좌표
- 렌더 트리를 가로 질러 브라우저 디스플레이에 페인트
CSS와 변경된 레이아웃을 다시 계산하면 복잡한 알고리즘이 사용되며 성능에 영향을줍니다.
DOM 속성을 업데이트 할뿐만 아니라 가치. 알고리즘을 따릅니다.
이제 DOM을 10 번 직접 업데이트하면 위의 모든 단계가 하나씩 실행되고 DOM 알고리즘을 업데이트하면 DOM 값을 업데이트하는 데 시간이 걸립니다.
이것이 Real DOM이 가상 DOM보다 느린 이유입니다.