本文包括的內容:css
介紹小程序原理的文章比較多,這篇講的比較細:微信小程序架構分析。這篇文章的做者也成功的實現了wept,讓小程序運行在本身的webapp裏。html
參考最多的是微店的Hera,完成度很是高的小程序框架,可以將小程序的demo代碼在web/iOS/android運行起來,並且實現了不少工具。Hera的問題是開發於比較早期的版本,不兼容最新的版本了。Hera還有一個問題是他修改了小程序構建以後的目錄結構,採用了service.html做爲service部分的入口,跟小程序自己的實現尚有有一些區別。因此Hera只可以構建執行本身編寫的小程序,不能執行別人編寫的小程序。vue
個人目標是可以運行其它人開發的app,意味着我只能經過逆向的方式拿到wxapkg。可是由於拿不到源碼,因此要儘量在構建環節跟小程序保持一致。python
通過數週的掙扎,目前已經實現了運行官方demo。已經達到"可行"的階段,可是還遠遠談不上「可用」,由於須要實現小程序大量的API,這是個體力活,依賴我的的力量難以完成。android
官方demo小程序原先的目錄分爲幾類文件:git
demo
├── app.js
├── app.json
├── app.wxss
├── config.js
├── image
│ ├── green_tri.png
│ ├── ...
├── page
│ ├── API
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── pages
│ │ │ ├── action-sheet
│ │ │ │ ├── action-sheet.js
│ │ │ │ ├── action-sheet.json
│ │ │ │ ├── action-sheet.wxml
│ │ │ │ └── action-sheet.wxss
│ │ │ ├── ...
│ │ └── resources
│ │ └── ...
│ ├── ...
├── project.config.json
├── util
│ └── util.js
└── vendor
└── qcloud-weapp-client-sdk
├── ...
複製代碼
通過小程序的開發環境構建後,生成了一個*.wxapkg文件。 這個文件能夠經過從越獄的iPhone或者root的安卓手機上拿到。有部分人用charles經過https抓包拿到了下載連接,也拿到了包。 拿到後要進行解包。有大神已經經過反編譯安卓apk的方式拿到了解包部分的代碼,而後用python重寫了一遍。源碼見wechat-app-unpack。github
解包後獲得的目錄以下:web
1.wxapkg_dir
├── app-config.json
├── app-service.js
├── app-service.js.map
├── image
│ ├── green_tri.png
│ ├── ...
├── page
│ ├── API
│ │ ├── index.html
│ │ ├── pages
│ │ │ ├── action-sheet
│ │ │ │ └── action-sheet.html
│ │ │ ├── ...
│ │ └── resources
│ │ └── kind
│ │ ├── api.png
│ │ ├── ...
│ ├── ...
└── page-frame.html
複製代碼
轉換過程能夠分爲三部分:算法
openVendor
命令能夠在小程序中獲取到構建腳本wcc和wcsc, 以及各個版本小程序的執行SDK ****.wxvpkg,這個SDK也能夠用wechat-app-unpack解開,解開后里面就是WAService.js和WAWebView.js等代碼。json
wxss 轉換成了css,wxml轉換成了inject_js,實際上就是virtual_dom。 是用什麼工具轉換的?小程序裏是叫wcc和wcsc。在開源工具hera本身實現了一套wxss-transpiler和wxml-transpiler。而hera的前身wept是直接使用wcc和wcsc。 咱們爲了減小維護成本,直接採用wcc和wcsc。 由於咱們沒有wcc和wcsc的源碼,因此只能藉助wxss-transpiler和wxml-transpiler來幫助咱們理解wxml/wxss的構建原理。
wxss-transpiler調用了一個PostCSS的插件,用來處理wxss。 PostCSS 提供了一種方式用 JavaScript 代碼來處理 CSS。它負責把 CSS 代碼解析成抽象語法樹結構(Abstract Syntax Tree,AST),再交由插件來進行處理。插件基於 CSS 代碼的 AST 所能進行的操做是多種多樣的,好比能夠支持變量和混入(mixin),增長瀏覽器相關的聲明前綴,或是把使用未來的 CSS 規範的樣式規則轉譯(transpile)成當前的 CSS 規範支持的格式。
wxml-transpiler:實現了一個轉譯器的工做,好比postcss也是轉譯器,包括解釋器(parser),代碼轉換器(Transformer),代碼生成器(Generator)。這個是閉源的。
更多實現原理見這篇文章
小程序在App中執行時的時候分爲三個不一樣的模塊,View/Service/Native,各司其職。
View和Service都在WKWebView中執行,互相沒法調用。他們之間經過Native層通訊。
Native和WebView之間經過webkit.messagehandler和evaluateJavascript互相調用。
WeixinJSBridge.publish: view和service之間的透傳,在WKWebView之間傳遞消息。
WeixinJSBridge.subscribe: 註冊監聽,監聽view和service之間的消息調用。
WeixinJSBridge.invoke: View或者Service傳遞消息到Native,而後Native使用邏輯調用js callback。
WeixinJSBridge.on:監聽Native的事件。
這裏以iOS爲例介紹Native執行過程。安卓相似。
經過解壓微信的ipa能夠拿到WAService.js和WAWebView.js兩個基礎庫文件,文件內容與hera的service.js/view.js已經有了較大的區別。 咱們採用小程序的架構和hera的兩個webView的方案,儘量模仿小程序的執行過程。
View部分是比較直觀的,就是WKWebView加載web頁。這裏須要在app-config.json裏讀取到首頁的路徑,而後加載該頁面。這個路徑下的xxx/index.html是沒法直接加載的,須要作一些處理。要引入本地執行SDK裏的index.css和view.js, 而後把page-frame.html
裏的virtual-dom所有塞進該頁面。 而後loadHTML便可。
View全部的WKWebView也是要註冊WKUserContentController的,用於通訊。 經過反彙編能夠得知這個類在微信中叫YYWAWebView
,調用js是直接調用-evaluateJavaScript:completionHandler:
方法的。
view.js中包含的邏輯:
Service部分的實現,Hera和微信小程序採起的了不一樣的架構。 Hera的實現較爲簡潔,跟View部分保持一致,採用了WKWebView,調用-evaluateJavaScript:completionHandler:
方法執行js,js回調OC時使用WKScriptMessageHandler。 經過反彙編能夠得知這個類在微信中叫WAJSCoreService
,js和OC之間的調用是採用JavascriptCore互相調用。
JavascriptCore它首先要加載app-config.json並把這個配置賦給一個全局對象__wxConfig。而後他要加載service.js是SDK基礎,再而後他要加載app-service.js,這裏麪包含了用戶編寫的js邏輯。最後它發出全局消息 WeixinJSBridge.publish('serviceReady',,);</script>
喚起小程序app的初始化。
Service.js中包含的邏輯:
Native執行的問題比較複雜,由於基本是黑盒,裏面發生了什麼並不知道。 hera的方案在構建過程就已經跟小程序實際的方案有所區別,會提升維護成本。因此咱們只能靠猜想來實現Native的執行過程。
Native部分就是做爲入口,運行環境,跳轉,轉發消息,實現擴展。包括網絡模塊/攝像頭/tabbar實現的都是擴展。 咱們能夠得知的是消息傳遞的協議。而後只能經過safari來調試webView,根據協議的名稱和出入參來猜想協議的內容。
小程序是顛覆我對Web的固有印象,最初還覺得是相似weex或者rn的調用原生的方式,沒想到幾乎徹底是運行在WKWebView之上的。
存在的問題:
setData:
這種傳遞整個model對象,是兩次對象的深拷貝,可能會增長兩次json的序列化和反序列化,若是model對象很複雜對性能影響比較大。固然已經比純web頁強不少了。目前來看仍是隻適合輕量化的應用。受制於架構以及微信的平臺,我的認爲是對Web的替代和改善。可是就算在可見的將來,仍是很難跟native抗衡。
現代瀏覽器和操做系統之間的界限愈來愈模糊。App的"下載/安裝"過程自己就是一種妥協。只要小程序的體驗足夠好,應該沒有人會拒絕。