【轉】微信小程序也要強行熱更代碼,鵝廠不服你來肛我呀

點擊查看原文排版更好哦

前言

微信爲了限制小程序的熱更越過審覈,所以限制了 eval / new Function 等方式動態執行代碼。其實說實話,限制熱更本來能理解,但是你這審覈速度如此龜速,讓版本迭代和bug修復都異常艱難。尤其是今年春節前夕的時候,我們小程序一審就是5天!但是隔壁某大廠的告訴我們他們小程序審覈才用了3個小時,所以也不難猜測我們這些創業小廠永遠都是被瘋狂插隊的。

好,鵝廠既然你不仁,那就特麼我就別怪我不義了。不能用 eval / new Function 就不能動態執行代碼了?不存在的!這種限制聊勝於無,不過一張紙而已,有本事就關了 ajax 呀。

把最近寫的文章也更新在這裏吧,方便大家學習正確的姿勢:

前端要以正確的姿勢學習編譯原理(上篇)

首先用 JavaScript 寫一個 JavaScript 解釋器

熱更的第一步,就是用 JavaScript 寫一個 JavaScript 解釋器。對於很多小夥伴來說,寫一個JavaScript 解釋器這聽起來天方夜譚,但事實上卻是非常簡單,因爲使用 JavaScript 實現 JavaScript 解釋器,所以語義幾乎可以完全複用。

我現在列一下具體實現步驟:

  • 解析 JavaScript 代碼字符串,得到 JavaScript 代碼的抽象語法樹(AST)。解析這個步驟不需要自己做,有非常多優秀的現成的庫,比如 acornjs/acorn 。結果會解析成標準的 ESTree。
  • 因爲 JavaScript 的語法樹是有標準格式的 estree/estree ,所以只需要對照這個標準格式進行實現語法樹的求值,只要保證 JavaScript 一樣的語義,就和 eval / new Function 等效果差不多了。

需要注意的細節:

  • 作用域。比如 var 聲明的變量是函數作用域,const / let 是詞法作用域,這些要注意區分。
  • || 和 && 運算符。這兩個運算符有短路的效果,所以不能和其他運算符一樣先求兩邊的值。
  • 函數閉包。就像上述所說的,用 JavaScript 實現 JavaScript 解釋器幾乎可以完全複用 JavaScript 語義,在這裏就體現的淋漓精緻了。解釋器函數閉包就可以用語言本身的閉包來進行實現,非常輕鬆愉快。
  • 注入標準庫。我們做這個解釋器的目的不是爲了做沙盒,所以沒有對環境進行隔離,但是即便如此,我們還是需要把 JavaScript 的標準庫注入進去。標準庫可以在 JavaScript 標準庫 找到。
  • new 操作符。這個問題我研究了很久,最終找到了還算是有效的方案,在下面示例代碼裏面有。
  • 打斷控制流的操作。break / return / continue 這類會打斷控制流的操作,處理起來需要小心。
    示例代碼:bramblex/jsjs

效果如下:在這裏插入圖片描述

然後設計完整熱更方案

page / component 這種東西我暫時還沒研究過能怎麼更新,畢竟我對小程序也不是非常熟悉。我們就直接討論如何熱更程序代碼吧。

首先既然我們要熱更,我們就必須思考幾個問題:

  • 從哪裏更新代碼?毫無疑問,我們需要一個用來更新的服務器。
  • 更新下來的代碼放在那裏?目前來看,更新下來的放在小程序裏面的 Storage 裏面就很好。
  • 什麼時候知道代碼需要更新了?要解決這個問題,那需要我們要在遠端服務器和本地記錄代碼版本,對比版本來確定是否需要更新。
  • 代碼什麼時候時候執行?我建議是把熱更的代碼當成一個單獨的模塊,在 App 創建之前就可以執行了

接下來,解決問題,設計具體熱更方案:

  • 代碼從服務器更新,有兩個 api 。/update/version 返回 v0.0.1 這樣的版本號,/update/code 返回代碼字符串。
  • 本地的 Storage 有 version 和 code 兩個 key 進行存儲對應的本地代碼和版本。
    當打開小程序的時候,獲取比較本地版本和遠程版本,如果版本一致怎不管,如果版本不一致則更新本地代碼。
  • 執行熱更的代碼,熱更部分代碼可以用 module.exports 或者你喜歡的變量形勢導出暴露的接口,保存在一個模塊裏面。
  • 然後各個 page 調用熱更部分的模塊代碼,嵌進業務代碼裏面。
  • 具體方案的示例代碼我就不給了,因爲我也沒有……畢竟,之後如果需要有什麼項目需要熱更小程序的時候,再寫這部分代碼,反正已經設計好了。

最後

這個方案還有非常多能夠改進的地方,比如用實現 IR 中間碼來進行傳輸和使用,提升性能和內存佔用等等。不過這是後話了,之後有時間再做改善吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章