您好,登錄后才能下訂單哦!
前面已經(jīng)用了幾篇文章詳細(xì)的講解了DynamicCSSFilter,現(xiàn)在我們來看他們是如何應(yīng)用到加載css資源文件的。
前提:
假定我們開發(fā)了一個(gè)theme叫platform-In-theme,它其中我們寫了一個(gè)main.css,并且在其中我們用@import url()語(yǔ)法包含了若干個(gè)其他css,其中有一個(gè)是forms.css,并且這個(gè)css是用Sass的語(yǔ)法規(guī)則寫的,我們來深入研究下加載這個(gè)2個(gè)css文件的異同。
調(diào)試分析:
首先,當(dāng)頁(yè)面請(qǐng)求main.css的時(shí)候,因?yàn)樗鼭M足DynamicCSSFilter的模式,所以進(jìn)入processFilter()方法,由前面幾篇文章,很快的拿到requestURI,requestPath,contextPath等信息,
從這圖上可以很清楚的看到,這個(gè)realPath是在我們的tomcat服務(wù)器上的webapps目錄下的theme部署子目錄,所以說這個(gè)是正確的,我們的自定義theme都是部署在這個(gè)目錄上。
現(xiàn)在我們可以看下原始還沒有被解析的main.css長(zhǎng)什么樣子:
很顯然,和我們?cè)O(shè)想的一樣,它就是作為一個(gè)總的css用來包含其他的css文件。
現(xiàn)在開始解析這個(gè)css 文件,調(diào)用的是DynamicCSSUtil類的parseSass()方法.
首先它在第用98行利用theme=_getTheme(request,c***ealPath)來
獲取當(dāng)前theme,因?yàn)槲覀兊恼军c(diǎn)使用了platform-In-theme,所以返回這個(gè)theme.
然后,它利用_isThemeCssFastLoad(request,themeDisplay)方法獲取我們是否啟用了fast load ,因?yàn)檫@里我們沒有啟用fast load,所以返回false.
然后在115行獲取c***ealFile的File對(duì)象,剛才講過了,這個(gè)theme在服務(wù)器的webapps的相應(yīng)theme目錄中。
然后調(diào)用SassToCssBuilder.getCacheFile(c***ealPath)方法
來獲取這個(gè)css資源文件對(duì)應(yīng)的緩存文件,它首先吧真實(shí)css資源文件的反斜杠"\\"全部替換成正斜杠"/",然后獲取最后一個(gè)正斜杠位置,這是用來區(qū)分文件路徑部分和文件名部分,然后它在中間插入.sass_cache.
(千萬注意,這次和上次說的$CATALINA_HOME/TMPDIR 下面的緩存數(shù)據(jù)文件完全不同,那個(gè)文件是用于直接返回到客戶端(如果存在并且最新)的最終css文件,如果使用那個(gè)文件,就壓根不會(huì)調(diào)用parseSass()方法,而這個(gè)緩存的是原始的css資源文件,它是在parseSass()方法中被調(diào)用的,所以用途不同)
所以獲得的緩存文件的路徑就是如下圖:
這里有個(gè)判斷,如果這個(gè)緩存文件存在并且是最新的,那么就不用調(diào)用jRuby解析,而是直接把這個(gè)緩存文件的內(nèi)容作為最終parseSass()的返回值,也就是作為最終解析完的普通css文件輸出,但是我們是第一次,所以沒有這個(gè)資源文件,只好老老實(shí)實(shí)走jRuby解析的過程。
(1)正式解析的第一步是調(diào)用SassToCssBuilder.parseStaticTokens(content)方法來吧一些靜態(tài)的符號(hào)替換掉:
很容易理解,就是把Sass中的一些特殊內(nèi)容替換掉,比如文本的寬度,高度,和輸入框的高度寬度。
在這一步完結(jié)后,我們的main.css不受到影響。
(2)正式解析的第二步是先通過getQueryString方法獲得請(qǐng)求字符串。
然后調(diào)用_propagateQueryString()方法進(jìn)行操作:
這步驟的作用是對(duì)于每一個(gè)@import(url ...)導(dǎo)入的資源文件,都在后面加上請(qǐng)求字符串。所以在這一步之后,我們的main.css變?yōu)椋?/p>
和我們?cè)O(shè)想的一樣,所有的@import url 的url后面都附加了請(qǐng)求字符串。這是為了保證請(qǐng)求一致性(我猜的)
(3)正式解析的第三步就進(jìn)入了jRuby解析引擎的內(nèi)核了,這是通過_parseSass私有方法來完成的:
從這里我們可以看出,它首先會(huì)構(gòu)造一個(gè)HashMap對(duì)象,然后把我們要解析必要的參數(shù),比如被解析的Sass內(nèi)容(content),css的真實(shí)路徑(c***ealPath),在當(dāng)前應(yīng)用使用的Theme的css路徑(cssThemePath),sass的緩存位置(sassCachePath)都放在HashMap中,然后在第295行使用_rubyExecutor.eval()方法調(diào)用jRuby解析器(位于/webapps/ROOT/WEB-INF/lib/jruby.jar中)來解析這個(gè)Sass文件:
最后解析完的結(jié)果通過unsyncPrintWriter輸出而返回,對(duì)于我們的main.css來說,經(jīng)過這一步之后,結(jié)果還是一樣的。因?yàn)檫@文件大多數(shù)都是引入其他文件,并沒有Sass的語(yǔ)法,所以不受到j(luò)Ruby解析引擎的 影響。
(4)正式解析的第四步是吧@portal_ctx@和@theme_p_w_picpath_path@注解都替換成相應(yīng)的字符串,這個(gè)工作代碼如下:
我們的main.css中沒有這些標(biāo)識(shí)符,所以不受到影響。
經(jīng)過以上4步之后,這個(gè)方法就返回了dynamicContent,我們可以看到,它最終 返回到瀏覽器后的結(jié)果和正式解析第二步的一樣:
以上我們講解的是對(duì)于main.css的資源訪問,我們現(xiàn)在來看下對(duì)于其中包含的某個(gè)用Sass寫的文件,比如說上面的forms.css,這個(gè)流程又是這么樣的。
其實(shí)大體上流程都一致:
我這里也想省略去多數(shù)重復(fù)的調(diào)試流程了,反正最終不一樣的就是正式解析的第3步,它會(huì)去調(diào)用jruby.jar中的解析引擎去完成具體的解析,所以我們開始這個(gè)forms.css文件的內(nèi)容是:
解析完成之后,這個(gè)文件內(nèi)容變?yōu)椋?/p>
總結(jié):
(1)當(dāng)單個(gè)加載Sass資源文件的時(shí)候,這種Sass資源文件都有可能有解析完的文件緩存在服務(wù)器上,并且緩存文件的位置一定在原始資源文件的上級(jí)目錄下的.sass_cache目錄下,并且文件名和原始Sass資源文件名字相同。
(2)正式解析的第一步是解析Sass文件中的靜態(tài)符號(hào),比如@model_hints_contant....@
(3) 正式解析的第二步是吧所有Sass中的以@import url()形式給出的外部引入,其被引入的資源文件后面都加上請(qǐng)求字符串,這是為了保證其請(qǐng)求的一致性。
(4)正式解析的第三步是調(diào)用jRuby的解析引擎根據(jù)解析語(yǔ)法進(jìn)行解析,它會(huì)吧所有的Sass語(yǔ)法替換為普通的css語(yǔ)法,這個(gè)解析引擎位于webapps/ROOT/WEB-INF/lib/jruby.jar jar包中
(5)正式解析的第四步是做一些收尾工作,吧一些靜態(tài)標(biāo)識(shí)符@portal_ctx@和@theme_p_w_picpath_path@解析為字符串,因?yàn)樵赾ss文件中經(jīng)常會(huì)用到一些外部圖片參與到樣式中。
(6)對(duì)于main.css ,主要影響的是(3)
(7)對(duì)于main.css包含的某個(gè)css,如果它是用Sass語(yǔ)法寫的,那么主要受到影響的是(4)
(8)一般的css,如果頁(yè)面上有一些特殊的記號(hào),那么受到(2)和 (5)影響。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。