小程序實現原理解析

概述

做爲一名前端開發,假設你還停留在應用開發層面,那你就OUT了,快來跟我一塊兒探討下小程序框架自己底層實現的一些技術細節吧,讓咱們從小程序的執行機制來深度瞭解小程序。css


小程序是基於WEB規範,採用HTML,CSS和JS等搭建的一套框架,微信官方給它們取了一個很是牛逼的名字:WXML,WXSS,但本質上仍是在整個WEB體系之下構建的。
WXML,我的推測在取這個名字的是微信的Xml,說究竟就是xml的一個子集。html

WXML採用微信本身定義的少許標籤WXSS,你們可以理解爲就是本身定義的CSS。實現邏輯部分的JS仍是通用的ES規範。並且runtime仍是Webview(IOS WKWEBVIEW, ANDROID X5)。前端

小程序

小程序文件夾結構

這裏寫圖片描寫敘述

一個完整的小程序主要由下面幾部分組成:
一個入口文件:app.js
一個全局樣式:app.wxss
一個全局配置:app.json
頁面:pages下。每個頁面再按文件夾劃分。每個頁面4個文件
視圖:wxml,wxss
邏輯:js。json(頁面配置,不是必須)vue

注:pages裏面還可以再依據模塊劃分子文件夾,孫子文件夾。僅僅需要在app.json裏註冊時填寫路徑便可。node

小程序打包

開發完畢後。咱們就可以經過這裏可視化的button。點擊直接打包上傳公佈,審覈經過後用戶就可以搜索到了。
這裏寫圖片描寫敘述react

那麼打包怎麼實現的呢?
這就涉及到這個編輯器的實現原理和方式了。它自己也是基於WEB技術體系實現的,nwjs+react,nwjs是什麼:簡單是說就是node+webkit,node提供給咱們本地api能力,而webkit提供給咱們web能力,二者結合就能讓咱們使用JS+HTML實現本地應用程序。
既然有nodejs,那上面的打包選項裏的功能就好實現了。
ES6轉ES5:引入babel-core的node包
CSS補全:引入postcss和autoprefixer的node包(postcss和autoprefixer的原理看這裏)
代碼壓縮:引入uglifyjs的node包android

注:在android上使用的x5內核。對ES6的支持很差。要兼容的話,要麼使用ES5的語法或者引入babel-polyfill兼容庫。ios

打包後的文件夾結構

小程序打包後的結構例如如下:
這裏寫圖片描寫敘述web

所有的小程序基本都最後都被打成上面的結構
一、WAService.js 框架JS庫。提供邏輯層基礎的API能力
二、WAWebview.js 框架JS庫,提供視圖層基礎的API能力
三、WAConsole.js 框架JS庫。控制檯
四、app-config.js 小程序完整的配置。包括咱們經過app.json裏的所有配置,綜合了默認配置型
五、app-service.js 咱們本身的JS代碼,所有打包到這個文件
六、page-frame.html 小程序視圖的模板文件,所有的頁面都使用此載入渲染。且所有的WXML都拆解爲JS實現打包到這裏
七、pages 所有的頁面。這個不是咱們以前的wxml文件了,主要是處理WXSS轉換,使用js插入到header區域。chrome

小程序架構

微信小程序的框架包括兩部分View視圖層、App Service邏輯層。View層用來渲染頁面結構,AppService層用來邏輯處理、數據請求、接口調用。它們在兩個進程(兩個Webview)裏執行。


視圖層和邏輯層經過系統層的JSBridage進行通訊,邏輯層把數據變化通知到視圖層,觸發視圖層頁面更新,視圖層把觸發的事件通知到邏輯層進行業務處理。

小程序架構圖:
這裏寫圖片描寫敘述

小程序啓動時會從CDN下載小程序的完整包。一般是數字命名的,如:_-2082693788_4.wxapkg

小程序技術實現

小程序的UI視圖和邏輯處理是用多個webview實現的,邏輯處理的JS代碼所有載入到一個Webview裏面,稱之爲AppService,整個小程序僅僅有一個。並且整個生命週期常駐內存,而所有的視圖(wxml和wxss)都是單獨的Webview來承載,稱之爲AppView。因此一個小程序打開至少就會有2個webview進程,正式因爲每個視圖都是一個獨立的webview進程,考慮到性能消耗,小程序不一樣意打開超過5個層級的頁面,固然同是也是爲了體驗更好。

AppService

可以理解AppService即一個簡單的頁面,主要功能是負責邏輯處理部分的執行,底層提供一個WAService.js的文件來提供各類api接口,主要是下面幾個部分:
消息通訊封裝爲WeixinJSBridge(開發環境爲window.postMessage, IOS下爲WKWebview的window.webkit.messageHandlers.invokeHandler.postMessage。android下用WeixinJSCore.invokeHandler)

一、日誌組件Reporter封裝
二、wx對象下面的api方法
三、全局的App,Page,getApp,getCurrentPages等全局方法
四、還有就是對AMD模塊規範的實現

