這裡的離線處理指標下把一些事件提前做好,不在應用運行時再去做
其實前端的離線處理在一些工具中可以看到,比如說css中的背景圖,某些css工具在打包處理的時候,如果圖片的檔案大小比較小,工具會讀取檔案內容轉成base64直接放到css檔案內,減少http請求。
類似的還有使用字串模板的情況下,提前把字串模板變成js中的函數,避免運行時再去生成對應的函數
接下來聊聊其他的離線處理
模板的離線處理
自訂標籤
現在很多前端框架支援自訂標籤的書寫方式,例如基於vue的element。我們以它的inputnumber為例來看: http://element.eleme.io/#/en-US/component/input-number
<el-input-number v-model="num1" @change="handleChange" :min="1" :max="10"></el-input-number>
一個自訂的el-input-number標籤,最終產生的html是
<div class="el-input-number"> <div class="el-input"> <input type="text" autocomplete="off" class="el-input__inner"> </div> <span class="el-input-number__decrease el-icon-minus is-disabled"></span> <span class="el-input-number__increase el-icon-plus"></span></div>
vue會把自訂標籤替換成最終實現的html內容,這個過程是運行時做的。其實這個過程是可以透過工具線下處理好的,不必在程式執行時再做。
字串模板
字串模板在許多前端頁面中可見,模板引擎也很多,以underscore中的template方法為例:https://github.com/jashkenas/underscore/blob/master/underscore.js #L1579,它裡面在產生函數時,如果沒有variable參數,則會加一個with語句,通常我們是避免掉with的
那麼有沒有什麼辦法是不用傳variable,也不使用with語句呢?這個也是可以線下處理好的。例如模板如下
<%for(var i=0;i<list.length;i++){%> <%=list[i].text%><%}%>
透過工具我們是很容易轉換成下面的內容的
<%for(var i=0;i<obj.list.length;i++){%> <%=obj.list[i].text%> <%}%>
這個就需要藉助acorn類似的工具來處理了,不過肯定是可以做到的。
有的同學說這樣做是錯的,因為with語句不在運行時,根本不知道它裡面的變數從哪裡取值。是的,不過我們完全可以透過約定模板中用到的變數都應該在使用時,明確傳遞
比如window上有一個getUser()方法在去掉with前
var tmpl='<%=getUser()%>'; _.template(tmpl,{});
這時可以正常工作
通過離線工具的處理,去掉with後,模板變成了
var tmpl='<%=obj.getUser()%>'; _.template(tmp,{});
這時候就不行了,不過我們可以約定模板中使用到的都應該在調用時顯式傳遞,從而避免一些潛在的問題出現。
當然,這個模板字串離線處理最好的結果是直接就是一個函數放在那裡了。
css圖片的處理
在我們的專案中,考慮以下檔案結構
|____index.html |____index.css |____index.js
我們通常是把html和css打包時,打包到js檔案中的,因為js檔案可以很方便的模組化,把html ,css依附在js檔案上。這樣js按需載入時,html和css也按需載入了,不需要為它們特殊處理。
假設它們最終打包出來index.js如下
var Magix=require('magix'); var indexHTML='<div class="mp-et5-content">...</div>'; Magix.applyStyle('mp-ec5','.mp-et5-content{color:red}');
更多資訊可參考 https://github.com/thx/magix-combine/issues/15這個包裝工具。
樣式變成一個字串放在js檔案中。
我們看一個事情:在css中使用背景圖時,為了達到最佳實踐,我們希望在支持webp後綴的使用webp,在高清屏下使用2倍圖等 。如果我們用純css實現,要寫很多media query,產生css程式碼。
其实这个事情我们没办法离线处理,但我们可以这样做:书写css仍然是写最基础的背景图,不去考虑webp,2倍图等事情,也不需要写media query之类的。在打包时,把图片这块调用js函数在运行时动态处理
如前面文件结构中的,假设index.css中使用了一个背景图
.title{background-image:url(//cdn/a.png)}
我们打包到js中时,完全可以变成
var Magix=require('magix'); var ataptImg=function(img){ //处理webp 2倍图等 return img } Magix.applyStyle('mp-ec5','.mp-et5-title{background-image:url('+adaptImg('//cdn/a.png')+'}');
这样可以很方便的处理掉这些事情。