領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多Web 應用程式通常嚴重依賴我們稱之為靜態資源的資源,例如 Javascript、CSS 和影像檔案。在 Grails 應用程式中,它們被放入專案的web-app目錄中,然後從 HTML 中引用。例如,
<link rel="stylesheet" href="${resource(dir: 'css', file: 'main.css')}" type="text/css">
將建立指向檔案web-app/css/main.css的連結。所有這些都非常簡單。您甚至可能認為當前的支援足以滿足任何人的需求。您還想做什麼?
這是一個很好的觀點。答案取決於您的應用程式的複雜性,但讓我們從上面的 CSS 連結示例開始。為什麼我們必須鍵入<link rel="..." href=...>透過檢視副檔名,我們知道該資源是一個 CSS 檔案。我們也知道 CSS 檔案應該使用上面的元素連結到 HTML 頁面中。所以我們基本上是在為 Grails 本身應該能夠處理的事情做很多重複的輸入。
“好吧,”我聽到你這樣說,“但我們可以為 CSS 連結新增一個標籤。”確實可以,Grails 2 將包含一個<g:external/>標籤,它能智慧地為資源選擇合適的連結型別。但現在考慮生產環境:將 CSS 和 Javascript 檔案捆綁在一起不是個好主意嗎?壓縮它們呢?(順便說一句,Yahoo 提供了一個名為 ySlow 的工具,可以為你提供有關這類最佳化的提示)。那麼我們如何實現這些最佳化呢?你可能會臨時做,但這樣做會限制你的選擇,因為你無法定義資源之間的關係。我們真正想要的是一種在中心位置宣告資源並指明哪些資源應該一起處理和捆綁的方法。
如果我還沒有說服你存在更好的管理靜態資源的方法,那麼請考慮 Grails 外掛。許多外掛提供自己的靜態資源。事實上,有些外掛提供相同的資源。例如,舊版本的 YUI、Bubbling 和 Grails UI 外掛都包含 YUI 庫。我們真的需要多個完整的 Javascript 庫副本嗎?當然不需要。部分問題可以透過外掛間的依賴來解決,但這本身效果不佳,因為外掛無法宣告其某些資源依賴於另一個外掛中的特定資源。最終,開發人員需要確保所有適當的資源(包括傳遞依賴)都包含在每個頁面中。這可能需要一些反覆試驗,以確保所有必需的資源都連結到頁面中並且順序正確。
幸運的是,我們可以做得更好。進入 Resources 外掛。
只需安裝這一個外掛,你就可以開始在可重用模組中宣告你的靜態資源(Javascript、CSS 等)。然後你可以定義模組之間的依賴關係,這樣 Grails 就確切地知道一個模組需要哪些資源,包括在傳遞依賴中指定的資源。額外的好處是,模組確保資源始終以正確的順序在頁面中宣告,並且沒有重複。透過這樣做,模組大大減輕了靜態資源管理的痛苦。
你可以在應用程式和外掛中宣告資源模組。有幾種方法可以做到這一點,但最常見的方法是向專案新增一個或多個專用工件。對於應用程式來說,這可能是grails-app/conf/ApplicationResources.groovy。另一個例子是 YUI 外掛有grails-app/conf/YuiPluginResources.groovy。這些檔案的基本結構如下
modules = {
core {
resource url: 'js/core.js', disposition: 'head'
resource url: 'js/ui.js'
resource url: 'css/main.css'
resource url: 'css/branding.css'
resource url: 'css/print.css', attrs: [media: 'print']
}
utils {
dependsOn 'jquery'
resource url: 'js/utils.js'
}
forms {
dependsOn 'core', 'utils'
resource url: 'css/forms.css'
resource url: 'js/forms.js'
}
}
"core"、"utils" 和 "forms" 是我們應用程式模組的名稱,你可能已經猜到,"forms" 模組依賴於 "core" 和 "utils"。你還可以看到 "utils" 模組依賴於 "jquery",這是一個由 jQuery 外掛提供的模組。這種結構最好透過圖表形式展現
如果我們深入研究上述模組定義,我們可以看到單個資源是使用“resource”加上 URL 在模組中宣告的。此 URL 是資源相對於專案中的web-app目錄的位置。如果需要,你還可以新增額外屬性,以實現對資源的精細控制,特別是透過“disposition”設定。
有兩種標準處置方式:“head”,表示資源位於 <head> 元素內;以及“defer”,通常表示位於 body 的末尾(儘管你可以控制確切的放置位置,稍後會看到)。預設情況下,CSS 檔案具有“head”處置,而 Javascript 檔案使用“defer”,但這些預設值可以按資源覆蓋。
我們現在有了定義簡單或複雜資源模組網路的基礎,這些網路跨越應用程式和外掛邊界。從使用者的角度來看,更好的是,外掛負責確保其模組包含適當的資源和依賴項。
因此,Grails 現在可能已經知道你的應用程式及其外掛提供了哪些靜態資源,但它仍然不知道哪些頁面需要哪些資源。為此,你必須對你的 GSP 進行一些修改。
如你所知,你以前必須在佈局和檢視中顯式宣告所有 CSS 和 Javascript 連結。那麼使用 Resources 外掛後,這會如何改變呢?你不再將連結放入單個資源中,而是宣告你的頁面需要哪些模組,這使得<head>塊更加簡潔。此外,你還可以指定資源連結在頁面中的位置。這是一個使用 Resources 的非常簡單的佈局示例
<html>
<head>
...
<r:require modules="common, jquery"/>
<r:layoutResources/>
</head>
<body>
...
<r:layoutResources/>
</body>
</html>
如你所見,<r:require>標籤告訴 Grails 要在頁面中包含哪些靜態資源,而<r:layoutResources>標籤指定連結應該放在哪裡。你應該有兩個<r:layoutResources>標籤:一個在<head>中,另一個在<body>中。任何處置方式為“head”的資源將放在第一個標籤的位置,而處置方式為“defer”的資源將插入到第二個標籤的位置。
就是這樣!大部分工作都花在確保模組定義正確上。
到目前為止我所介紹的對於 CSS、Javascript 和 favicon 檔案非常有效,因為 Resources 外掛知道為它們生成什麼連結以及將這些連結放在哪裡。但是內聯影像和指令碼會發生什麼呢?
Resources 外掛將內聯影像和指令碼稱為“臨時資源”。這些通常不會在模組中宣告,而是在頁面中遇到時簡單地進行處理。一個標準的內聯影像連結看起來像
<img src="${resource(dir:'images',file:'grails_logo.png')}" ... />
那麼我們如何讓 Resources 外掛知道影像檔案呢?我們不需要!從 Grails 2.0 開始,<g:resource/>標籤(上面用作方法)如果安裝了外掛,會自動向外掛註冊資源。這意味著對映器執行的所有魔法(稍後我會談到)都將應用於給定資源。當然,<g:resource/>可以用於任何型別的資源,而不僅僅是影像。
內聯指令碼有點不同,因為它們不是外部檔案的連結。但是它們仍然可以從 Resources 外掛中受益。預設情況下,所有使用<g:javascript/>標籤宣告的內聯指令碼將像往常一樣執行。但是,如果你將<g:javascript/>替換為<r:script/>標籤,則內聯指令碼將被移動到第二個<r:layoutResources/>的位置(它們的預設處置方式是“defer”)。你還可以宣告一個明確的處置方式,以便指令碼進入<head>。最棒的是,內聯指令碼保留了它們在頁面中宣告的順序。
還有一種臨時資源需要提及:CSS。樣式表是指定背景和其他型別影像的常見方式,但 CSS 檔案不作為 GSP 檔案處理。Resources 外掛是否知道這些連結?幸運的是,是的。儘管 Resources 外掛會修改它管理的所有資源的 URL 路徑,但這對你來說無關緊要,因為外掛還會自動更新 CSS 檔案中的連結。一切都會正常工作!
Resources 外掛本身就使靜態資源的管理比以前簡單得多。但這只是故事的一部分。由於外掛知道所有資源並控制它們的連結生成,因此它可以執行額外的處理以新增有趣的行為。此處理由一個可擴充套件的對映器管道完成
不要將此圖表視為絕對正確的參考:作為使用者,確切的管道及其工作方式並不重要。關鍵是,如果你願意,可以新增自己的對映器實現,或者只是安裝一個提供自己對映器的外掛。結果是,只需付出極少的努力,即可獲得一些非常強大的功能。
例如,假設你安裝了 Resources 外掛,定義了一些模組,並且你的 GSP 檢視和佈局已設定為使用適當的標籤。只需安裝 Cached Resources 和 Zipped Resources 外掛,你將立即開始滿足一些 ySlow 建議,例如為所有靜態資源設定長期 Expires 頭和 gzip 壓縮(儘管你可以停用特定檔案型別(如影像,它們通常已經壓縮)的 gzip 壓縮)。這不應該這麼容易,對嗎?但事實就是如此。
Resources 外掛已經存在了一段時間,並且已經在一些生產站點中使用。它甚至在 Grails 網站上也在使用。這不足為奇:它將靜態資源的改進管理與一個對映器管道相結合,該管道允許易於使用但功能強大的功能。經驗豐富的 Web 開發人員會立即注意到差異,你可以期待未來會有越來越多的外掛支援 Resources。它甚至有自己的使用者指南。
由於該外掛帶來的優勢,Grails 2 將其作為新 Grails 專案的預設外掛,並將其整合到一些核心標籤中,例如<g:resource>。但即使你還不能使用 Grails 2,你仍然可以將其與舊版本的 Grails 一起使用,並以很少的精力從出色的資源管理中受益。其關鍵設計原則之一是,它可以在任何 Grails 應用程式中安裝而不會破壞任何東西。
無論你使用哪個版本的 Grails,安裝此外掛都將改善你作為 Web 開發人員的生活。這不容小覷。