天天看點

Nancy之靜态檔案處理

原文: Nancy之靜态檔案處理

今天我們來談談Nancy中的靜态檔案(JavaScript,CSS等)該如何處理。

在前面的Demo中,我們也已經用到了這一塊的内容,

但并沒有深入了解,隻是停留在使用的層面上。

在進入今天的正題之前,我們先來簡單看看我們熟悉的ASP.NET MVC中是如何管理我們項目中的這些靜态檔案呢?

其實當我們建立一個MVC的項目時,已經生成了一個“模闆”讓我們參考,

這個“模闆”就是App_Start下面的 BundleConfig.cs

1     public class BundleConfig
 2     {
 3         // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
 4         public static void RegisterBundles(BundleCollection bundles)
 5         {
 6             bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
 7                         "~/Scripts/jquery-{version}.js"));
 8             bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
 9                         "~/Scripts/jquery.validate*"));
10             // Use the development version of Modernizr to develop with and learn from. Then, when you're
11             // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
12             bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
13                         "~/Scripts/modernizr-*"));
14             bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
15                       "~/Scripts/bootstrap.js",
16                       "~/Scripts/respond.js"));
17             bundles.Add(new StyleBundle("~/Content/css").Include(
18                       "~/Content/bootstrap.css",
19                       "~/Content/site.css"));
20         }
21     }        

其中的ScriptBundle和StyleBundle分别是用于管理js和css的類,這兩個類都是繼承了Bundle這個類!

它位于System.Web.Optimization程式集,如果想要用這個功能,記得添加引用喔!

那我們要怎麼使用這個呢?

現在假設在根目錄下面有css和js兩個檔案夾,裡面分别存放着Style1.css、Style2.css和js1.js、js2.js

下面就來看看怎麼把它交于Bundle管理

1      bundles.Add(new ScriptBundle("~/bundles/js").Include(
2                     "~/js/js1.js",
3                     "~/js/js2.js"));
4       bundles.Add(new StyleBundle("~/bundles/css").Include(
5                     "~/css/Style1.css",
6                     "~/css/Style2.css"));        

 其中的“~/bundles/js”和"~/bundles/css"是虛拟路徑!

 然後就是在頁面中使用(就是用我們剛才的虛拟路徑)

1  @Styles.Render("~/bundles/css")
2  @Scripts.Render("~/bundles/js")        

是不是很友善呢!更多關于Bundle的内容可以參考

http://www.asp.net/mvc/overview/performance/bundling-and-minification

因為它不是我們今天的主要内容,隻是拿來與Nancy中的靜态檔案處理形成對比,便于我們的了解。

下面就來看看Nancy中的靜态檔案怎麼處理。

為了示範的友善,這裡僅使用css。

先看看具體的使用,然後再簡單分析其内部的實作。

一、建立一個空的asp.net應用程式

在這個應用程式中添加我們需要的引用,這裡可以根據前面介紹的,

按自己喜歡的方式、方法來添加Nancy相關的引用

二、建立Modules

老規矩:Modules檔案夾、HomeModule.cs

1     public class HomeModule : NancyModule
 2     {
 3         public HomeModule()
 4         {
 5             Get["/"] = _ =>
 6             {
 7                   return View["index"];
 8             };
 9 
10             Get["/default"] = _ =>
11             {
12                 return View["default"];
13             };
14 
15             Get["/custom"] = _ =>
16             {
17                 return View["custom"];
18             };
19 
20             Get["/other"] = _ =>
21             {
22                 return View["other"];
23             };
24 
25             Get["/sub"] = _ =>
26             {
27                 return View["sub"];
28             };
29         }
30     }       

三、建立content、assets、other三個檔案夾,以及在assets檔案夾下面建立一個sub檔案夾用于存放樣式表

四、分别添加一些簡單的樣式在這些檔案夾中

content下面的sytle.css内容如下

