JavaScript로 작성할 수 있는 모든 애플리케이션은 결국 JavaScript로 작성될 것입니다. 마찬가지로, 미니 프로그램을 사용하여 구현할 수 있는 모든 제품은 결국 미니 프로그램을 사용하여 구현될 것입니다. 그렇다면 작은 프로그램을 개발하는 방법은 무엇입니까? 다음 글은 전자상거래 프론트엔드 팀을 위한 5년간의 소규모 프로그램 개발 경험(10,000 단어 원칙 + 최적화 팁)을 요약하고 공유합니다. 모두에게 도움이 되기를 바랍니다!
WeChat 미니 프로그램의 기본 디자인에 대한 질문
- 듀얼 스레드 모델이 정확히 무엇인가요?
- 뷰와 로직을 어떻게 분리하나요?
- WXML 및 WXSS와 같은 이상한 구문을 사용하는 이유는 무엇입니까?
- 위험한 작업 API를 차단하는 방법은 무엇입니까?
- 통신 방법과 데이터 기반 뷰 업데이트 구현 방법은 무엇입니까?
- 듀얼 스레드 모델의 단점은 무엇인가요?
성능 문제
렌더링 스레드와 JS 엔진 스레드는 상호 배타적입니다. 차단 문제입니다. 장기간 JS 스크립트 실행은 UI 보기 렌더링에 직접적인 영향을 미쳐 페이지 지연이 발생합니다
보안 문제
위험한 HTML 태그(a, 스크립트) 및 JS API(함수, 평가, DOM API) , 공격자가 페이지 콘텐츠 변조, 사용자 정보 불법 입수 등을 하기 쉽습니다.
해결책
애플릿은 뷰 표시와 로직 처리를 두 개의 스레드로 분리하는 듀얼 스레드 모델을 채택합니다.
모델에서 HTML 태그는 개발자가 네이티브 태그를 직접 호출할 수 없도록 캡슐화됩니다. JS의 원래 위험한 논리 작업 API 기능도 차단되며, 관련된 통신 작업은 중간 계층에서 제공하는 API를 통해서만 가상 DOM 업데이트(데이터 기반 뷰)를 트리거할 수 있습니다. )
뷰 레이어와 로직 레이어의 기능은 WeChat 클라이언트에 내장된 미니 프로그램 기본 라이브러리 JS 파일을 통해 제공됩니다
WAWebview.js Virtual Dom의 전체 구성 요소 시스템 세트 및 관련 구현을 포함하여 뷰 레이어 기반의 API 기능을 제공합니다.
WAService.js 로직 레이어 기반의 API 기능을 제공하여 개발자에게 다양한 작업을 위한 API를 노출합니다
다른 운영 환경에서는 스크립트 실행 환경과 구성 요소 렌더링 환경이 다르며 성능 성능도 다릅니다.
iOS, iPadOS 및 Mac OS에서는 소규모 프로그램 로직 레이어의 JavaScript 코드는 JavaScriptCore에서 실행되고 뷰 레이어는 WKWebView에 의해 렌더링됩니다. 환경에는 iOS 14, iPad OS 14, Mac OS 11.4 등이 포함됩니다.
Android의 JavaScript 코드는 애플릿 로직 레이어 V8에서 실행되는 뷰 레이어는 모바일 Chromium 커널을 기반으로 WeChat이 자체 개발한 XWeb 엔진으로 렌더링됩니다(과거 X5부터 자체 개발한 XWeb 엔진까지, 뷰 레이어는 모바일 기반으로 렌더링됨). Chrome 커널, 그리고 공식 공개에 따르면 로직 레이어도 향후 V8에서 분리될 예정입니다. 즉, 맞춤형 XWeb Worker 스레드를 사용합니다. 즉, Web Worker 스레드를 미니 프로그램의 로직 레이어로 맞춤화하는 것입니다 참조 링크)
Windows에서 미니 프로그램은 로직 레이어 JavaScript와 뷰 레이어 모두 Chromium 커널을 사용합니다
개발 도구에서는 애플릿 로직 레이어의 JavaScript 코드가 NW.js에서 실행되며, 뷰는 레이어는 Chromium WebView
미니 프로그램과 관련된 구성 요소에는 내장 구성 요소, 사용자 정의 구성 요소, 기본 구성 요소의 세 가지 유형이 있습니다.
Web Component는 브라우저에서 캡슐화된 기능과 맞춤형 요소를 생성하는 기능으로, 세 가지 주요 기술로 구성됩니다
사용자 정의 요소(사용자 정의 요소) 사용자 정의 요소와 해당 동작을 정의한 다음 필요에 따라 사용자 인터페이스에서 사용할 수 있는 JavaScript API 세트
Shadow DOM(Shadow DOM) 캡슐화된 "그림자" DOM 트리를 요소(기본 문서 DOM과 별도로 렌더링됨)에 연결하고 관련 기능을 제어하기 위한 JavaScript API입니다. 이러한 방식으로 요소의 기능을 비공개로 유지하면 문서의 다른 부분과 충돌할 염려 없이 스크립트를 작성하고 스타일을 지정할 수 있습니다.
HTML 템플릿
템플릿 및 슬롯 요소는 렌더링된 페이지. 그런 다음 사용자 정의 요소 구조의 기초로 여러 번 재사용할 수 있습니다.
Exparser는 WeChat 미니 프로그램의 구성 요소 구성 프레임워크로, 미니 프로그램 기본 라이브러리에 내장되어 있으며 다양한 구성 요소의 기초를 제공합니다. 미니 프로그램을 지원합니다. 내장 컴포넌트와 사용자 정의 컴포넌트를 포함한 애플릿의 모든 컴포넌트는 Exparser에 의해 구성되고 관리됩니다. 애플릿에서는 WXML을 포함하여 페이지의 최종 노드 트리 구성까지 모든 노드 트리 관련 작업이 Exparser에 의존합니다. createSelectorQuery 호출 및 사용자 정의 구성 요소 기능 등
Exparser는 노드 속성, 이벤트 바인딩 등을 포함하여 전체 페이지의 노드 트리와 관련된 정보를 유지 관리하며 이는 Shadow DOM 구현의 단순화된 버전에 해당합니다
3. Exparser 기능
구성 요소의 몇 가지 기본 동작을 구성 요소에 등록합니다. to 상속
registerElement컴포넌트 등록 및 상호 작용 주로 속성과 이벤트
컴포넌트 생성미니 프로그램의 기본 라이브러리는 미니 프로그램이 시작되면 페이지와 컴포넌트라는 두 가지 생성자를 제공합니다. 속성, 데이터, 메서드 등과 같은 필드는 Exparser의 구성 요소 레지스트리에 기록됩니다. 페이지를 초기화할 때 Exparser는 페이지 루트 구성 요소의 인스턴스를 생성하고 사용된 다른 구성 요소도 이에 따라 구성 요소 인스턴스를 생성합니다. 재귀 프로세스)
5. Page와 Component
생성 과정 위의 그림을 보면 페이지 렌더링과 컴포넌트 렌더링 시 미니 프로그램의 통신 방식에 차이가 있음을 확실히 알 수 있습니다. 그중 페이지 렌더링에서 VDOM의 생성 및 비교는 뷰 계층에서 완료되며 논리 계층은 렌더링 계층의 업데이트 논리를 트리거하기 위해 데이터 데이터를 전송하는 역할만 담당합니다. 컴포넌트 렌더링에서 로직 레이어와 뷰 레이어는 VDOM 집합을 공동으로 유지해야 합니다. 이 방법은 컴포넌트가 초기화될 때 로직 레이어에 컴포넌트의 VDOM을 구축한 다음 이를 뷰 레이어와 동기화하는 것입니다. 후속 업데이트 작업은 먼저 논리 계층에서 이전 VDOM과 새 VDOM의 차이점을 수행한 다음 차이점 이후의 결과만 전달하고 직접 VDOM 업데이트 및 렌더링을 위해 뷰 계층에 전달합니다. 이 작업의 가장 큰 장점은 DOM 수준에 대한 뷰 업데이트 통신의 세분성을 제어하는 것입니다. 최종적으로 변경되는 DOM만 업데이트됩니다(때로는 이전과 비교하여 데이터 변경이 반드시 뷰 업데이트를 가져오지 않기 때문입니다). 데이터 레벨 업데이트가 더욱 정확해져 불필요한 통신 비용을 방지하고 더 나은 성능을 제공합니다.
3), 미니 프로그램 네이티브 컴포넌트. 예를 들어 입력 상자 구성 요소(입력, 텍스트 영역)에는 키보드를 더 잘 제어할 수 있는 기능이 있습니다.
과 동시에 WebView의 렌더링 작업도 줄여줍니다. 예를 들어 지도 구성 요소와 같은 보다 복잡한 구성 요소의 렌더링 작업은 WebView 스레드를 차지하지 않고 기본 처리를 위해 보다 효율적인 클라이언트로 전달됩니다.
, setData, 데이터 통신 및 다시 렌더링 프로세스를 우회하여 풍부한 그리기 인터페이스 세트를 사용하여 캔버스 구성 요소(캔버스)를 직접 그릴 수 있습니다.
컴포넌트가 클라이언트에게 이를 알리고, 클라이언트는 너비와 높이를 기준으로 동일한 위치에 네이티브 영역을 삽입하고, 클라이언트는 이 영역에 인터페이스를 렌더링합니다.
위치나 너비와 높이가 변경되면, 구성 요소는 클라이언트가 해당 조정을 수행함을 알립니다
일부 CSS 스타일은 기본 구성 요소에 적용할 수 없습니다.
수준 문제(기본 구성 요소는 가장 높은 수준이며 WebView 레이어)
솔루션
커버 뷰 및 커버 이미지 구성 요소를 사용하여 기본 구성 요소를 덮음(제한된 기능, 유연성 없음)
동일 레이어 렌더링(기본 구성 요소를 동일한 레이어에 직접 렌더링) 특정 기술적 수단을 통한 WebView 수준(위)
WKWebView는 WebKit 커널에서 생성된 합성 레이어를 렌더링합니다. iOS의 WKCompositingView 구성 요소에 포함되지만 구성 레이어와 DOM 노드 사이에는 일대일 매핑이 없습니다(커널은 일반적으로 여러 DOM 노드를 하나의 구성 레이어로 병합합니다).
WKChildScrollView: DOM 노드의 CSS 속성이 Overflow: Scroll로 설정된 경우(낮은 버전에서는 -webkit-overflow-scrolling: touch를 동시에 설정해야 함) WKWebView는 이에 대한 WKChildScrollView를 생성합니다(순서대로). iOS WebView 스크롤을 허용하면 WebView의 스크롤이 실제로 실제 기본 스크롤 구성 요소에 의해 수행됩니다. WebKit 커널은 이미 WebView와 다른 DOM 노드 간의 계층적 관계를 처리했으며 WKChildScrollView 쌍이 있습니다. 및 DOM 노드.
Creation process
WebPlugin은 브라우저 커널의 플러그인 메커니즘으로, 미니 프로그램의 Android 측에서
embedembed 태그를 기반으로 구현됩니다. 삽입을 정의하는 데 사용되는 HTML5의 새로운 태그 콘텐츠(예: 플러그인, 미디어 등)는 PDF, Midi, Wav, MP3 등의 형식일 수 있습니다. 예를 들어, Chrome 브라우저는 embed 태그를 기반으로 합니다.
Chromium 커널 확장과 결합된 embed 태그를 기반으로 달성되었습니다. Chromium은 WebPlugin 메커니즘을 지원합니다. WebPlugin은 주로 embed 태그를 구문 분석하고 설명하는 데 사용됩니다. 커널에서 제공하는 텍스처 텍스처
생성 프로세스WebView 측에 포함 DOM 노드를 생성하고 구성 요소 유형을 지정합니다.
Chromium 커널은 WebPlugin 인스턴스를 생성하고 RenderLayer를 생성합니다.
5), 레이어 코드 편집 보기
JS 파일에는 다음이 포함됩니다. 장치 화면 너비에 따라 px 단위로 적응적으로 계산할 수 있는 크기 단위 rpx를 추가하는 변환 방법
WCC 명령 도구 실행 프로세스
wcc는 WXML을 컴파일하여 JS 파일 제품을 생성합니다.
JS 파일에는 WXML을 수신하는 $gwx 메서드가 포함되어 있습니다. 실행 후 generateFunc 메서드를 생성하고 generateFuncReady 이벤트를 트리거합니다.
generateFunc 메서드는 가상 DOM
1. JSVirtualMachine
VM 환경을 인스턴스화하여 JS 코드를 실행합니다. 실행해야 할 JS가 여러 개인 경우 여러 VM을 인스턴스화해야 합니다. 그리고 GC 문제가 발생하기 쉽기 때문에 이러한 VM은 서로 상호 작용할 수 없다는 점에 유의해야 합니다.2. JSContext
JSContext는 JS 코드 실행을 위한 컨텍스트 개체이며 Webview의 창 개체와 동일합니다. . 동일한 VM에서 다른 Context3, JSValue
WASM과 유사하게 JsValue는 주로 JS 데이터 유형과 Swift 또는 Java 데이터 유형 간의 상호 매핑을 해결하는 데 사용됩니다. 즉, JSContext에 마운트된 모든 콘텐츠는 JSValue 유형입니다. Swift와 Java는 JS와 JS 간의 유형 변환을 자동으로 구현합니다. 4. JSExport는 JSCore 프로토콜에서 기본 인터페이스를 노출하는 데 사용됩니다. 간단히 말하면 Native 관련 속성과 메소드를 프로토타입 객체의 메소드와 속성으로 직접 변환합니다3. 모듈 사양 구현define을 통해 모듈을 정의합니다. 이는 모듈에서 사용할 수 있는 다른 항목을 제한합니다. 윈도우, 문서 등의 모듈에서 정의 메소드는 모든 JS 코드 로직을 "경로-모듈" 키-값 쌍의 형태로 전역 변수에 저장하여 구현됩니다.
모듈을 사용할 때 require를 사용하세요. 모듈, 요구 사항, 모듈 및 내보내기만 전달됩니다. 코드에서 읽은 다른 변수는 정의되지 않습니다. 이는 미니 프로그램에서 일부 브라우저 환경 개체를 얻을 수 없는 이유이기도 합니다. 이는 실제로 Webpack이 모듈을 패키징하는 방식과 매우 유사한 일반적인 모듈 로딩 아이디어입니다.
애플릿 논리 계층과 렌더링 계층 간의 통신은 Native(WeChat 클라이언트)에 의해 중계되며 논리 계층에서 보낸 네트워크 요청도 기본 구현
여러 끝의 다양한 구현은 결국 개발자가 호출할 수 있도록 WeiXinJSBridge와 같은 호환성 레이어로 캡슐화됩니다
1. iOS 측
뷰 레이어와 로직 레이어의 구현 원리는 동일합니다. 그들은 네이티브 메소드 WeixinJSCore를 창에 주입하여 구현됩니다. WebView의 객체입니다. 이 WeixinJSCore는 JS 호출
3을 위해 제공되는 WeChat 인터페이스(네이티브 구현)입니다. WeChat 개발자 도구
통신을 위해 websocket을 사용하세요2), WeixinJSBridge 모듈 객체WeixinJSBridge는 뷰 레이어 JS와 Native를 제공합니다. 뷰 레이어와 로직 레이어 사이의 메시지 통신 메커니즘은 다음과 같은 방법을 제공합니다:invoke: JS가 네이티브 API를 호출
on: JS는 기본 메시지를 수신합니다.
publish: 보기 레이어는 메시지를 게시합니다.
subscribe: 논리 레이어 메시지를 구독합니다.
DOM을 유연하게 운영할 수 없으며 더 복잡한 효과를 얻을 수 없습니다.
네이티브 구성 요소와 관련된 일부 보기에는 사용 제한이 있습니다. 예를 들어 WeChat의 scrollView는 텍스트 영역을 가질 수 없습니다
페이지 크기와 열린 페이지 수가 제한되어 있습니다
별도의 개발 및 조정이 필요하며 기존 코드 리소스를 재사용할 수 없습니다.
JSCore의 JS 볼륨이 상대적으로 크면 초기화 시간에 영향을 미칩니다
데이터를 전송할 때 직렬화 및 역직렬화에 소요되는 시간을 고려해야 합니다
듀얼 스레드로 인한 성능 병목 현상도 WeChat의 주요 문제입니다. 자체적으로 해결에 전념해 왔습니다. 앞서 언급했듯이 애플릿은 Chromium 커널을 수정하여 새로운 XWeb 커널의 논리 계층 구현을 사용자 정의된 XWeb Worker 스레드로 대체합니다. 이렇게 하면 추가 V8이 필요하지 않으며 메모리 사용량이 크게 늘어납니다. 또한 Chromium 커널의 Worker 스레드를 기반으로 하기 때문에 데이터 통신에 있어서 통신 방식의 기본 setData를 PostMessage로 대체하여 더 높은 성능의 통신 능력을 얻는 것은 당연합니다
또한 Alipay 애플릿의 기본 구현에 대해 배우고 연구했습니다. Alipay 애플릿도 유사한 듀얼 스레드 아키텍처 모델을 사용합니다. UC에서 제공하는 브라우저 커널을 사용하여 렌더링 계층은 Webview 스레드에서 실행되고 논리 계층은 서비스 워커를 실행하기 위해 별도의 스레드를 시작합니다. 그러나 서비스 워커는 MessageChannel API를 통해 렌더링 스레드와 통신해야 하며, 데이터 양이 많고 객체가 복잡할 경우 성능 병목 현상도 발생합니다.
이에 알리페이 애플릿은 기존 JS 가상 머신 V8을 재설계하고 최적화된 격리 모델(Optimized Isolation Model, OIM)을 제안했습니다. OIM의 주요 아이디어는 스레드 실행 환경과 관련이 없는 JS 가상 머신 인스턴스뿐만 아니라 불변 또는 불변 JS 객체에서 데이터와 인프라를 공유하여 JS 계층의 논리적 격리를 유지하면서, 다중 인스턴스 시나리오 및 전력 소비 오버헤드에서 메모리를 절약할 수 있습니다. 인스턴스 간에 공유되는 일부 데이터는 동기화 오버헤드를 가져오지만 격리 모델에서는 이 솔루션에서 공유하는 데이터, 개체, 코드 및 가상 머신 인프라가 변경 불가능하거나 비휘발성이므로 경쟁이 거의 발생하지 않습니다.
새로운 격리 모델에서는 Webview의 V8 인스턴스가 로컬 런타임이고, Worker 스레드의 V8 인스턴스도 로컬 런타임입니다. 논리 계층과 렌더링 계층이 상호 작용하면 setData 개체가 공유 힙 따라서 렌더링 계층의 로컬 런타임은 개체를 직접 읽고 렌더링 계층의 렌더링에 사용할 수 있으므로 개체의 직렬화 및 네트워크 전송이 줄어들고 시작 성능과 렌더링 성능이 크게 향상됩니다.
또한 Alipay 애플릿은 홈페이지 오프라인 캐싱 최적화를 구현합니다. 먼저 지난번에 저장한 홈페이지 UI 페이지를 렌더링하고 홈페이지를 사용자에게 표시한 다음 백그라운드에서 프런트엔드 프레임워크와 비즈니스 코드를 계속 로드합니다. 로딩이 완료되면 오프라인 캐시 홈페이지 UI와 병합되어 사용자에게 동적 홈페이지를 보여줍니다. 이는 WeChat 애플릿의 초기 렌더링 캐싱 솔루션과 매우 유사하며 더욱 급진적입니다. WebAssembly 기술은 가상 DOM의 핵심 코드를 다시 구현하고 미니 프로그램의 페이지 렌더링을 개선하는 데에도 사용되었습니다. [추천 관련 동영상 튜토리얼: 웹 프론트엔드]
기술적 아키텍처는 문제를 해결하기 위해 탄생합니다. 좋은 기술 솔루션은 디자이너가 개발 효율성을 높이고 기술 비용, 성능 경험 및 시스템 보안도 비즈니스 동향, 제품 형태 및 사용자 요구와 긴밀하게 통합되어야 합니다.
미니 프로그램이 시작되면(콜드 스타트) WeChat은 미니 프로그램의 아이콘, 이름 및 로딩 프롬프트 아이콘이 포함된 미니 프로그램의 고정된 시작 인터페이스를 표시합니다.
이때 WeChat은 여러 가지를 완료합니다. 작업: 미니 프로그램 코드 패키지 다운로드, 미니 프로그램 코드 패키지 로드, 미니 프로그램 홈페이지 초기화
개발자 입장에서는 코드 패키지 크기를 조절하면 미니 프로그램의 시작 시간을 줄이는 데 도움이 됩니다. 1MB 미만의 코드 패키지의 경우 다운로드 시간은 최적화 계획
내에서
929ms(iOS)내에서 제어할 수 있습니다. package
합리적 할당, 하도급 및 사전 로딩 규칙
미세 분할, 비동기 하도급
위챗에서는 페이지 수준을 미리 준비합니다. 미니프로그램 홈페이지입니다. 페이지 렌더링에 페이지 수준이 사용될 때마다 WeChat은 미리 새 페이지 수준을 준비하기 시작하므로 wx.navigateTo가 호출될 때마다 가능한 한 빨리 새 페이지가 표시될 수 있습니다. 뷰 레이어 페이지의 콘텐츠는 pageframe.html 템플릿을 통해 생성됩니다.
페이지 레벨 준비 단계
첫 번째 단계는 iOS 및 Android 시스템에서 WebView를 시작하는 것입니다. 운영 체제가 시작되면 WebView는 짧은 시간이 걸립니다
두 번째 단계는 WebView에서 기본 라이브러리를 초기화하는 것입니다. 이 때 페이지 렌더링 성능을 향상하기 위해 기본 라이브러리의 일부 내부 최적화도 수행됩니다
세 번째 단계는 미니 프로그램이 페이지의 초기 데이터를 받은 후 즉시 페이지 렌더링을 시작할 수 있도록 애플릿의 WXML 구조와 WXSS 스타일을 주입하는 것입니다. (이 단계는 미니 프로그램이 시작되기 전에는 실행할 수 없습니다.)
View 레이어 전역 변수
논리 레이어 전역 변수
View 레이어 코드 주입
Logic 레이어 코드 주입
Inject on Demand 및 Inject When Demand
일반적으로 미니 프로그램이 시작되면 하위 패키지와 메인 패키지의 모든 JS 코드(독립 패키지 제외) 시작 페이지가 있는 하위 패키지)가 병합되어 주입됩니다. 기본 라이브러리 버전 2.11.1부터 주문형 주입 및 시간이 많이 걸리는 주입이 구성됩니다. 애플릿은 페이지에서 사용되지 않는 사용자 정의 구성 요소와 현재 페이지에 필요한 페이지 코드만 주입합니다. 로딩 및 초기화
데이터 통신은 사용되지 않습니다.
미니 프로그램에서 시작하거나 새 페이지가 열리면 페이지의 초기 데이터(데이터)와 경로 및 기타 관련 정보가 뷰 레이어의 초기 렌더링을 위해 로직 레이어에서 뷰 레이어로 전송됩니다.
네이티브 레이어는 이러한 데이터를 뷰 레이어에 직접 전달하는 동시에 사용자에게 새로운 페이지 수준을 제공하고, 뷰 레이어는 이 페이지 수준에 인터페이스를 그립니다.
뷰 레이어는 관련 데이터를 받은 후 페이지 경로에 따라 적절한 WXML 구조를 선택합니다. WXML 구조는 페이지의 첫 번째 렌더링 결과를 얻기 위해 결합됩니다. 뷰 레이어 코드 삽입 및 수집 로직 레이어에서 보낸 초기 데이터를 수신하고 초기 데이터와 뷰 레이어에서 얻은 페이지 구조 및 스타일 정보를 결합한 후 미니 프로그램 프레임워크는 미니 프로그램 홈 페이지를 렌더링하고 미니 프로그램 첫 화면, 홈 페이지에서 onReady 이벤트를 트리거합니다.
초기 렌더링 캐시
가 켜져 있으면 로직 레이어의 초기 데이터에 의존하지 않고 렌더링 레이어의 캐시된 데이터를 사용하여 첫 번째 렌더링을 직접 완료할 수 있어 시작 시간이 단축됩니다(onReady 이벤트는 다음에서 실행됨). 전진).페이지 초기화 시간은 크게 페이지의 초기 데이터 통신 시간과 초기 렌더링 시간의 두 부분으로 구성됩니다. 그 중 데이터 통신 시간은 로직 계층에서 데이터 구성이 시작되어 뷰 계층에서 완전한 수신이 완료될 때까지의 시간을 의미하며, 데이터 용량이 64KB 미만일 경우 총 시간은 30ms 이내로 제어할 수 있다.
전송 시간은 일반적으로 데이터 양과 양의 상관관계가 있습니다. 지나치게 큰 데이터를 전송하면 이 시간이 크게 늘어납니다. 따라서 전송되는 데이터의 양을 줄이는 것
은 데이터 전송 시간을 줄이는 효과적인 방법입니다.초기 렌더링
초기 렌더링은 페이지가 생성될 때 발생합니다. 초기 렌더링 중에 초기 데이터는 해당 WXML 조각에 적용되어 노드 트리를 생성합니다. 노드 트리는 개발자 도구의 WXML 패널에 표시되는 페이지 트리 구조로, 페이지에 있는 모든 구성 요소 노드의 이름, 속성 값, 이벤트 콜백 함수 및 기타 정보를 포함합니다. 마지막으로 노드 트리에 포함된 각 노드를 기반으로 각 구성 요소가 인터페이스에 순차적으로 생성됩니다. 초기 렌더링에서 얻은 데이터와 현재 노드 트리는 다시 렌더링을 위해 유지됩니다.
이 전체 과정에서 시간 오버헤드는 일반적으로 노드 트리의 총 노드 수에 비례합니다. 따라서
WXML에서 노드 수를 줄이면초기 렌더링 및 다시 렌더링에 소요되는 시간 오버헤드를 효과적으로 줄이고 렌더링 성능을 향상시킬 수 있습니다.
2) 데이터 렌더링 업데이트
초기 렌더링이 완료된 후 뷰 레이어는 개발자가 setData를 호출한 후 인터페이스 업데이트를 수행할 수 있습니다.속성 이름(. 및 [] 등의 데이터 경로 기호 포함)을 구문 분석하고 해당 계층 구조를 반환합니다. 해당 로컬 데이터를 수정합니다.
{abc: 1} 中 abc 属性名 => [abc] {a.b.c: 1} 中 'a.b.c' 属性 => [a,b,c] {"array[0].text": 1} => [array, 0, text]
evaluateJavascript
: 사용자가 전송한 데이터를 문자열 형식으로 변환하여 전달해야 합니다. 동시에 변환된 데이터 내용이 하나로 합쳐진 후 JS 스크립트를 실행하여 양쪽의 독립된 환경에 전달됩니다. 다시 렌더링할 때 로직 레이어는 setData 데이터를 데이터로 병합하고, 렌더링 레이어는 데이터와 setData 데이터를 WXML 조각에 적용하여 새 노드 트리를 얻습니다. 그런 다음 새 노드 트리를 현재 노드 트리와 비교하여 어떤 노드를 업데이트해야 하는지, 어떤 노드를 추가하거나 제거해야 하는지 알 수 있습니다. 마지막으로 다음 재렌더링을 위해 이전 노드 트리가 새 노드 트리로 대체됩니다. 현재 노드 트리와 새 노드 트리를 비교할 때 setData 데이터의 영향을 받는 노드 속성이 비교됩니다. 따라서 불필요한 세트 데이터를 제거하고 setData의 데이터 양을 줄이는 것도 이 단계의 성능 향상에 도움이 됩니다.3), 사용자 이벤트 통신
뷰 레이어는
클릭 이벤트, 터치 이벤트등과 같은 사용자 이벤트를 허용합니다.
사용자 이벤트의 통신은 비교적 간단합니다. 사용자 이벤트가 트리거되고 관련 이벤트 리스너가 트리거되어야 할 때 뷰 레이어는 정보를 로직 레이어에 다시 제공합니다.
레이턴시를 줄이는 방법은 크게 두 가지가 있습니다.
불필요한 이벤트 바인딩을 제거(WXML에서 바인딩 및 캐치)하여 통신 데이터의 양과 수를 줄입니다.이벤트를 바인딩할 때 대상 및 currentTarget을 전송해야 하므로 노드의 데이터 접두사 속성에 너무 큰 데이터를 배치하지 마세요
主包内容
Tab页(系统要求)、业务必要页面(错误兜底页、登陆授权页等),其余文件都以业务模块或者页面的维度,拆分成各自的分包
分包预加载
据用户的实际使用场景,预测下一跳的页面,将可能性最高的场景设置为预加载分包(可以参照业务埋点数据),例如:进入电商首页后,需要对会场和商详页的分包进行预加载
实现思路
小程序不支持主包引用分包代码,只能在分包中引用主包代码,所以把公共使用的组件代码放在主包目录中,但这些公共组件未必在主包所属的页面中会被引用,可能只是在分包页面中被多次引用,这样使得主包中代码体积越来越大,用户首次加载速度变慢。
将主包页面不依赖的公共组件分别分发到依赖它们的分包目录中,虽然分包各自的体积会有所增大,但主包体积会有显著下降
实现原理
将所有需要分发的组件放置主包指定目录中,并添加配置文件,说明组建文件分发信息。在开发时用 gulp 任务监听单个文件变化、在构建时递归遍历所有组件,将其复制到配置文件中指定的子包路径目录中。
目标文件在复制之前,都先要将文件内的依赖路径进行更新,使其在子包中运行时也能引用成功。针对不同类型的文件,采取不同的依赖分析手段。
JS 文件:使用 babel.transformFile 修改依赖引用地址
WXSS 文件:使用 postcss.plugin('transform-wxss') 处理依赖的 @import 导入样式文件地址
WXML 文件:使用 require('htmlparser2').Parser 来转换内部 wxs、template(import 和 include 导入)依赖的引用地址
异步分包
小程序基础库版本 2.17.3 及以上开始支持分包异步化,即可以在分包之间互相引用,这个能力可以快速取代我们自己的组件分发方案,而且优化效果更佳,可以将分包中公共依赖的代码部分打成新的分包,在使用时异步按需引入,能力与 Web 端的异步组件类似,但这个方案在生产环境的稳定性有待验证。
实现思路
合并 setData 调用,将其放在下个时间片(事件循环)统一传输,降低通信频率
实现原理
需要先将逻辑层 this.data 进行更新,避免前后数据不一致造成逻辑出错。将需要传送至视图层的 data 进行整合,在 nextTick 中调用原生的 setData 统一进行传送,可以有效降低通信频率,并且在传送前手动做一次与 this.data 的 diff 操作,降低通信体积
1. 降低频率
const nextTick = wx.nextTick ? wx.nextTick : setTimeout; // 小程序里的时间片 API
2. 减少体积
参考京东 Taro 中 diff 的实现,对基本、数组、对象等不同类型进行处理,最终转换为 arr[1]、x.y 这样的属性路径语法,减少传输信息量
实现思路
onLaunch、onLoad 等生命周期函数中存在大量对微信 Storage 的同步调用(使用 Sync 结尾的API),这些操作涉及JS与原生通信,同步等待耗时过久,推迟页面 onReady 触发即用户可交互时间,影响用户体验。直接改为异步操作又存在业务代码改动量较大的问题,存在一定风险,大量的异步回调代码语义不优雅、可读性较差。因此需要对原生 Storage 操作进行重封装,改为对内存中对象的实时存取,提高响应速度,并定期调用原生 API 向真实 Storage 中同步。
实现原理
기본 API로 getStorage 및 getStorageSync를 사용하여 API를 캡슐화합니다. 처음 호출되면 원본 데이터를 얻기 위해 네이티브 API가 트리거되고 모든 후속 작업이 저장됩니다. (삭제, 수정, 검색)은 이 개체를 기반으로 합니다. 설정 및 제거 작업은 해당 데이터를 더티로 표시하고 더티 테이블에 저장하여 나중에 변경 사항이 기본 엔드에 동기화될 수 있도록 해야 합니다. 호출자는 메모리가 실행 중일 때 우발적인 데이터 손실을 방지하기 위해 정기적으로 변경 동기화 메서드를 호출하여 데이터를 유지해야 합니다(동기화된 더티 테이블의 데이터 탐색). 일반적으로 이 메서드는 정기적으로 실행되어야 합니다(앱의 onShow가 setInterval을 실행함). 앱의 onHide 수명 주기에서 실행됩니다.
스토리지 API를 다시 캡슐화했을 뿐만 아니라 시간이 오래 걸리는 다른 동기화 API(예: 장치 및 시스템 정보를 얻는 데 사용되는 getSystemInfo/getSystemInfoSync API, 기본 구현은 동기식)에 대해서도 유사한 접근 방식을 채택했습니다. ) 시스템 API는 첫 번째 획득 중에만 호출되고 결과는 메모리에 캐시되며 후속 호출은 캐시된 정보를 직접 반환합니다.
구현 아이디어
페이지 A에서 B로 이동하기 전에 페이지 A에서 메시지를 내보내면 페이지 B 데이터 인터페이스 요청이 발생하고 결과가 캐시됩니다. , B 페이지가 열리면 먼저 캐시를 가져옵니다. 인터페이스를 가져올 수 없으면 인터페이스를 다시 호출하세요
구현 원칙
B 페이지가 인스턴스화되지 않았지만 페이지가 등록되었습니다. 페이지 외부 코드가 실행되었으므로 미리 페이지 A로 메시지 게시 및 구독을 완료할 수 있습니다
구현 아이디어
메인 패키지에 등록되지 않거나 비동기적으로는 게시 및 구독 모드를 통해 수행할 수 없으며 사전 로드 방법을 전역적으로 등록하여 달성할 수 있습니다
구현 원칙
사전 요청을 시작합니다. 이전 페이지 경로 이동, 이 요청을 전역 Promise 변수에 저장하고 사전 요청이 필요한 경우 로드된 페이지가 처음 렌더링될 때 전역 Promise 변수에서 데이터 결과를 가져온 후 콜백하는 것이 우선순위입니다
전체 이미지 리소스 최적화(알리바바 클라우드 기능)
구현 아이디어
사용자 모델 하드웨어 성능 수준에 따라 프런트 엔드 디스플레이는 다양한 렌더링 전략을 설정합니다.
구현 원리
저사양에서 다음 기능을 다운그레이드합니다. 엔드 머신 시나리오
프레임워크 도구
BeautyWe는 쓰리 스퀘어 미니 프로그램 사업 개발 프레임워크가 기반이 되는 공공 사업을 담고 있습니다. logic of life
응용 시나리오
각 페이지의 사용자 로그인 상태 확인, URL 매개변수 획득 및 처리, 자동 PV 매장, 성능 모니터링 등 공공 비즈니스 로직
구현 원칙
라이프사이클 기능은 플러그인으로, 기본 onLoad, onShow, onReady 및 기타 기능을 Object.defineProperty를 사용하여 다시 작성하여 내부적으로 Promise 작업 체인을 구성합니다. 플러그인을 도입하면 작업 체인에 메소드를 자유롭게 삽입할 수 있습니다. 시스템 수명주기 기능이 실행될 때 순차적으로 트리거되고 호출되는 중간 및 전면 위치입니다.
라이프 사이클 후크 플러그인을 구현한 후 처리해야 하는 모든 종류의 기본 공용 로직을 캡슐화하고 이를 호스트의 Promise 작업 체인(네이티브 라이프 사이클)에 삽입할 수 있습니다
미니 프로그램 CI + Gitlab CI + Puppeteer를 기반으로 반자동 미니 프로그램 구성 및 배포 도구 세트가 구현됩니다. 자세한 내용은 내 다른 기사"WeChat Mini 프로그램 자동 배포를 참조하세요. 솔루션", WeChat 미니 프로그램은 나중에 Linux 환경에서 독립적으로 실행할 수 있는 miniprogram-ci를 제공하므로 더 간단하고 사용하기 쉽습니다.
모니터링 기능
비즈니스 숨은 포인트 (페이지 PV, 모듈 노출 등 비즈니스 숨은 포인트)
성과 리포팅(미니 프로그램 시작, 페이지 렌더링, FMP, 메모리 알람)
예외 모니터링(JS 오류, 인터페이스 오류, 비즈니스 오류)
성능 모니터링 보고 유형
memory_warning: 메모리 알람 데이터 보고. 수집 방법: wx.onMemoryWarning 콜백
app_launch에서 알람 수준을 수집합니다. 앱 런타임 데이터 보고. 수집방법: 앱 라이프사이클 실행 시간(onLaunch, onShow)을 기록하고, 페이지가 onLoad
page_render될 때 보고합니다.: 페이지 런타임 데이터 보고. 수집방법: 페이지 라이프사이클 실행 시간(onLoad, onShow, onReady), FMP 등을 기록하고 페이지가 onHide 또는 onUnload
구현 원칙
플러그인 프레임워크 기반 솔루션, Life Cycle Hook 기능 재작성 후 페이지 프로그램 실행 중 자동으로 성능 데이터를 기록 및 보고할 수 있습니다
FMP를 주요 지표로 사용하여 자세한 내용은 사용자 경험 중심 프런트엔드 성능 최적화의 또 다른 기사를 참조하세요. 또한 일상적인 개발에서는 일상적인 비즈니스 반복에서 성능과 안정성의 기본 보장을 향상할 수 있는 몇 가지 사양도 개발했습니다. 자세한 내용은 WeChat Mini 프로그램 개발 군사 규칙을 참조하세요.
공식 문서에서 프레임워크의 기반 기술이 지속적으로 공개되는 것은 소규모 프로그램의 기술 구축이 점점 더 성숙해지고 완벽해지고 있음을 보여줍니다. 인프라 생태계가 지속적으로 강화됨에 따라 관계자들은 동일 레이어 렌더링, 네트워크 환경 모니터링, 초기 렌더링 캐싱, 시작 성능 최적화 등 이러한 기능에 대한 지원을 연속적으로 제공하여 점차적으로 미니 프로그램을 웹 생태계에 더 가깝게 만들었습니다.
우리는 다양한 문제를 해결하기 위해 하도급 및 비동기화, CI 패키징, 성능 API 등을 자체적으로 개발했으며 나중에 이러한 기능을 기본적으로 구현할 예정입니다. 쓸데없는 노력처럼 보일 수도 있지만, 사실 이는 우리가 과거에 해왔던 일이 옳았으며, 그 방향이 전체 생태계의 발전과 일치한다는 것을 보여줄 뿐입니다.
기술 역량의 향상 외에도 WeChat 미니 프로그램 생태계는 순간을 공유하는 미니 프로그램 지원, 단편 생성 지원 등 더 많은 비즈니스 시나리오에서 지속적으로 역량 지원을 강화하고 있습니다. 링크, WeChat 채팅 자료는 비즈니스에 더 많은 가능성과 상상력을 제공하기 위한 미니 프로그램을 엽니다.
WeChat은 또한 하드웨어 장치(비일반 컴퓨팅 장치)에서 WeChat 클라이언트 실행 조건 없이 WeChat 미니 프로그램을 실행할 수 있는 미니 프로그램 하드웨어 프레임워크를 출시했습니다. Android 태블릿, 대형 화면 장치, 하드웨어는 IoT 장치 사용자에게 보다 표준화되고 기능이 풍부한 경험을 제공하기 위해 저렴한 화면 상호 작용 솔루션을 제공합니다.
이 말은 수십 년 동안 컴퓨터 기술 분야에 퍼져 있던 Atwood의 법칙이라는 말이 생각납니다. JavaScript로 작성할 수 있는 모든 응용 프로그램은 결국 JavaScript로 작성됩니다. 마찬가지로, 미니 프로그램을 사용하여 구현할 수 있는 모든 제품은 결국 미니 프로그램을 사용하여 구현될 것입니다.
2017년 위챗 미니 프로그램 탄생 이후 슈퍼앱 + 미니 프로그램/라이트 애플리케이션 모델이 위챗, 위챗 미니 프로그램 등 다양한 사업에서 시도되고 테스트되었으며, Alipay 및 Alipay 미니 프로그램, Douyin 및 Douyin 미니 프로그램 등 저비용, 빠른 반복 및 쉬운 홍보를 갖춘 제품 모델인 미니 프로그램은 슈퍼앱이 가져온 엄청난 트래픽의 지원을 받아 다양한 분야에서 큰 성공을 거두었으며, 이미 점차 추세가 되어가고 있으며, 점점 더 많은 회사들이 이 모델을 자사 제품에 추가하고 있습니다. 미니 프로그램 자체는 전염병 기간 동안 다양한 지역의 건강 코드 애플리케이션, 커뮤니티의 전자 상거래 단체 구매를 위한 미니 프로그램 코드, 밀크티를 마시고 싶은 경우 레스토랑 주문 등 삶의 모든 측면에 자신도 모르게 통합되었습니다. 커피, 미니 프로그램을 통해 미리 다운로드 받을 수 있습니다. 사실, 작은 프로그램의 제품 기술 솔루션은 사람들의 삶과 떼려야 뗄 수 없는 관계입니다.
친구와 얘기하면서 미니 프로그램이 중국 특성을 지닌 PWA 애플리케이션이라고 농담으로 말했습니다. 미래에도 미니 프로그램은 기존 온라인 쇼핑, 생활 서비스 애플리케이션 외에 여전히 큰 잠재력을 갖고 있습니다. 따라서 의료, 오프라인 소매, 엔터테인먼트 게임, AI 인텔리전스 및 기타 산업과 같은 시장 격차로 인해 미니 프로그램 기술의 유용성을 볼 수 있습니다. 미니 프로그램의 개발 잠재력은 더욱 커집니다. 미니 프로그램은 미니 프로그램을 접근 가능하고 유비쿼터스하게 만드는 원래 목표를 향해 나아가고 있습니다.
원본 주소 : https://juejin.cn/post/7100752247381819399(학습 영상 공유 :
웹 프론트엔드 시작하기)