實現微信小程式編譯和執行環境系列(初始篇)

風逝_發表於2019-11-02

前言

最近一段時間在研究實現微信小程式和小遊戲編譯打包和執行環境平臺開發

目前基本可以支援微信基礎庫2.8.2功能迭代了

所以想通過記錄分享一下自己的認知過程中遇到的一些問題和解決方案來更好的理解小程式設計上的優點和一些不足的地方

在此之前網上有存在開源的一些基於微信基礎庫版本1.0的一些參考 核心作者是由開源大牛啟明兄wept專案基礎上構建的(目前有幸和啟明兄成為同事對這個小程式整體的架構理解幫助了我很多)

由於wept的執行環境是基於微信基礎庫1.0的版本上實現之後也不維護了,時間上是2016的在後續的更新的版本中新加的一些特性如自定義元件 npm包很多api等開發實現都不支援, 最主要是的微信在後續架構中更換底層的通訊方式採用了webstock的方式等一些其他變化


正文

後面我會通過幾篇文章來整體描述一下從工具到破解到原始碼解析和原理到實現的處理流程

最開始的時候也在網上找了很多的資料,看了有一些人寫的解析微信小程式架構的文章,從中學習瞭解了很多

但如果想模擬實現出來這麼個東西 還是有蠻迷糊的,所以我想通過我們所實現的過程來一點點從現象 看本質來解析下微信小程式編譯和執行原理

凡事對自己多點信心 多堅持下 多學習下,想想我們遇到的問題,當時感覺我 搞不定了 弄不了 最後隨著時間的推移和認知的迭代問題總會慢慢消滅掉


本文將先通過全面解析微信開發者工具來知道那些基本的檔案和內容組成一一講述(從現象 看本質)

在此之前我們通過官方文件可以瞭解一些內容

  • 整個小程式框架系統分為兩部分:邏輯層(App Service)和 檢視層(View)

  • 小程式提供了自己的檢視層描述語言 WXML 和 WXSS

  • 基於 JavaScript 的邏輯層框架,並在檢視層與邏輯層間提供了資料傳輸和事件系統他們兩個執行緒裡執行

  • 檢視層使用WebView渲染,邏輯層使用JSCore執行, 檢視層和邏輯層通過系統層的JSBridage進行通訊,邏輯層把資料變化通知到檢視層,觸發檢視層頁面更新, 檢視層把觸發的事件通知到邏輯層進行業務處理

從上述說明中我們可以得知一些重要資訊邏輯層(App Service)和 檢視層(View) 以及兩者之間的通訊協調

下面通過微信開發工具來展示說明,小程式邏輯層的 javascript 程式碼是執行在 NW.js 中,檢視層是由 Chromium 60 Webview 來渲染的 他們之間是通過webstock協議來通訊的

以下我們主要是以mac環境為主

我們先開啟 微信開發工具官方demo 如圖

1

從上圖和我們的一些理解我們知道微信小程式的檔案格式主要組成

  • .js 主要頁面邏輯
  • .wxml 頁面結構,框架設計的一套標籤語言,結合基礎元件、事件系統,可以構建出頁面的結構。
  • .wxss 是一套樣式語言,用於描述 WXML 的元件樣式。
  • .json 頁面配置按照『約定優於配置』的原則。

接下來我們先找到本機微信開發者工具應用包裡面如圖

2

我們後面分析的主要程式碼都在package.nw裡面和core.wxvpkg

這些檔案在後面實現過程中都會使用說明用途的

  • js檔案裡面的內容主要是在頁面和邏輯層的渲染用,後面將會看到
  • core.wxvpkg是這個裡面的核心檔案破解這個包可以知道很多邏輯可以先給大家看下解壓後包的結構
3 4

core.wxvpkg解壓程式碼上傳在unwxvpkg大家有興趣可以自己先試試


接下來我們回到開發者工具中開啟

微信開發者工具--》除錯--》除錯微信開發者工具

7

開啟除錯後我們可以看到的介面如下:

6

從上面的現象我們可以看出他的兩層渲染層和邏輯層結構是包含在兩個webview裡面

第一個對應的webview是渲染層的每個頁面都對應一個地址

但邏輯層appservice只有一個不變的

下來我們可以看看這個webview裡面是個什麼東

如果我們直接把view層的webview標籤改成iframe的話

可以看到微信就直接不在裡面展示給你頁面白屏了

7 1

如果你更改appservice的webview的話微信還會給你各種alert彈框,反正應該就是不想讓你分析他的程式碼

7 2 7 3

