摘要:原作者唐斌騰訊什么原名是一個簡單易用的前端模板預(yù)編譯工具。本文作者為來自騰訊團(tuán)隊的唐斌,他在本文中為我們分析了傳統(tǒng)前端模板內(nèi)嵌的弊端,如開發(fā)調(diào)試效率低下自動化構(gòu)建復(fù)雜度比較高等特點,并針對目前現(xiàn)狀給出了較好的解決方案。
原作者: 唐斌(騰訊)|
TmodJS什么TmodJS(原名atc)是一個簡單易用的前端模板預(yù)編譯工具。它通過預(yù)編譯技術(shù)讓前端模板突破瀏覽器限制,實現(xiàn)后端模板一樣的同步“文件”加載能力。它采用目錄來組織維護(hù)前端模板,從而讓前端模板實現(xiàn)工程化管理,最終保證前端模板在復(fù)雜單頁 Web 應(yīng)用下的可維護(hù)性。更多內(nèi)容,可訪問:http://code.csdn.net/news/282...。
本文作者為來自騰訊 TmodJS 團(tuán)隊的唐斌,他在本文中為我們分析了傳統(tǒng)前端模板內(nèi)嵌的弊端,如開發(fā)調(diào)試效率低下、自動化構(gòu)建復(fù)雜度比較高等特點,并針對目前現(xiàn)狀給出了較好的解決方案。下面為作者原文,可供參考。
前端模板早期,開發(fā)人員都是直接在 JS 文件中采用最原始的方式直接拼接 HTML 字符串:
var html = ""; for (var i = 0, users = data.users; i < users.length; i ++) { html += "
這種方式剛開始在一兩個簡單的頁面中還是比較靈活的,但弊端也十分明顯:UI 與邏輯代碼混雜在一起,閱讀起來會非常吃力。一旦隨著業(yè)務(wù)復(fù)雜起來,或者多人維護(hù)的情況下,幾乎會失控。
受 jQuery 作者的 tmpl 模板引擎影響,從 09 年開始到現(xiàn)在,前端模板引擎出現(xiàn)了百花齊放的局面,涌現(xiàn)出一大批行色各異的引擎,幾乎每個前端工程中都使用了模板引擎。一條前端模板類似這樣:
它使用一個特殊的 標(biāo)簽來存放模板(由于瀏覽器不支持這種類型的聲明,它存放的代碼不會當(dāng)作 JS 運行,代碼也不會被顯示出來)。使用模板引擎渲染模板的示例:
var html = tmpl("user_tmpl", data); document.getElementById("content").innerHTML = html;在線示例
http://aui.github.io/artTempl...
通過前端模板引擎將 UI 分離后,模板的書寫與修改就變得簡單多了,也提升了可維護(hù)性。但是,隨著這種方式規(guī)模化后其弊端也隨之而來。
模板內(nèi)嵌的弊端模板內(nèi)嵌,主要存在 3 個方面的問題,主要包括:
開發(fā)調(diào)試效率低
每次修改前端模板需要改動頁面的代碼,如果不是純靜態(tài)頁面,無法使用類似 fiddler 的工具將頁面映射到本地進(jìn)行開發(fā),開發(fā)調(diào)試依賴只能服務(wù)端環(huán)境,效率低下。
自動化構(gòu)建
在現(xiàn)代 Web 前端工程體系中,幾乎每一個環(huán)節(jié)都擁有相應(yīng)的優(yōu)化工具,這些幾乎都被 Grunt 這個自動構(gòu)建工具連接起來。但是前端模板若內(nèi)嵌到頁面中,復(fù)雜度會比較高,現(xiàn)有工具因為受限難以進(jìn)行自動優(yōu)化。
模塊化
前端模板集中在一個文件中這必然會引起多人協(xié)作的問題,隨著項目復(fù)雜度增加,按文件模塊化迫在眉睫。
現(xiàn)有的模板外置解決方案與優(yōu)劣解析目前越來越多的項目已經(jīng)將模板從頁面中遷移出來,主要有兩種方式:
Ajax 拉取方案
通過 Ajax 加載遠(yuǎn)程模板,然后再使用模板引擎解析。這種方式的好處就是模板可以按文件存放,書寫起來也是十分便利,但弊端相當(dāng)明顯:由于瀏覽器同源策略限制的,導(dǎo)致模板無法部署到 CDN 網(wǎng)絡(luò)中。
在 JS 文件中存放模板
為避免上述加載模板方案無法跨域的致命缺陷,模板存放在 JS 文件中又成了最佳實踐方式,但是這種情況下需要對回車符進(jìn)行轉(zhuǎn)義,對書寫不友好,嚴(yán)重影響開發(fā)效率。例如:
var user_tmpl = "{{each users as value}}
或者:
var user_tmpl = "{{each users as value}}" + "
現(xiàn)有模板組織方案優(yōu)劣,如下表對比:
組織方式 | 開發(fā)效率 | 優(yōu)化空間 |本地調(diào)試 | 代碼復(fù)用 | 團(tuán)隊協(xié)作
內(nèi)嵌業(yè)務(wù)頁中 | ? | ? | ? | ? | ?
Ajax 遠(yuǎn)程加載| ? | ? | ? | ? | ?
嵌入 js 文件 | ? | ? | ? | ? | ?
總結(jié):
?方便優(yōu)化的模式不利于開發(fā);
?利于開發(fā)的模式不利于優(yōu)化。
看下服務(wù)端模板是如何做的:
模板按文件與目錄組織模板
template("tpl/home/main", data)
模板使用 include 語句完成復(fù)用
{{include "../public/header"}}
這一切看起來很美,前端是否也可以采用這樣的模式?但是現(xiàn)實告訴我們,這是一個艱巨的任務(wù)。
現(xiàn)實難題瀏覽器對文本加載會有跨域限制
瀏覽器同步加載會引起界面卡頓
加載大量的模板文件會帶來 http 資源消耗問題
解決方案為了實現(xiàn)上述“理想模式”,我們推出了 TmodJS——模板預(yù)編譯器。
TmodJS 采用三種方案來解決難題:
本地構(gòu)建
模板編寫完成后,通過一個本地工具將模板編譯成瀏覽器可執(zhí)行的代碼——JS,這樣就可以用腳本的方式來加載模板,不必受瀏覽器的同源策略限制,模板可以部署到任意 CDN,而無需處理跨域問題。
工具內(nèi)部采用模板引擎—— artTemplate完成模板編譯,輸出 JS 文件。artTemplate 也是來自騰訊的開源項目,它支持預(yù)編譯,編譯后的代碼可以無需引擎運行。
種子文件
為了實現(xiàn) template(path, data) 這種同步接口,TmodJS 會不斷的更新一個名為 template.js 的種子文件,這個文件合并了公用方法與編譯后的模板,項目只需要引用這個文件就可以按路徑同步的方式調(diào)用模板。例如:
var tpl = template("home/index"); var html = tpl(data); document.getElementById("content").innerHTML = html;
模板目錄
為了讓團(tuán)隊成員、自動化工具能更好的管理模板,前端模板不再內(nèi)嵌到頁面中,而是使用專門的目錄進(jìn)行組織維護(hù);使用路徑作為模板的 ID,這樣與源文件保持對應(yīng)關(guān)系——這樣好處就是極大的增加了可維護(hù)性。例如:頁面頭部底部的公用模板可以放在tpl/public目錄下,首屏的模板可以放在 tpl/home下面。
模板與工程化TmodJS 采用了自動編譯機(jī)制,一經(jīng)啟動后就無需人工干預(yù),每次模板創(chuàng)建與更新都會自動編譯,直到正式上線都無需對代碼進(jìn)行任何修改。實現(xiàn)文件系統(tǒng)的前端模板只是 TmodJS 最基本的任務(wù),它在背后還做了這些優(yōu)化:
模板壓縮與合并
TmodJS 編譯之前會壓縮掉模板的空白字符,編譯為 JS 后又會進(jìn)行一次壓縮,此時輸出的 JS 甚至?xí)仍寄0甯。ㄗ罡呖蓽p少一半的體積)。
在默認(rèn)設(shè)置下,TmodJS 會將模板目錄所有模板編譯后再進(jìn)行壓縮與合并,輸出后的 template.js 稱之為模板包(內(nèi)部名稱叫 TemplateJS 格式)這種打包的方式非常適合移動端單頁 WebApp,輸出后的模板包可直接可作為開發(fā)階段與線上運行的文件,適合中小型項目。
查看編譯后的模板示例
依賴管理
當(dāng)然,將所有前端模板都打包在一個文件中不一定適合每一個項目,因為很多大型項目需要更細(xì)致的優(yōu)化,將模板編譯為 AMD、CMD、CommonJS 類型的的模塊是一個不錯的選擇,此時模板內(nèi)部的include 語句會編譯成 requier("xxx/xxx") 形式聲明依賴,接入對應(yīng)的 Grunt 插件可自動完成依賴合并。
本地調(diào)試
因為模板已經(jīng)被獨立出來,所以使用 fiddler 將線上模板映射到本地進(jìn)行開發(fā)調(diào)試將十分容易。如果線上模板報錯,開啟 TmodJS 的 debug 模式后可以直接找到出錯的模板路徑以及所在行號,例如:
Template Errorpublic/header Render Error Cannot read property "0" of undefined 5
沙箱與擴(kuò)展
很多開發(fā)者習(xí)慣在模板中訪問頁面中全局定義的函數(shù),如果模板內(nèi)嵌到頁面中問題似乎不大,一旦模板外置后這種隱含的依賴關(guān)系將會導(dǎo)致嚴(yán)重的維護(hù)問題,TmodJS 采用沙箱機(jī)制來解決此問題:限制開發(fā)者訪問外部對象,模板用到的所有變量在閉包中被強(qiáng)制指向模板數(shù)據(jù)。
為了方便擴(kuò)展模板的功能,可指定一個外部 JS 作為公用方法(輔助方法),這個 JS 會被合并到到 template.js 中。
安全過濾
模板的變量輸出默認(rèn)都會被過濾函數(shù)包裹,在運行時進(jìn)行過濾,從而避免模板開發(fā)者因為疏忽導(dǎo)致站點 XSS 漏洞。例如:
模板
{{title}}
編譯代碼
"" + $escape(title) + "
"
與第三方自動化構(gòu)建工具配合
目前 TmodJS 已有 Grunt 與 Gulp 這兩種流行的自動化構(gòu)建工具的插件,未來將支持更多的自動化工具。
前后端模板共享
TmodJS 與 artTemplate 模板引擎使用同樣的模板語法,而 artTemplate 提供了 NodeJS 版本,可以直接讀取 TmodJS 的模板目錄,這意味著可以輕松的做到前后端模板共享,技術(shù)方案自由切換。
經(jīng)過上面的一些優(yōu)化,我們達(dá)到了下面成果:
組織方式 | 開發(fā)效率 | 優(yōu)化空間 | 本地調(diào)試 | 代碼復(fù)用 | 團(tuán)隊協(xié)作
TmodJS | ? | ? | ? | ? | ?
參考網(wǎng)址:http://www.lupaworld.com/arti...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/81132.html
摘要:前端優(yōu)化已經(jīng)是一個被寫爛的題材了。前端模板方案有很多。重繪是瀏覽器性能優(yōu)化的一個重點,特別是針對的優(yōu)化。如果你對前端性能優(yōu)化有自己的想法,歡迎騷擾我。 前端優(yōu)化已經(jīng)是一個被寫爛的題材了。 雖千萬人吾往矣,這里我僅分享我的一些實踐經(jīng)驗。 歡迎一起交流 歡迎關(guān)注我的個人公眾號,不定期更新自己的工作心得。 showImg(https://segmentfault.com/img/remote...
摘要:前端優(yōu)化已經(jīng)是一個被寫爛的題材了。前端模板方案有很多。重繪是瀏覽器性能優(yōu)化的一個重點,特別是針對的優(yōu)化。如果你對前端性能優(yōu)化有自己的想法,歡迎騷擾我。 前端優(yōu)化已經(jīng)是一個被寫爛的題材了。 雖千萬人吾往矣,這里我僅分享我的一些實踐經(jīng)驗。 歡迎一起交流 歡迎關(guān)注我的個人公眾號,不定期更新自己的工作心得。 showImg(https://segmentfault.com/img/remote...
摘要:前端優(yōu)化已經(jīng)是一個被寫爛的題材了。前端模板方案有很多。重繪是瀏覽器性能優(yōu)化的一個重點,特別是針對的優(yōu)化。如果你對前端性能優(yōu)化有自己的想法,歡迎騷擾我。 前端優(yōu)化已經(jīng)是一個被寫爛的題材了。 雖千萬人吾往矣,這里我僅分享我的一些實踐經(jīng)驗。 歡迎一起交流 歡迎關(guān)注我的個人公眾號,不定期更新自己的工作心得。 showImg(https://segmentfault.com/img/remote...
摘要:小程序開發(fā)網(wǎng)站推薦微信小程序支付寶小程序百度智能小程序字符跳動小程序小程序組件化開發(fā)框架開發(fā)小程序框架語法開發(fā)小程序框架,漸進(jìn)式應(yīng)用漸進(jìn)式應(yīng)用教程博客大牛推薦張鑫旭個人網(wǎng)站阮一峰網(wǎng)絡(luò)日志阮一峰教程廖雪峰官方網(wǎng)站呂大豹的博客司徒正美博客編程教 小程序開發(fā)網(wǎng)站推薦 微信小程序:https://developers.weixin.qq.... 支付寶小程序:https://open.al...
閱讀 2651·2021-11-22 15:24
閱讀 1383·2021-11-17 09:38
閱讀 2757·2021-10-09 09:57
閱讀 1209·2019-08-30 15:44
閱讀 2449·2019-08-30 14:00
閱讀 3550·2019-08-30 11:26
閱讀 2942·2019-08-29 16:28
閱讀 757·2019-08-29 13:56