對於一個應用來講界面的重要性無言而喻,而Web應用的界面是使用Html+Css以及Javascript實現的,ASP.NET MVC是一個用來構建Web應用的框架,它的界面也是Html實現的,對於一些開發團隊來講,通常Web項目會存在專業的UI前端工程師和後端工程師,前端工程師可能只懂設計和Html,可是對於如何將設計好的Html應用到ASP.NET可能就須要ASP.NET工程師的幫助。
本文將介紹如何將已經設計好的Web界面應用到ASP.NET MVC中以及如何對這些資源文件進行管理,先看一下修改後的效果:css
本章的主要內容有:
● 素材選擇
● ASP.NET MVC的界面佈局及界面實現
● 使用BundleConfig進行素材資源管理
○ 使用bundle對素材分類
○ 使用Bundle對資源文件進行優化
○ 在Bundle中使用通配符及文件版本(min版)的選擇
○ 使用CDN
○ Bundle中的緩存
○ Bundle重寫樣式表中資源引用路徑
○ 自定義資源轉變(Transform)
● 小結html
本文選取開源主題Start Bootstrap - Clean Blog爲例進行介紹。
Clean Blog是一個現代風格的響應式主題,基於bootstrap 4.0,下圖爲Clean Blog的運行效果:前端
將Clean Blog下載到本地並導入《My Blog》項目中,該主題中包含了相應的樣式表、圖片、Js、示例頁面等文件:jquery
注:Clean Bolg的GitHub地址:https://github.com/BlackrockDigital/startbootstrap-clean-bloggit
Clean Blog是由Html、Css、Javascript文件組成的一個靜態Web界面,要將其應用到ASP.NET MVC中,只須要對其結構進行分析後一一替換到ASP.NET MVC的View中便可。
因此首先要分析的是Clean Blog以及My Blog應用的頁面佈局,對於Clean Blog來講它分爲三塊,分別是導航、內容以及頁腳:github
一樣的My Blog以前使用的ASP.NET MVC默認模板也是分爲了導航、內容和頁腳:web
對於上面的佈局來講,導航和頁腳部分是不變的,只有中間的內容是變化的,在ASP.NET MVC中提供了佈局頁的機制,專門用來定義頁面佈局,將不變的內容放置在該佈局頁面上,因此要更換界面首先須要的就是定義佈局頁面:
在Views/Shared目錄下添加一個新的佈局頁面,將Clean Blog的Index頁面中的導航以及頁腳代碼複製到新的佈局頁面中,包括css以及js的引用(注:須要修改路徑),頁面內容部分使用@RenderBody()方法代替:bootstrap
同時將_ViewStart.cshtml中指定的佈局文件改成新建立的CleanBlog佈局文件:後端
最後參照Clean Blog內容頁樣式完成相應內容頁面修改便可,下面以「聯繫咱們」頁面爲例:緩存
運行效果(注:沒有實現原主題中的信息提交功能):
經過上面的介紹知道了如何經過佈局頁面來搭建頁面內容,Web頁面除了自己的Html代碼外還少不了css、JavaScript等文件的支持,但這些文件都是相對零散的,在ASP.NET中有一個Bundle機制專門用於管理這些資源文件。
Bundle有捆和包的意思,而在ASP.NET MVC中它實際就是能夠將一組css或JavaScript捆綁起來,捆綁能夠根據資源的一些特性進行歸類,與此同時還添加了一些有用的附加功能,如:文件最小化、資源文件的版本管理、使用CDN加速、資源文件的緩存等等,下面就介紹如何使用bundle來管理新添加到項目中的素材資源。
爲了保證頁面樣式一致,因此在建立佈局文件時添加了全站共用的樣式和腳本,Clean Blog是基於Bootstrap4.0創建的,除此以外還有一些特殊的內容,以下圖所示,它的實例代碼中已經進行過度類:
樣式主要包括Bootstrap的核心樣式、模板中使用的字體以及模板中的自定義樣式,一樣JavaScript除了bootstrap必要的JavaScript外還有自定義的JavaScript。根據這個分類規則,在App_Start/BundleConfig的BundleConfig類型中註冊分類:
樣式分類:
腳本分類:
注:建議bundle的地址以bundles做爲前綴,避免與路由衝突。
完成後在佈局文件中改用Bundle渲染樣式和腳本:
前面經過Bundle對資源進行了分類,當同一類資源下存在多個文件時,頁面只須要一句代碼就能夠所有引入使代碼更清晰,固然Bundle機制在資源分類的同時,更重要的是能夠對資源文件進行優。
這裏的優化有兩個點分別是文件請求的優化和文件大小的優化,前者是將同一類的文件進行合併,合併成一個文件,在請求時只需請求一次便可,後者是將css及JavaScript中不須要的字符刪除、變量名稱簡寫以達到縮減文件尺寸的目的。
使用Bundle管理資源時,在Release模式下將自動進行優化,另外也能夠設置BundleTable.EnableOptimizations爲true進行強制優化,以下圖所示:
運行時將能夠看到以下結果:
1. 請求數量減小:
2.非最小化的js文件被最小化,如clean-blog.js:
注:上面請求中出現字體文件沒法找到的錯誤將在後續內容解釋。
對於一些樣式或腳本組件來講,它自己就可能由多個文件構成,以下圖中的Jquery目錄中就有jquery.js以及jquery.slim.js兩個文件:
在一些複雜的應用中還可能會使用到jQuery的其它組件,這樣資源文件會更多,爲了簡化Bundle對資源的歸類,在使用Bundle註冊分類時,可使用通配符來一次匹配多個文件:
注:Bundle中能識別的通配符有兩種,經常使用的就是「*」,另外還能夠經過「{version}」來匹配文件版本。更多通配符相關內容可參考:https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification#using-the--wildcard-character-to-select-files
直接使用*通配符能夠匹配相應目錄下的全部文件,下圖是運行結果:
從圖中能夠看到,比以前的請求中多了一些js文件,這些文件就是經過通配符匹配到的,但要注意的是這裏沒有獲取包含.min版本的js文件,在相同目錄下clean-blog.js以及jquery.js都有被最小化的min版本:
Bundle機制會根據debug/release模式或者BundleTable.EnableOptimizations屬性來判斷是否對資源文件優化,在release模式(web.config中compilation的debug屬性爲true)下或者BundleTable.EnableOptimizations設爲true時會啓用資源優化,這裏的資源優化除了上面提到的多個文件捆綁外,若是文件列表中有min版本文件,那麼就會優先選擇min版本文件。
因爲優化模式下沒法看到具體請求的文件名稱,因此在clean-blog.min.js中添加一條日誌輸出代碼:
而後使用release模式運行程序,將會得到下面結果:
除了看到請求減小之外,還看到日誌中輸出了min版本文件中添加的內容,證實使用release模式運行時Bundle會自動選擇文件最小化的版本。
CDN(內容分發網絡),爲了提升web的響應速度,其中一項主要的優化手段就是將靜態資源放到CDN上,這樣用戶就能夠在離他最近的網絡節點獲取到這些資源,這樣既提升了資源獲取的速度同時也下降了應用服務器的壓力,ASP.NET中的Bundle能夠爲相應的資源配置CDN,而且該配置也是release模式下生效:
使用CDN主要有如下幾個步驟:
● 將bundles的UseCdn屬性設爲true。
● 建立Bundle對象時構造方法中傳入CDN的路徑。
● 設置Bundle對象的CdnFallbackExpression屬性,該屬性用於判斷經過CDN加載的內容是否正確加載,若是沒有那麼會加載Include中的內容。
運行效果:
將bundles.CdnFallbackExpression的屬性設置爲window.jQuery會生成一個判斷window.jQuery對象是否存在,若是不存在則獲取服務器資源的代碼:
經過修改CDN資源路徑,模擬CDN沒法訪問狀況,它會自動加載可用的資源:
CDN可用資源參考:http://www.bootcdn.cn/
在Release或資源優化模式下,Bundle爲其管理的資源提供了緩存機制,在第一次訪問Bundle管理的資源時,Bundle會爲每一組資源生成一個惟一標識,而後將該資源默認緩存一年:
當資源發生改變時惟一標識會發生變化,那麼原來緩存的內容就自動失效了。
在前面的介紹的過程當中release模式下一直有一個錯誤,就是沒法找到字體文件,這是由於在編寫樣式時會引入一些字體或者圖片等外部資源,而這些資源通常是用相對路徑進行引用的,可是當ASP.NET中使用Bundle來對樣式資源進行捆綁時,該資源的url地址就發生改變了,致使使用該地址組合的引用資源的地址不正確,從而致使了資源沒法加載:
爲了解決這一問題,Bundle提供了一個重寫樣式引用相對路徑的解決方案,在將樣式表註冊到Bundle中時,能夠爲相應的樣式文件添加一個CssRewriteUrlTransform對象,它用於Css文件優化時對其引用的Url進行重寫:
添加以上代碼後,運行程序將解決字體沒法找到的問題:
資源轉變是Bundle機制在優化資源時提供的一個可拓展接口,如上面介紹的css Url重寫就是資源轉變的拓展,Bundle中實現資源轉變須要實現如下接口:
接口中的參數分別表明獲取到文件的虛擬路徑和文件的內容。
下面建立一個在css中插入自定義內容的資源轉換器,來介紹如何實現資源轉變的自定義拓展:
實現IItemTransform接口,在樣式文件中追加".test {color: red;}"樣式:
將該轉換器經過Include方法應用到對應文件上:
運行結果顯示相應內容已經被添加到最終的樣式文件中:
注:IItemTransform接口是在資源優化前調用的,因此本例添加內容包含的空格和分號最終都被優化刪除了,因此在使用IItemTransform進行拓展時須要注意資源優化問題。
另外在Bundle中還有另一個拓展接口IBundleTransform,它定義了一個用於轉換Bundle相應文件的方法:
實現Process接口,在響應的內容上添加註釋「hello selim」:
BundleTransform須要在Bundle的Transforms屬性上添加:
運行結果:
相對與ItemTransform來講BundleTransform處理後的內容不會再進行優化,在文檔https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification#less-coffeescript-scss-sass-bundling中還經過BundleTransform實現了less等文件動態編譯的功能,有興趣可參考該文檔。
本章主要介紹瞭如何將現有的Web樣式應用到ASP.NET MVC中,並着重介紹了ASP.NET MVC中對靜態資源管理的Bundle機制。Bundle機制除了能夠對資源文件進行歸類外還提供了資源文件優化、CDN、緩存等高級功能。合理的利用Bundle可讓項目代碼更清晰,同時也能夠提升應用的性能。
參考:
https://github.com/BlackrockDigital/startbootstrap-clean-blog
https://html.com/attributes/
https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification
https://www.codeproject.com/articles/842961/introducing-dynamic-bundles-for-asp-net-mvc
https://stackoverflow.com/questions/11355935/mvc4-stylebundle-not-resolving-images#
http://www.bootcdn.cn/
http://www.tutorialsteacher.com/mvc/scriptbundle-mvc
https://www.codeproject.com/Articles/728146/ASP-NET-MVC-bundles-internals
https://blogs.msdn.microsoft.com/rickandy/2011/05/21/using-cdns-and-expires-to-improve-web-site-performance/