? ? ? ?你也在玩小程序?這些基本原理你知道嗎?
微信小程序使用了前端技術(shù)棧JavaScript/WXML/WXSS衷咽。它背后的原理是怎么樣的呢槽地?
寫在前面
微信小程序使用了前端技術(shù)棧JavaScript/WXML/WXSS。但和常規(guī)的前端開發(fā)又有一些區(qū)別:
JavaScript:微信小程序的JavaScript運(yùn)行環(huán)境即不是Browser也不是Node.js昔脯。它運(yùn)行在微信App的上下文中亏狰,不能操作Browser context下的DOM定枷,也不能通過Node.js相關(guān)接口訪問操作系統(tǒng)API。所以沉颂,嚴(yán)格意義來講条摸,微信小程序并不是Html5,雖然開發(fā)過程和用到的技術(shù)棧和Html5是相通的铸屉。
WXML:作為微信小程序的展示層钉蒲,并不是使用Html,而是自己發(fā)明的基于XML語法的描述彻坛。
WXSS:用來修飾展示層的樣式顷啼。官方的描述是“ WXSS (WeiXin
Style Sheets)是一套樣式語言踏枣,用于描述WXML的組件樣式。WXSS用來決定WXML的組件應(yīng)該怎么顯示钙蒙∫鹌伲” “我們的WXSS具有CSS大部分特性...我們對CSS進(jìn)行了擴(kuò)充以及修改」幔”基于CSS2還是CSS3马昨?大部分是哪些部分?是否支持CSS3里的動畫扛施?不得而知鸿捧。
在微信小程序官方文檔上,有下面這段話:
微信小程序運(yùn)行在三端:iOS煮嫌、Android和 用于調(diào)試的開發(fā)者工具
·在iOS上笛谦,小程序的javascript代碼是運(yùn)行在JavaScriptCore中
·在Android上,小程序的javascript代碼是通過X5內(nèi)核來解析
·在 開發(fā)工具上昌阿, 小程序的javascript代碼是運(yùn)行在nwjs(chrome內(nèi)核) 中
我們先從開發(fā)工具談起饥脑。
開發(fā)工具
小程序的javascript代碼運(yùn)行在nwjs中。nwjs是什么鬼呢懦冰?官方介紹是這樣寫的:
NW.js (previously known as node-webkit) lets you call allNode.js modules directly from DOM and enables a new way of writing applicationswith all Web technologies.
nwjs合并Browser和Node.js的運(yùn)行時灶轰,可以使用前端開發(fā)技術(shù)來開發(fā)跨平臺的應(yīng)用程序。借助Node.js訪問操作系統(tǒng)原生API的能力刷钢,可以開發(fā)中跨平臺的應(yīng)用程序笋颤。微信小程序開發(fā)工具就是使用nwjs開發(fā)的。如果你是Mac用戶内地,進(jìn)入目錄/Applications/wechatwebdevtools.app/Contents/Resources/app.nw/app可以看到開發(fā)工具的實現(xiàn)代碼伴澄,當(dāng)然代碼是經(jīng)過混淆的。網(wǎng)上流行的破解版本開發(fā)工具原理上就是修改這里面的代碼阱缓。
與此類似的非凌,一個更火的項目是Electron,由GitHub推出的荆针,它也是把Browser和Node.js結(jié)合敞嗡,用來開發(fā)跨平臺的應(yīng)用程序。程序員們應(yīng)該聽說過Atom這個編輯器界的后起之秀航背。包括微軟擁抱開源社區(qū)的編輯器vscode也是使用Electron開發(fā)的喉悴。
Electron vs nwjs
這兩個平臺有什么區(qū)別?為什么微信選擇nwjs呢玖媚?我們不妨猜一猜箕肃。
從技術(shù)角度來講:
應(yīng)用程序入口不同:Electron入口是一個javascript腳本,腳本里要自己負(fù)責(zé)創(chuàng)建瀏覽器窗口今魔,加載html頁面突雪。而nwjs的入口就是一個html頁面起惕,框架自己會創(chuàng)建瀏覽器窗口來顯示這個html頁面。
Node.js集成方式不同:Electron直接使用Node.js的共享庫咏删,不需要修改Chromium代碼惹想。而nwjs為了集成Node.js,需要修改Chromium代碼督函,以便在瀏覽器里能通過Node.js訪問系統(tǒng)原生API嘀粱。
Multi-Context:
nwjs有多個上下文,一個是瀏覽器的上下文辰狡,用來訪問Browser相關(guān)API锋叨,比如操作DOM,另外一個是Node上下文宛篇,用來訪問操作系統(tǒng)API娃磺。Electron沒有使用多個上下文,對開發(fā)者更友好叫倍。
從應(yīng)用角度來講:
打包后的文件大型滴浴:Electron打包后文件會比nwjs小不少。一個18M的程序吆倦,使用Electron打包后是117M听诸,而使用nwjs打包后的程序是220M。微信小程序開發(fā)工具打包后是219M (v0.10.102800)蚕泽。沒有親測晌梨,評價來源參考文檔。
代碼保護(hù):Electron只支持代碼混淆來保護(hù)须妻,而nwjs把核心代碼放在V8引擎里仔蝌,不但可以保護(hù)代碼,還可以提高執(zhí)行效率荒吏。
開源社區(qū)活躍度:Electron應(yīng)該是完勝的掌逛。看看使用Electron構(gòu)建的應(yīng)用程序就知道了司倚。而據(jù)說nwjs的開發(fā)文檔有些都沒有及時更新。
應(yīng)用程序啟動時間:Electron會稍微快一點篓像。沒有親測动知,評價來源參考文檔。
從這個分析猜測员辩,微信選擇nwjs的原因可能是出于代碼保護(hù)盒粮。畢竟開發(fā)工具可以上傳小程序,有些接口和數(shù)據(jù)需要比較嚴(yán)密的保護(hù)奠滑。哪位大诺ぶ澹可以挖挖看哪些代碼被保護(hù)起來了妒穴。
真機(jī)運(yùn)行環(huán)境
下面內(nèi)容完全是猜測的,如有言中摊崭,實屬運(yùn)氣讼油。
微信小程序的運(yùn)行環(huán)境應(yīng)該更類似ReactNative之類,而不是純Html5呢簸。兩者最大的不同在于矮台,ReactNative的界面是由原生控件渲染出來的,而Html5的界面是由瀏覽器內(nèi)核渲染出來的根时。兩者在性能上有較大的差異瘦赫,感興趣的可以參閱我的另外一篇文章《跨平臺
App 開發(fā)技術(shù)方案匯總》。
原理上蛤迎,小程序是如何在微信App里運(yùn)行的呢确虱?
微信App里包含javascript運(yùn)行引擎。
微信App里包含了WXML/WXSS處理引擎替裆,最終會把界面翻譯成系統(tǒng)原生的控件校辩,并展示出來。這樣做的目的是為了提供和原生App性能相當(dāng)?shù)挠脩趔w驗扎唾。
我們來意淫一下小程序加載運(yùn)行的過程:
用戶點擊打開一個小程序
微信App從微信服務(wù)器下載這個小程序
分析app.json得到應(yīng)用程序的配置信息(導(dǎo)航欄召川,窗口樣式,包含的頁面列表等)
加載并運(yùn)行app.js
加載并顯示在app.json里配置的第一個頁面
這個只是從開發(fā)者眼中看到的一個簡化版的過程胸遇,實際過程應(yīng)該比這要復(fù)雜得多荧呐,涉及到瀏覽器線程(就是運(yùn)行我們的邏輯層代碼app.js等的線程)和AppService線程之間的交互。
生命周期
至于微信App是如何與小程序的邏輯層javascript交互的呢纸镊?可以簡單地歸納如下:
JavaScript是腳本語言倍阐,可以在運(yùn)行時解釋并執(zhí)行。微信App里包含了一個JavaScript引擎逗威,由它來負(fù)責(zé)執(zhí)行邏輯層的JavaScript代碼峰搪。那么JavaScript調(diào)用的小程序相關(guān)API怎么實現(xiàn)的呢?答案是最終會被翻譯成實現(xiàn)在微信App里的原生接口凯旭。比如開發(fā)者調(diào)用wx.getLocation(OBJECT)獲取當(dāng)前地理位置概耻,微信App里的JavaScript引擎在執(zhí)行這個代碼時,會去調(diào)用微信App里實現(xiàn)的原生接口來獲取地理位置坐標(biāo)罐呼。
感興趣的朋友可以閱讀我之前推薦過的一篇文章《React
Native 從入門到原理》鞠柄。文章分析的雖然是ReactNative,但實際上原理是相通的嫉柴。
總結(jié)
微信小程序最大的好處是不需要做設(shè)備適配厌杜,只要微信能運(yùn)行,小程序就能運(yùn)行。小程序雖然是一個封閉形態(tài)下的前端開發(fā)技術(shù)夯尽,但借助微信的巨大影響力瞧壮,幾乎所有人都在往里面沖。微信小程序太火了匙握,內(nèi)測火咆槽,公測更火。內(nèi)測剛出來肺孤,就有人用微信小程序?qū)崿F(xiàn)了商城罗晕,并開源。感嘆一下:你的熱情赠堵,就像一把火小渊,燃燒了整個沙漠。
作為開發(fā)者茫叭,提幾個不足:
不支持從node_modules中加載模塊酬屉。這樣無形中就把npm排除在外了。從開發(fā)生態(tài)角度揍愁,這個應(yīng)該是微信小程序下一步要重點解決的問題吧呐萨。
開發(fā)工具自帶的代碼編輯器還是太簡陋了。不知道為什么微信要重復(fù)發(fā)明輪子莽囤。理論上谬擦,給流行的代碼編輯器(sublime/atom/vscode etc.)開發(fā)個插件。然后用戶直接到小程序后臺上傳提交審核就好了朽缎。程序員是挑剔到近乎偏執(zhí)的物種惨远,代碼編輯器又是程序員時刻打交道的工具,要做好實屬不易话肖。