點選確定消都消不了只能重新重啟編譯了 有點小噁心啊

居然不讓我們正大光明的看,那我們只能搞一些旁門左道來破壞了

我們第一步還是開啟:微信開發者工具--》除錯--》除錯微信開發者工具 在控制檯輸入

document.getElementsByTagName('webview')

可以看到對應的有4個webview,我們先要關注的是第一個webview因為你點開可以發現第一個對應的就是渲染層的webview

後面的幾個可以先不關注,後續我們會詳解

然後我們執行命令開啟第一個webview:

document.getElementsByTagName('webview')[0].showDevTools(true,null)

可以看到如圖

8

現在我們就可以看到微信頁面渲染層的頁面結構了

(這裡說明下本篇文章中檔案裡面的內容每一個檔案的來源和用途,我都會在後續章節中講解出來 因為裡面涉及的內容過多 我怕放在一篇文章裡會太長大家看了會厭煩,所以我會分為幾篇來說明,後面的appservice 和 一些基礎包和WAWebview.js WAService.js以及使用的同步api和請求在頁面的appservice.js等等,在本篇中只會簡單描述出來 不做過多講解,後續會逐步更新)

上面的webview可以找到對應的頁面層的結構,那麼appservice要怎麼找到呢?

其實最簡單的我們直接在首頁裡面的控制檯打document就可以直接看到展示的邏輯層程式碼

(我的做法是從寫了微信的alert和基礎庫的一些檔案都可以看到這個結構)

9

注意點在微信小遊戲裡面微信重寫了window和document物件 所以不能直接按照我們平常操作頁面那樣使用

接下面我們看下微信小程式的基礎庫庫檔案

方法是我們在首頁控制檯裡面輸入openVendor() 我們可以看到彈出的檔案系統,這裡面對應的就是你選擇本地的

詳情==》除錯基礎庫==》選擇基礎庫版本

10
  • .wxvpkg檔案就是每個基礎庫版本的包我們,解壓這個包我們可以看到他的組成

  • wcc 可執行程式,用於將 wxml 轉為 view 模組使用的js

  • wcsc 可執行程式,用於將 wxss 轉為 view 模組使用的 css

.wxvpkg包裡面這個基礎庫檔案的WAWebview.js和WAService.js

對應這兩個webview裡面的js引用你可以仔細觀察下

.wxvpkg檔案解包後的格式

11

解壓.wxvpkg格式包的程式碼地址github

對於wcc和wcsc原始碼現在沒必要去研究他,但我們可以通過指令碼劫持方法可以看到他執行了什麼命令操作

這裡告訴大家一個方法劫持他的執行命令

找到微信開發者工具wcc和wcsc的地方然後新建兩個同名的指令碼,然後把原檔案從命名,然後重啟微信開發者工具一定要重啟不然不生效

wcc wcsca劫持指令碼程式碼地址github

13

然後我們到首頁控制檯還是輸入openVendor()可以看到輸出的檔案

13 2

從上面這個圖就可以看出下面這個圖裡面我們可以認知到一些資訊

  • 首次載入的時候wcc執行了-ds -d - xc...和-ds -d - cc...結構的命令可以看到微信首次把所有.wxml都執行了
  • 可以看到引數裡面有個數字其實他對應的有幾種.wxml檔案形式向只存在.wxml和自定義元件等一些格式他是沒計算在內的
  • -xc -cc 其實對應就是下面圖兩個邏輯層和渲染層裡面的js方式
12
  • 我發現當我們修改一個.wxml裡面一點改動的時候,微信又會全部從新編譯執行這些命令很耗時這點其實可以改進的
  • 另一個微信開發者工具感覺做的不友好的地方是大於 500KB 的 javascript 檔案不做給你做es6 轉換和壓縮,就算你設定了微信也不會給你轉,可以在source裡面的資源可以看出

wcc執行的命令最終生成的就是邏輯層和渲染層的$gwxc()方法裡面的js程式碼,大家可以自己手動測試下就會發現

13 3

wxss生成的主要是渲染層eval()這一坨程式碼

14

本篇只是簡單描述了一些關鍵檔案的描述

後面我會對關鍵檔案進行一一分析 描述下他具體做了什麼,為什麼用到它

下一篇會給大家帶來渲染層和邏輯層的具體頁面檔案內容結構解析,以及webstock通訊架構在微信開發者工具裡面的運用 可以先給大家看下

15

其實他們之間的協調工作以及公開對外的wx.物件上面的api都是 通過websocket協議訊息實現的

原文地址github感覺有用的話點個star支援一下

歡迎持續關注

相關文章