高性能JavaScript模板引擎實(shí)現(xiàn)原理詳解
隨著 web 發(fā)展,前端應(yīng)用變得越來(lái)越復(fù)雜,基于后端的 javascript(Node.js) 也開(kāi)始嶄露頭角,此時(shí) javascript 被寄予了更大的期望,與此同時(shí) javascript MVC 思想也開(kāi)始流行起來(lái)。javascript 模板引擎作為數(shù)據(jù)與界面分離工作中最重要一環(huán),越來(lái)越受開(kāi)發(fā)者關(guān)注,近一年來(lái)在開(kāi)源社區(qū)中更是百花齊放,在 Twitter、淘寶網(wǎng)、新浪微博、騰訊QQ空間、騰訊微博等大型網(wǎng)站中均能看到它們的身影。
本文將用最簡(jiǎn)單的示例代碼描述現(xiàn)有的 javascript 模板引擎的原理,包括新一代 javascript 模板引擎 artTemplate 的特性實(shí)現(xiàn)原理,歡迎共同探討。
artTemplate 介紹
artTemplate 是新一代 javascript 模板引擎,它采用預(yù)編譯方式讓性能有了質(zhì)的飛躍,并且充分利用 javascript 引擎特性,使得其性能無(wú)論在前端還是后端都有極其出色的表現(xiàn)。在 chrome 下渲染效率測(cè)試中分別是知名引擎 Mustache 與 micro tmpl 的 25 、 32 倍。

除了性能優(yōu)勢(shì)外,調(diào)試功能也值得一提。模板調(diào)試器可以精確定位到引發(fā)渲染錯(cuò)誤的模板語(yǔ)句,解決了編寫(xiě)模板過(guò)程中無(wú)法調(diào)試的痛苦,讓開(kāi)發(fā)變得高效,也避免了因?yàn)閱蝹€(gè)模板出錯(cuò)導(dǎo)致整個(gè)應(yīng)用崩潰的情況發(fā)生。
artTemplate 這一切都在 1.7kb(gzip) 中實(shí)現(xiàn)!
javascript 模板引擎基本原理
雖然每個(gè)引擎從模板語(yǔ)法、語(yǔ)法解析、變量賦值、字符串拼接的實(shí)現(xiàn)方式各有所不同,但關(guān)鍵的渲染原理仍然是動(dòng)態(tài)執(zhí)行 javascript 字符串。
關(guān)于動(dòng)態(tài)執(zhí)行 javascript 字符串,本文以一段模板代碼舉例:

這是一段非常樸素的模板寫(xiě)法,其中,”” 為 closeTag (邏輯語(yǔ)句閉合標(biāo)簽),若 openTag 后面緊跟 “=” 則會(huì)輸出變量的內(nèi)容。
HTML語(yǔ)句與變量輸出語(yǔ)句被直接輸出,解析后的字符串類似:

語(yǔ)法分析完畢一般還會(huì)返回渲染方法:

渲染測(cè)試:

在上面 render 方法中,模板變量賦值采用了 with 語(yǔ)句,字符串拼接采用數(shù)組的 push 方法以提升在 IE6、7 下的性能,jQuery 作者 john 開(kāi)發(fā)的微型模板引擎 tmpl 是這種方式的典型代表,參見(jiàn): http://ejohn.org/blog/javascript-micro-templating/
由原理實(shí)現(xiàn)可見(jiàn),傳統(tǒng) javascript 模板引擎中留下兩個(gè)待解決的問(wèn)題:
1、性能:模板引擎渲染的時(shí)候依賴 Function 構(gòu)造器實(shí)現(xiàn),F(xiàn)unction 與 eval、setTimeout、setInterval 一樣,提供了使用文本訪問(wèn) javascript 解析引擎的方法,但這樣執(zhí)行 javascript 的性能非常低下。
2、調(diào)試:由于是動(dòng)態(tài)執(zhí)行字符串,若遇到錯(cuò)誤調(diào)試器無(wú)法捕獲錯(cuò)誤源,導(dǎo)致模板 BUG 調(diào)試變得異常痛苦。在沒(méi)有進(jìn)行容錯(cuò)的引擎中,局部模板若因?yàn)閿?shù)據(jù)異常甚至可以導(dǎo)致整個(gè)應(yīng)用崩潰,隨著模板的數(shù)目增加,維護(hù)成本將劇增。
artTemplate 高效的秘密
1、預(yù)編譯
在上述模板引擎實(shí)現(xiàn)原理中,因?yàn)橐獙?duì)模板變量進(jìn)行賦值,所以每次渲染都需要?jiǎng)討B(tài)編譯 javascript 字符串完成變量賦值。而 artTemplate 的編譯賦值過(guò)程卻是在渲染之前完成的,這種方式稱之為“預(yù)編譯”。artTemplate 模板編譯器會(huì)根據(jù)一些簡(jiǎn)單的規(guī)則提取好所有模板變量,聲明在渲染函數(shù)頭部,這個(gè)函數(shù)類似:

