對于一個應用來說界面的重要性無言而喻,而Web應用的界面是使用Html+Css以及Javascript實作的,ASP.NET MVC是一個用來建構Web應用的架構,它的界面也是Html實作的,對于一些開發團隊來說,一般Web項目會存在專業的UI前端工程師和後端工程師,前端工程師可能隻懂設計和Html,但是對于如何将設計好的Html應用到ASP.NET可能就需要ASP.NET工程師的幫助。
本文将介紹如何将已經設計好的Web界面應用到ASP.NET MVC中以及如何對這些資源檔案進行管理,先看一下修改後的效果:

本章的主要内容有:
● 素材選擇
● ASP.NET MVC的界面布局及界面實作
● 使用BundleConfig進行素材資源管理
○ 使用bundle對素材分類
○ 使用Bundle對資源檔案進行優化
○ 在Bundle中使用通配符及檔案版本(min版)的選擇
○ 使用CDN
○ Bundle中的緩存
○ Bundle重寫樣式表中資源引用路徑
○ 自定義資源轉變(Transform)
● 小結
本文選取開源主題Start Bootstrap - Clean Blog為例進行介紹。
Clean Blog是一個現代風格的響應式主題,基于bootstrap 4.0,下圖為Clean Blog的運作效果:
将Clean Blog下載下傳到本地并導入《My Blog》項目中,該主題中包含了相應的樣式表、圖檔、Js、示例頁面等檔案:
注:Clean Bolg的GitHub位址:https://github.com/BlackrockDigital/startbootstrap-clean-blog
Clean Blog是由Html、Css、Javascript檔案組成的一個靜态Web界面,要将其應用到ASP.NET MVC中,隻需要對其結構進行分析後一一替換到ASP.NET MVC的View中即可。
是以首先要分析的是Clean Blog以及My Blog應用的頁面布局,對于Clean Blog來說它分為三塊,分别是導航、内容以及頁腳:
同樣的My Blog之前使用的ASP.NET MVC預設模闆也是分為了導航、内容和頁腳:
對于上面的布局來說,導航和頁腳部分是不變的,隻有中間的内容是變化的,在ASP.NET MVC中提供了布局頁的機制,專門用來定義頁面布局,将不變的内容放置在該布局頁面上,是以要更換界面首先需要的就是定義布局頁面:
在Views/Shared目錄下添加一個新的布局頁面,将Clean Blog的Index頁面中的導航以及頁腳代碼複制到新的布局頁面中,包括css以及js的引用(注:需要修改路徑),頁面内容部分使用@RenderBody()方法代替:
同時将_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/
本文連結:http://www.cnblogs.com/selimsong/p/8589175.html
ASP.NET沒有魔法——目錄
作者:7m魚
出處:http://www.cnblogs.com/selimsong/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。