而後整個頁面就是載入一堆JS文件,包括小程序配置config,上面的WAService.js(調試模式下有asdebug.js)。剩下就是咱們本身寫的所有的js文件,一次性都載入。

在開發環境下

一、頁面模板:app.nw/app/dist/weapp/tpl/appserviceTpl.js
二、配置信息,是直接寫入一個js變量。__wxConfig。
3,其它配置
這裏寫圖片描寫敘述

線上環境

而在上線後是應用部分會打包爲2個文件,名稱app-config.json和app-service.js,而後微信會打開webview去載入。線上部分應該是微信自身提供了對應的模板文件,在壓縮包裏沒有找到。


一、WAService.js(底層支持)
二、app-config.json(應用配置)
三、app-service.js(應用邏輯)

而後執行在JavaScriptCore引擎裏面。

AppView

這裏可以理解爲h5的頁面。提供UI渲染,底層提供一個WAWebview.js來提供底層的功能,詳細例如如下:
一、消息通訊封裝爲WeixinJSBridge(開發環境爲window.postMessage, IOS下爲WKWebview的window.webkit.messageHandlers.invokeHandler.postMessage。android下用WeixinJSCore.invokeHandler)
二、日誌組件Reporter封裝
三、wx對象下的api。這裏的api跟WAService裏的還不太同樣,有幾個跟那邊功能差點兒相同,但是大部分都是處理UI顯示相關的方法
四、小程序組件實現和註冊
五、VirtualDOM,Diff和Render UI實現
六、頁面事件觸發

在此基礎上,AppView有一個html模板文件,經過這個模板文件載入詳細的頁面。這個模板主要就一個方法,$gwx,主要是返回指定page的VirtualDOM,而在打包的時候,會事先把所有頁面的WXML轉換爲ViirtualDOM放到模板文件中,而微信本身寫了2個工具wcc(把WXML轉換爲VirtualDOM)和wcsc(把WXSS轉換爲一個JS字符串的形式經過style標籤append到header裏)。

Service和View通訊

使用消息publish和subscribe機制實現兩個Webview之間的通訊,實現方式就是統一封裝一個WeixinJSBridge對象。而不一樣的環境封裝的接口不同。詳細實現的技術例如如下:

windows環境

經過window.postMessage實現(使用chrome擴展的接口注入一個contentScript.js。它封裝了postMessage方法,實現webview之間的通訊。並且也它經過chrome.runtime.connect方式,也提供了直接操做chrome native原生方法的接口)
發送消息:window.postMessage(data, ‘*’);。// data裏指定 webviewID
接收消息:window.addEventListener(‘message’, messageHandler); // 消息處理並分發,相同支持調用nwjs的原生能力。
在contentScript裏面看到一句話。證明了appservice也是經過一個webview實現的,實現原理上跟view同樣,僅僅是處理的業務邏輯不同。

'webframe' === b ? postMessageToWebPage(a) : 'appservice' === b && postMessageToWebPage(a)

IOS

經過 WKWebview的window.webkit.messageHandlers.NAME.postMessage實現微信navite代碼裏實現了兩個handler消息處理器:
invokeHandler: 調用原生能力
publishHandler: 消息分發
這裏寫圖片描寫敘述

Android

經過WeixinJSCore.invokeHanlder實現,這個WeixinJSCore是微信提供給JS調用的接口(native實現)
invokeHandler: 調用原生能力
publishHandler: 消息分發

微信組件

在WAWebview.js裏有個對象叫exparser。它完整的實現小程序裏的組件,看詳細的實現方式,思路上跟w3c的web components規範神似,但是詳細實現上是不同的,咱們使用的所有組件,都會被提早註冊好,在Webview裏渲染的時候進行替換組裝。
exparser有個核心方法:
regiisterBehavior: 註冊組件的一些基礎行爲,供組件繼承
registerElement:註冊組件,跟咱們交互接口主要是屬性和事件

這裏寫圖片描寫敘述

組件觸發事件(帶上webviewID),調用WeixinJSBridge的接口,publish到native。而後native再分發到AppService層指定webviewID的Page註冊事件處理方法。

總結

小程序底層仍是基於Webview來實現的。並無發明創造新技術,整個框架體系。比較清晰和簡單,基於Web規範,保證現有技能價值的最大化,僅僅需瞭解框架規範便可使用已有Web技術進行開發。易於理解和開發。

MSSM:對邏輯和UI進行了全然隔離,這個跟當前流行的react,agular,vue有本質的差異,小程序邏輯和UI全然執行在2個獨立的Webview裏面,然後面這幾個框架仍是執行在一個webview裏面的,假設你想。仍是可以直接操做dom對象,進行ui渲染的。

組件機制:引入組件化機制,但是不全然基於組件開發。跟vue同樣大部分UI仍是模板化渲染,引入組件機制能更好的規範開發模式,也更方便升級和維護。

多種剋制:不能同一時候打開超過5個窗體。打包文件不能大於1M,dom對象不能大於16000個等。這些都是爲了保證更好的體驗。

相關文章
相關標籤/搜索