這個(gè)自動(dòng)生成的函數(shù)就如同一個(gè)手工編寫(xiě)的 javascript 函數(shù)一樣,同等的執(zhí)行次數(shù)下無(wú)論 CPU 還是內(nèi)存占用都有顯著減少,性能近乎極限。
值得一提的是:artTemplate 很多特性都基于預(yù)編譯實(shí)現(xiàn),如沙箱規(guī)范與自定義語(yǔ)法等。
2、更快的字符串相加方式
很多人誤以為數(shù)組 push 方法拼接字符串會(huì)比 += 快,要知道這僅僅是 IE6-8 的瀏覽器下。實(shí)測(cè)表明現(xiàn)代瀏覽器使用 += 會(huì)比數(shù)組 push 方法快,而在 v8 引擎中,使用 += 方式比數(shù)組拼接快 4.7 倍。所以 artTemplate 根據(jù) javascript 引擎特性采用了兩種不同的字符串拼接方式。
artTemplate 調(diào)試模式原理
前端模板引擎不像后端模板引擎,它是動(dòng)態(tài)解析,所以調(diào)試器無(wú)法定位到錯(cuò)誤行號(hào),而 artTemplate 通過(guò)巧妙的方式讓模板調(diào)試器可以精確定位到引發(fā)渲染錯(cuò)誤的模板語(yǔ)句,例如:

artTemplate 支持兩種類型的錯(cuò)誤捕獲,一是渲染錯(cuò)誤(Render Error)與編譯錯(cuò)誤(Syntax Error)。
1、渲染錯(cuò)誤
渲染錯(cuò)誤一般是因?yàn)槟0鍞?shù)據(jù)錯(cuò)誤或者變量錯(cuò)誤產(chǎn)生的,渲染的時(shí)候只有遇到錯(cuò)誤才會(huì)進(jìn)入調(diào)試模式重新編譯模板,而不會(huì)影響正常的模板執(zhí)行效率。模板編譯器根據(jù)模板換行符記錄行號(hào),編譯后的函數(shù)類似:

當(dāng)執(zhí)行過(guò)程遇到錯(cuò)誤,立馬拋出異常模板對(duì)應(yīng)的行號(hào),模板調(diào)試器再根據(jù)行號(hào)反查模板對(duì)應(yīng)的語(yǔ)句并打印到控制臺(tái)。
2、編譯錯(cuò)誤
編譯錯(cuò)誤一般是模板語(yǔ)法錯(cuò)誤,如不合格的套嵌、未知語(yǔ)法等。由于 artTemplate 沒(méi)有進(jìn)行完整的詞法分析,故無(wú)法確定錯(cuò)誤源所在的位置,只能對(duì)錯(cuò)誤信息與源碼進(jìn)行原文輸出,供開(kāi)發(fā)者判斷。
相關(guān)文章
javascript實(shí)現(xiàn)倒計(jì)時(shí)提示框
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)倒計(jì)時(shí)提示框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
深入了解JavaScript中的二進(jìn)制操作及位掩碼應(yīng)用
在JavaScript中,二進(jìn)制操作可以說(shuō)是一項(xiàng)非常強(qiáng)大和有用的技能,尤其是在處理數(shù)據(jù)和位掩碼時(shí),它們是不可或缺的,本文將介紹JavaScript中的二進(jìn)制操作,包括什么是二進(jìn)制以及如何在JavaScript中進(jìn)行二進(jìn)制操作2023-06-06
JS添加刪除一組文本框并對(duì)輸入信息加以驗(yàn)證判斷其正確性
需要添加幾組數(shù)據(jù)到數(shù)據(jù)庫(kù),但是具體幾組數(shù)據(jù)不確定,有客戶來(lái)填寫(xiě),所以,這里我用JS進(jìn)行添加刪除子方案,并要對(duì)方案輸入的正確性加以判斷,感興趣的朋友可以了解下2013-04-04
使用bootstrap3開(kāi)發(fā)響應(yīng)式網(wǎng)站
這篇文章主要為大家詳細(xì)介紹了使用bootstrap3開(kāi)發(fā)響應(yīng)式網(wǎng)站的具體代碼,感興趣的小伙伴們可以參考一下2016-05-05
Jquery顏色選擇器ColorPicker實(shí)現(xiàn)代碼
這里我要分享一個(gè)自己修改的顏色選擇器,有需要的朋友參考下2012-11-11
JavaScript html5 canvas繪制時(shí)鐘效果(二)
這篇文章主要介紹了JavaScript html5繪制時(shí)鐘效果的相關(guān)資料,使用HTML5的canvas標(biāo)簽和Javascript腳本,模擬顯示了一個(gè)時(shí)鐘,感興趣的小伙伴們可以參考一下2016-03-03
js中encode、decode的應(yīng)用說(shuō)明
這里簡(jiǎn)單介紹下js中的encode、decode的字符2012-10-10
微信小程序嵌入H5頁(yè)面(webview)的基本用法和父子傳參數(shù)詳細(xì)說(shuō)明
微信小程序中嵌入H5頁(yè)面通常指的是在小程序中使用Web-view組件來(lái)加載外部的網(wǎng)頁(yè),下面這篇文章主要給大家介紹了關(guān)于微信小程序嵌入H5頁(yè)面(webview)的基本用法和父子傳參數(shù)的相關(guān)資料,需要的朋友可以參考下2024-08-08