1 body {background-color:#00ffff;}
2 p {font-size:xx-large; }        

assets和other下面的style.css内容如下

1 body {background-color:#00ffff;}
2 p {font-size:xx-large;color:#ff0000;}        

assets/sub下面 的style.css内容如下

1 body {background-color:#808080;}
2 p {font-size:xx-large;color:#ff0000;}        

五、添加Views

老規矩:Views檔案夾、Home檔案夾

添加 index.html、default.html、custom.html、other.html、sub.html 五個頁面

Nancy之靜态檔案處理
Nancy之靜态檔案處理
1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>index</title>
 5     <meta charset="utf-8" />
 6 </head>
 7 <body>
 8     <a href="/default">page with default convention</a><br />
 9     <a href="/custom">page with custom convention</a><br />
10     <a href="/other">page without custom convention</a><br />
11     <a href="/sub">page sub</a>
12 </body>
13 </html>      

index.html

Nancy之靜态檔案處理
Nancy之靜态檔案處理
1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>default</title>
 5     <meta charset="utf-8" />
 6     <link href="../../content/style.css" rel="stylesheet" />
 7 </head>
 8 <body>
 9    <p>這是引用 /content/sytle.css 的頁面(預設的convention配置)</p>
10 </body>
11 </html>      

default.html

Nancy之靜态檔案處理
Nancy之靜态檔案處理
1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>custom</title>
 5     <meta charset="utf-8" />
 6     <link href="../../assets/style.css" rel="stylesheet" />
 7 </head>
 8 <body>
 9    <p>這是引用 /assets/style.css 的頁面(自定義Convention配置)</p>
10 </body>
11 </html>      

custom.html

Nancy之靜态檔案處理
Nancy之靜态檔案處理
1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>other</title>
 5     <meta charset="utf-8" />
 6     <link href="../../other/style.css" rel="stylesheet" />
 7 </head>
 8 <body>   
 9     <p>這是引用 /other/style.css 的頁面(沒有Convention配置)</p>
10 </body>
11 </html>      

other.html

Nancy之靜态檔案處理
Nancy之靜态檔案處理
1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>sub</title>
 5     <meta charset="utf-8" />
 6     <link href="../../assets/sub/style.css" rel="stylesheet" />
 7 </head>
 8 <body>
 9    <p>這是引用 /assets/sub/style.css 的頁面(自定義Convention配置,子檔案夾測試)</p>
10 </body>
11 </html>      

sub.html

六、在"引導程式"中配置Convention(至關重要的一步)

建立DemoBootstrapper.cs,使其繼承DefaultNancyBootstrapper并且override我們的ConfigureConventions

1     public class DemoBootstrapper : DefaultNancyBootstrapper
2     {
3         protected override void ConfigureConventions(NancyConventions nancyConventions)
4         {
5             base.ConfigureConventions(nancyConventions);
6             nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("assets"));
7         }
8     }        

七、運作結果

Nancy之靜态檔案處理

八、結果分析與探讨

1、default.html 用的樣式是在content下面的,能正常加載樣式!

2、custom.html用的樣式是在assets下面的,能正常加載樣式!

3、other.html用的樣式是在other下面的,不能正常加載樣式!!

4、sub.html用的樣式是在assets/sub下面的,能正常加載樣式!

很明顯,結果有點出乎我們的意料,我們在Convetion的配置中,隻配置了一項!

就是對assets檔案夾進行了處理。其他都沒有手動配置!

但是在content下面的樣式是能夠正常顯示的!!而other下面的是不能正常顯示的!!assets的子檔案夾sub的樣式也正常顯示!!

這個給人貌似不是很合理的感覺。

看看Network的内容會發現other下面的樣式表不是不能正常加載那麼簡單,而是直接給個404!!!

Nancy之靜态檔案處理

那我們就深入的去看看這裡面到底發生了什麼事吧!

fork一份Nancy的源碼,clone到本地,來看看個是以然。(其實上面的例子我就是在源碼上面添加的一個Demo)

首先看看我們今天的主題Conventions下面的東西

Nancy之靜态檔案處理

其中從名字就可以看出跟我們今天的主題靜态檔案,相關的就有7個!!

但這并不是我們的出發點,我們的出發點是下面這個!

1     protected override void ConfigureConventions(NancyConventions nancyConventions)
2         {
3             base.ConfigureConventions(nancyConventions);
4             nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("assets"));
5         }        

Convention的配置指引着我們要先去看看NancyConvetions這個類

在其構造方法中調用了 BuildDefaultConventions 這個方法

1         /// <summary>
2         /// Initializes a new instance of the <see cref="NancyConventions"/> class.
3         /// </summary>
4         public NancyConventions()
5         {
6             this.BuildDefaultConventions();
7         }          

這就很明顯的告訴我們,無論如何,它都會有預設的Conventions!!而且看了裡面的實作

會發現,預設的Convention還不僅僅是一個!!而是包含多個。這裡我們僅探讨關于靜态檔案的。

1         private void BuildDefaultConventions()
 2         {
 3             var defaultConventions =
 4                 AppDomainAssemblyTypeScanner.TypesOf<IConvention>(ScanMode.OnlyNancy);
 5             this.conventions = defaultConventions
 6                 .Union(AppDomainAssemblyTypeScanner.TypesOf<IConvention>(ScanMode.ExcludeNancy))
 7                 .Select(t => (IConvention)Activator.CreateInstance(t));
 8             foreach (var convention in this.conventions)
 9             {
10                 convention.Initialise(this);
11             }
12         }        

現在我們就該去找關于靜态檔案的預設Convetion

發現剛才的7個相關中,有一個DefaultStaticContentsConventions

它實作了IConvention接口(Nancy中基本都是接口化程式設計,很Nice!!)。

其中的初始化方法中

1         public void Initialise(NancyConventions conventions)
2         {
3             conventions.StaticContentsConventions = new List<Func<NancyContext, string, Response>>
4             {
5                 StaticContentConventionBuilder.AddDirectory("Content")
6             };
7         }        

是不是跟我們自定義配置幾乎相差無幾!!我想看到AddDirectory的參數"Content",大家也應該都知道了

為什麼我們的content下面的樣式,沒有配置都能正常加載(我去,它預設都是content,能不正常加載麼。。)

裡面的StaticContentConventionBuilder又是何方神聖呢?

這個是靜态基于目錄的幫助類

Nancy之靜态檔案處理

裡面有兩個主要的方法 AddDirectory和AddFile ,都是傳回Func<NancyContext, string, Response>類型的東東。

看名字都已經知道大概實作了什麼東西,一個基于某個目錄,一個基于某個單獨的檔案。

這裡需要注意一下這兩個方法的參數!

還有一些其他的東西是用于拼接目錄和處理Cache的。

把這幾個重要的類看了一下,是不是對這個靜态檔案的預設配置也清晰了不少呢?

然後對自定義Convetion配置的了解也是類似的,是以這裡就不再累贅了。

從"引導程式"的ConfigureConventions中可以知道,無論我們自定義多少個Convetion,

都是要添加到StaticContentsConventions這個集合中的。

九、簡單總結

ConfigureConventions 與 BundleConfig 都是用于處理靜态檔案的,有相同之處,也有各自的特點。

在項目開發過程中,我們可能會根據習慣把css、javascript這些靜态檔案放在自己喜歡的位置,

但是在Nancy中這個的處理需要十分注意的是,隻要我們沒有将css和javascript檔案放在content中時,就一定要記得在Convention中進行配置!

否則頁面死活不是我們期待的那樣。。。。

是以我個人感覺這塊内容不是很友好,一旦不小心忘了配置,而且發現頁面樣式不對,首先想到的是不是樣式的路徑寫錯了

而不會直接考慮到Nancy的Convention配置這一層面。

為此,提醒各位使用Nancy的朋友,并建議各位:隻要您的項目用到了靜态檔案,請務必要override我們的ConfigureConventions !!

繼續閱讀