14.3 ASP.NET網(wǎng)站的預編譯和編譯
ASP.NET在將整個站點提供給用戶之前,可以預編譯該站點。這為用戶提供了更快的響應時間,提供了在向用戶顯示站點之前標識編譯時bug的方法,提供了避免部署源代碼的方法,并提供了有效的將站點部署到成品服務器的方法??梢栽诰W(wǎng)站的當前位置預編譯網(wǎng)站,也可以預編譯網(wǎng)站并將其部署到其他計算機。
在正式部署網(wǎng)站前,ASP.NET還要將代碼編譯成一個或多個程序集。
14.3.1 ASP.NET網(wǎng)站的預編譯
默認情況下,在用戶首次請求資源(如網(wǎng)站的一個頁)時,將動態(tài)編譯ASP.NET網(wǎng)頁和代碼文件。第一次編譯頁和代碼文件之后,會緩存編譯后的資源,這樣將大大提高隨后對同一頁提出的請求的效率。
ASP.NET還可以預編譯整個站點,然后再提供給用戶使用。這樣做有很多好處:
— 可以加快用戶的響應時間,因為頁和代碼文件在第一次被請求時無須編譯。這對于經(jīng)常更新的大型站點尤其有用。
— 可以在用戶看到站點之前識別編譯時bug。
— 可以創(chuàng)建站點的已編譯版本,并將該版本部署到成品服務器,而無須使用源代碼。
ASP.NET提供了兩個預編譯站點選項。
(1)預編譯現(xiàn)有站點。
如果希望提高現(xiàn)有站點的性能并對站點執(zhí)行錯誤檢查,那么此選項十分有用??梢酝ㄟ^預編譯網(wǎng)站來稍稍提高網(wǎng)站的性能。對于經(jīng)常更改和補充ASP.NET網(wǎng)頁及代碼文件的站點則更是如此。在這種內(nèi)容不固定的網(wǎng)站中,動態(tài)編譯新增頁和更改頁所需的額外時間會影響用戶對站點質(zhì)量的感受。在執(zhí)行就地預編譯時,將編譯所有的ASP.NET文件類型(HTML文件、圖形和其他非ASP.NET靜態(tài)文件將保持原狀)。預編譯過程的邏輯與ASP.NET進行動態(tài)編譯時所用的邏輯相同,這說明了文件之間的依賴關系。在預編譯過程中,編譯器將為所有可執(zhí)行輸出創(chuàng)建程序集,并將程序集放在%SystemRoot%\Microsoft. NET\Framework\version\Temporary ASP.NET Files文件夾下的特殊文件夾中。隨后,ASP.NET將通過此文件夾中的程序集來完成頁請求。如果再次預編譯站點,那么將只編譯新文件或更改過的文件(或那些與新文件或更改過的文件具有依賴關系的文件)。編譯器的這一優(yōu)化,用戶即使是在細微的更新之后,也可以編譯站點。
(2)針對部署預編譯站點。
此選項將創(chuàng)建一個特殊的輸出,可以將該輸出部署到成品服務器。預編譯站點的另一個用處是生成可部署到成品服務器的站點的可執(zhí)行版本。針對部署進行預編譯將以布局形式創(chuàng)建輸出,其中包含程序集、配置信息、有關站點文件夾的信息,以及靜態(tài)文件(如 HTML 文件和圖形)。
編譯站點之后,可以使用 Windows XCopy 命令、FTP、Windows 安裝等工具將布局部署到成品服務器。布局在部署完之后將作為站點運行,且 ASP.NET 將通過布局中的程序集來完成頁請求。
針對部署預編譯又可以按照以下兩種方式來針對部署進行預編譯:僅針對部署進行預編譯,或者針對部署和更新進行預編譯。
— 僅針對部署進行預編譯。
當僅針對部署進行預編譯時,編譯器實質(zhì)上將基于正常情況下在運行時編譯的所有ASP.NET源文件來生成程序集。其中包括頁中的程序代碼、.cs和.vb類文件,以及其他代碼文件和資源文件。編譯器將從輸出中移除所有源代碼和標記。在生成的布局中,為每個.aspx文件生成編譯后的文件(擴展名為.compiled),該文件包含指向該頁相應程序集的指針。
要更改網(wǎng)站(包括頁的布局),必須更改原始文件,重新編譯站點并重新部署布局。唯一的例外是站點配置,可以更改成品服務器上的 Web.config 文件,而無須重新編譯站點。此選項不僅為頁提供了最大程度的保護,還提供了最佳啟動性能。
— 針對部署和更新進行預編譯。
當針對部署和更新進行預編譯時,編譯器將基于所有源代碼(單文件頁中的頁代碼除外)及正常情況下用來生成程序集的其他文件(如資源文件)來生成程序集。編譯器將.aspx文件轉(zhuǎn)換成使用編譯后的代碼隱藏模型的單個文件,并將它們復制到布局中。
使用此選項,可以在編譯站點中的ASP.NET網(wǎng)頁之后對它們進行有限的更改。例如,可以更改控件的排列、頁的顏色、字體和其他外觀元素。還可以添加不需要事件處理程序或其他代碼的控件。
預編譯過程對ASP.NET Web應用程序中各種類型的文件執(zhí)行操作。文件的處理方式各不相同,這取決于應用程序預編譯只是用于部署還是用于部署和更新。表14-16描述了不同的文件類型,以及應用程序預編譯只是用于部署時對這些文件類型所執(zhí)行的操作。
表14-16 部署時不同文件類型對應的預編譯操作和輸出位置
文件類型
預編譯操作
輸出位置
.aspx、ascx、.master
生成程序集和一個指向該程序集的.compiled文件。原始文件保留在原位置,作為完成請求的占位符
程序集和.compiled文件寫入Bin文件夾中。頁(去除內(nèi)容的.aspx文件)保留在其原始位置
.asmx、.ashx
生成程序集。原始文件保留在原位置,作為完成請求的占位符
Bin文件夾
App_Code文件夾中的文件
生成一個或多個程序集(取決于Web.config設置)
Bin文件夾
未包含在App_Code文件夾中的.cs或.vb文件
與依賴于這些文件的頁或資源一起編譯
Bin文件夾
Bin文件夾中的現(xiàn)有.dll文件
按原樣復制文件
Bin文件夾
資源(.resx)文件
對于App_LocalResources或App_GlobalResources文件夾中找到的.resx文件,生成一個或多個程序集以及一個區(qū)域性結構
Bin文件夾
App_Themes文件夾及子文件夾中的文件
在目標位置生成程序集并生成指向這些程序集的.compiled文件
Bin文件夾
靜態(tài)文件(.htm、.html、圖形文件等)
按原樣復制文件
與源中結構相同
瀏覽器定義文件
按原樣復制文件
App_Browsers
依賴項目
將依賴項目的輸出生成到程序集中
Bin文件夾
Web.config文件
按原樣復制文件
與源中結構相同
Global.asax文件
編譯到程序集中
Bin文件夾
表14-17描述了不同的文件類型,以及應用程序預編譯用于部署和更新時對這些文件類型所執(zhí)行的操作。
表14-17 部署和更新時不同文件類型對應的預編譯操作和輸出位置
文件類型
預編譯操作
輸出位置
.aspx、ascx、.master
對于具有代碼隱藏類文件的文件,生成程序集和一個指向該程序集的.compiled文件。將這些文件的單文件版本原封不動地復制到目標位置
程序集和.compiled文件寫入Bin文件夾中
.asmx、.ashx
按原樣復制文件,但不編譯
與源中結構相同
App_Code文件夾中的文件
生成一個或多個程序集(取決于Web.config設置)
Bin文件夾
未包含在App_Code文件夾中的.cs或.vb文件
與依賴于這些文件的頁或資源一起編譯
Bin文件夾
續(xù)表
文件類型
預編譯操作
輸出位置
Bin文件夾中的現(xiàn)有.dll文件
按原樣復制文件
Bin文件夾
資源(.resx)文件
對于App_GlobalResources文件夾中的.resx文件,生成一個或多個程序集,以及一個區(qū)域性結構
對于App_LocalResources文件夾中的.resx文件,將它們按原樣復制到輸出位置的App_LocalResources文件夾中
程序集放置在Bin文件夾中
App_Themes文件夾及子文件夾中的文件
按原樣復制文件
與源中結構相同
靜態(tài)文件(.htm、.html、圖形文件等)
按原樣復制文件
與源中結構相同
瀏覽器定義文件
按原樣復制文件
App_Browsers
依賴項目
將依賴項目的輸出生成到程序集中
Bin文件夾
Web.config文件
文件被復制
與源中結構相同
Global.asax文件
編譯到程序集中
Bin文件夾
在部署預編譯的網(wǎng)站之后,可以對站點中的文件進行一定更改。表14-18描述了不同類型的更改所造成的影響。
表14-18 對文件進行更改后對網(wǎng)站的影響
文件類型
允許的更改(僅部署)
允許的更改(部署和更新)
靜態(tài)文件(.htm、.html、圖形文件等)
可以更改、移除或添加靜態(tài)文件。如果ASP.NET網(wǎng)頁引用的頁或頁元素已被更改或移除,可能會發(fā)生錯誤
可以更改、移除或添加靜態(tài)文件。如果ASP.NET網(wǎng)頁引用的頁或頁元素已被更改或移除,可能會發(fā)生錯誤
.aspx文件
不允許更改現(xiàn)有的頁。不允許添加新的.aspx文件
可以更改 .aspx 文件的布局和添加不需要代碼的元素,例如,HTML元素和不帶有事件處理程序的ASP.NET服務器控件。還可以添加新的.aspx文件,該文件通常在首次請求時進行編譯
.skin文件
忽略更改和新增的.skin文件
允許更改和新增的.skin文件
Web.config文件
允許更改,這些更改將影響.aspx文件的編譯。忽略調(diào)試或批處理編譯選項。
不允許更改配置文件屬性或提供程序元素
如果所做的更改不會影響站點或頁的編譯(包括編譯器設置、信任級別和全球化),則允許進行更改。忽略影響編譯或使已編譯頁中的行為發(fā)生變化的更改,否則在一些實例中可能會生成錯誤。允許其他更改
瀏覽器定義
允許更改和新增文件
允許更改和新增文件
從資源(.resx)文件編譯的程序集
可以為全局和局部資源添加新的資源程序集文件
可以為全局和局部資源添加新的資源程序集文件
對于ASP.NET Web應用程序中的可執(zhí)行文件,編譯器程序集,以及文件擴展名為.compiled的文件。程序集名稱由編譯器生成。.compiled文件不包含可執(zhí)行代碼。它只包含ASP.NET查找相應的程序集所需的信息。
在部署預編譯的應用程序之后,ASP.NET使用Bin文件夾中的程序集來處理請求。預編譯輸出包含.aspx或.asmx文件作為頁占位符。占位符文件不包含任何代碼。使用它們只是為了提供一種針對特定頁請求調(diào)用ASP.NET的方式,以便可以設置文件權限來限制對頁的訪問。
14.3.2 ASP.NET網(wǎng)站的編譯
為了使用應用程序代碼為用戶提出的請求提供服務,ASP.NET必須首先將代碼編譯成一個或多個程序集。程序集是文件擴展名為.dll的文件??梢圆捎枚喾N不同的語言來編寫ASP.NET代碼,如Visual Basic、C#、J#和其他語言。當在編譯代碼時,會將代碼翻譯成一種名為Microsoft中間語言(MSIL)的與語言和CPU無關的表示形式。運行時,MSIL將運行在.NET Framework的上下文中,.NET Framework會將MSIL翻譯成CPU特定的指令,以便計算機上的處理器運行應用程序。
編譯應用程序代碼具有許多好處,其中包括:
— 性能。編譯后的代碼的執(zhí)行速度要比諸如ECMAScript或VBScript的腳本語言快得多,因為它是一種更接近于機器代碼的表示形式,并且不需要進行其他分析。
— 安全性。編譯后的代碼要比非編譯的源代碼更難進行反向工程處理,因為編譯后的代碼缺乏高級別語言所具有的可讀性和抽象性。此外,模糊處理工具增強了編譯后的代碼對抗反向工程處理的能力。
— 穩(wěn)定性。在編譯時檢查代碼是否有語法錯誤、類型安全問題,以及其他問題。通過在生成時捕獲這些錯誤,可以消除代碼中的許多錯誤。
— 互操作性。由于MSIL代碼支持任何.NET語言,因此可以在代碼中使用最初用其他語言編寫的程序集。例如,如果正在用C#編寫ASP.NET網(wǎng)頁,可以添加對使用Visual Basic編寫的.dll文件的引用。
ASP.NET編譯結構包括許多功能,其中包括:
— 多語言支持;
— 自動編譯;
— 靈活部署;
— 可擴展生成系統(tǒng)。
(1)多語言支持。
在ASP.NET 2.0中,可以在同一個應用程序中使用不同的語言(如Visual Basic和C#),這是因為ASP.NET將為每一種語言分別創(chuàng)建一個程序集。對于存儲在App_Code文件夾中的代碼,可以為每種語言指定一個子文件夾。
(2)自動編譯。
當用戶首次請求網(wǎng)站的資源時,ASP.NET將自動編譯應用程序代碼和任何依賴資源。通常,ASP.NET為每個應用程序目錄(如App_Code)創(chuàng)建一個程序集,并為主目錄創(chuàng)建一個程序集(如果一個目錄中的文件是用不同編程語言編寫的,將為每種語言分別創(chuàng)建程序集),可以在Web.config文件的Compilation節(jié)指定將哪些目錄編譯成單個程序集。
(3)靈活部署。
因為ASP.NET在首次用戶請求時編譯網(wǎng)站,所以只需要將應用程序源代碼復制到成品Web服務器上即可。不過,ASP.NET還提供了預編譯選項,通過這些選項,可以在部署網(wǎng)站之前先進行編譯,或者在部署網(wǎng)站之后、用戶請求該網(wǎng)站之前進行編譯。預編譯有若干優(yōu)點。由于ASP.NET編譯網(wǎng)站時不存在延遲時間,因而預編譯可以改進首次請求時網(wǎng)站的性能。預編譯還能幫用戶找到不然只有當用戶請求頁時才能找到的錯誤。最后,如果在部署網(wǎng)站之前預編譯網(wǎng)站,則可以部署程序集,而不必部署源代碼。
可以使用ASP.NET編譯器工具(ASPNET_Compiler.exe)預編譯網(wǎng)站。該工具提供下列預編譯選項:
— 就地編譯。此選項執(zhí)行與動態(tài)編譯期間發(fā)生的相同編譯過程。可以使用此選項編譯已經(jīng)部署到成品服務器的網(wǎng)站。
— 不可更新完全預編譯??梢允褂么诉x項來編譯應用程序,然后將編譯后的輸出復制到成品服務器。所有應用程序代碼、標記和用戶界面代碼都將編譯為程序集。占位符文件(如.aspx頁)仍存在,因此可以執(zhí)行某些文件特定的任務(如設置權限),但文件中不包含可更新的代碼。為了更新任何頁或任何代碼,必須再次預編譯并再次部署網(wǎng)站。
— 可更新的預編譯。該選項類似于“不可更新完全預編譯”,不同之處在于用戶界面元素(如.aspx頁和.ascx控件)保留其所有標記、用戶界面代碼和內(nèi)聯(lián)代碼(如果有的話)??梢栽诓渴鹬蟾挛募械拇a;ASP.NET將檢測對文件所做的這些更改并重新進行編譯。請注意,預編譯期間代碼隱藏文件(.vb或.cs文件)中的代碼都將內(nèi)置到程序集中,因此如果不重新執(zhí)行預編譯和部署步驟,將無法更改這些代碼。
(4)可擴展生成系統(tǒng)。
ASP.NET使用BuildProvider類來生成項,如.aspx頁、.ascx文件和全局資源。可以通過創(chuàng)建從BuildProvider類繼承的類來擴展和自定義ASP.NET生成系統(tǒng),以編譯自定義資源。例如,可以添加新的文件類型,然后編寫生成該特定類型的BuildProvider。