實現微信小程序編譯和運行環境系列 (初始篇)
前言
最近一段時間在研究實現微信小程序和小游戲編譯打包和運行環境平臺開發。
目前基本可以支持微信基礎庫 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 如圖:
從上圖和我們的一些理解我們知道微信小程序的文件格式主要組成:
- .js 主要頁面邏輯; 
- .wxml 頁面結構,框架設計的一套標簽語言,結合基礎組件、事件系統,可以構建出頁面的結構; 
- .wxss 是一套樣式語言,用于描述 WXML 的組件樣式; 
- .json 頁面配置按照『約定優于配置』的原則。 
接下來我們先找到本機微信開發者工具應用包里面如圖
我們后面分析的主要代碼都在 package.nw 里面和 core.wxvpkg。
這些文件在后面實現過程中都會使用說明用途的。
- js 文件里面的內容主要是在頁面和邏輯層的渲染用,后面將會看到; 
- core.wxvpkg 是這個里面的核心文件破解這個包可以知道很多邏輯可以先給大家看下解壓后包的結構: 
core.wxvpkg 解壓代碼上傳在 unwxvpkg 大家有興趣可以自己先試試。
接下來我們回到開發者工具中打開:
微信開發者工具–》調試–》調試微信開發者工具
打開調試后我們可以看到的界面如下:
從上面的現象我們可以看出他的兩層渲染層和邏輯層結構是包含在兩個 webview 里面
第一個對應的 webview 是渲染層的每個頁面都對應一個地址
但邏輯層 appservice 只有一個不變的
下來我們可以看看這個 webview 里面是個什么東
如果我們直接把 view 層的 webview 標簽改成 iframe 的話
可以看到微信就直接不在里面展示給你頁面白屏了
如果你更改 appservice 的 webview 的話微信還會給你各種 alert 彈框,反正應該就是不想讓你分析他的代碼
點擊確定消都消不了只能重新重啟編譯了 有點小惡心啊
居然不讓我們正大光明的看,那我們只能搞一些旁門左道來破壞了
我們第一步還是打開:微信開發者工具–》調試–》調試微信開發者工具
在控制臺輸入
 復制代碼
document.getElementsByTagName('webview')可以看到對應的有 4 個 webview, 我們先要關注的是第一個 webview 因為你點開可以發現第一個對應的就是渲染層的 webview
后面的幾個可以先不關注,后續我們會詳解
然后我們執行命令打開第一個 webview:
 復制代碼
document.getElementsByTagName('webview')[0].showDevTools(true,null)可以看到如圖
現在我們就可以看到微信頁面渲染層的頁面結構了
(這里說明下本篇文章中文件里面的內容每一個文件的來源和用途,我都會在后續章節中講解出來 因為里面涉及的內容過多 我怕放在一篇文章里會太長大家看了會厭煩,所以我會分為幾篇來說明,后面的 appservice 和 一些基礎包和 WAWebview.js WAService.js 以及使用的同步 api 和請求在頁面的 appservice.js 等等,在本篇中只會簡單描述出來 不做過多講解,后續會逐步更新)
上面的 webview 可以找到對應的頁面層的結構,那么 appservice 要怎么找到呢?
其實最簡單的我們直接在首頁里面的控制臺打 document 就可以直接看到展示的邏輯層代碼
(我的做法是從寫了微信的 alert 和基礎庫的一些文件都可以看到這個結構)
注意點在微信小游戲里面微信重寫了 window 和 document 對象 所以不能直接按照我們平常操作頁面那樣使用
接下面我們看下微信小程序的基礎庫庫文件
方法是我們在首頁控制臺里面輸入 openVendor()
我們可以看到彈出的文件系統,這里面對應的就是你選擇本地的
詳情 ==》調試基礎庫 ==》選擇基礎庫版本
- .wxvpkg 文件就是每個基礎庫版本的包我們,解壓這個包我們可以看到他的組成; 
- wcc 可執行程序,用于將 wxml 轉為 view 模塊使用的 js; 
- wcsc 可執行程序,用于將 wxss 轉為 view 模塊使用的 css。 
.wxvpkg 包里面這個基礎庫文件的 WAWebview.js 和 WAService.js,對應這兩個 webview 里面的 js 引用你可以仔細觀察下.wxvpkg 文件解包后的格式:
對于 wcc 和 wcsc 源碼現在沒必要去研究他,但我們可以通過腳本劫持方法可以看到他運行了什么命令操作
這里告訴大家一個方法劫持他的運行命令
找到微信開發者工具 wcc 和 wcsc 的地方然后新建兩個同名的腳本,然后把原文件從命名,然后重啟微信開發者工具 一定要重啟不然不生效
然后我們到首頁控制臺還是輸入 openVendor() 可以看到輸出的文件
從上面這個圖就可以看出下面這個圖里面我們可以認知到一些信息
- 首次加載的時候 wcc 執行了 -ds -d - xc…和 -ds -d - cc…結構的命令可以看到微信首次把所有.wxml 都執行了 
- 可以看到參數里面有個數字其實他對應的有幾種.wxml 文件形式向只存在.wxml 和自定義組件等一些格式他是沒計算在內的 
- -xc -cc 其實對應就是下面圖兩個邏輯層和渲染層里面的 js 方式 
- 我發現當我們修改一個.wxml 里面一點改動的時候,微信又會全部從新編譯執行這些命令很耗時這點其實可以改進的。 
- 另一個微信開發者工具感覺做的不友好的地方是大于 500KB 的 javascript 文件不做給你做 es6 轉換和壓縮,就算你設置了微信也不會給你轉,可以在 source 里面的資源可以看出。 
wcc 執行的命令最終生成的就是邏輯層和渲染層的 $gwxc() 方法里面的 js 代碼,大家可以自己手動測試下就會發現。
wxss 生成的主要是渲染層 eval() 這一坨代碼
本篇只是簡單描述了一些關鍵文件的描述。
后面我會對關鍵文件進行一一分析描述下他具體做了什么,為什么用到它。
下一篇會給大家帶來渲染層和邏輯層的具體頁面文件內容結構解析,以及 webstock 通信架構在微信開發者工具里面的運用,可以先給大家看下。


















