国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
使用wro4j和maven在編譯期間壓縮js和css文件(經(jīng)典)
     最近在對一個web系統(tǒng)做性能優(yōu)化.
而對用到的靜態(tài)資源文件的壓縮整合則是前端性能優(yōu)化中很重要的一環(huán).
好處不僅在于能夠減小請求的文件體積,而且能夠減少瀏覽器的http請求數(shù).

因為是基于java的web系統(tǒng),并且使用的是nginx+tomcat做為服務(wù)器.
最后考慮用wro4j和maven plugin在編譯期間壓縮靜態(tài)資源.

優(yōu)化前:
基本上所有的jsp都引用了這一大坨靜態(tài)文件:

Html代碼  收藏代碼

    <link rel="stylesheet" type="text/css" href="${ctxPath}/css/skin.css"/> 
    <link rel="stylesheet" type="text/css" href="${ctxPath}/css/jquery-ui-1.8.23.custom.css"/> 
    <link rel="stylesheet" type="text/css" href="${ctxPath}/css/validationEngine.jquery.css"/> 
     
    <script type="text/javascript">var GV = {ctxPath: '${ctxPath}',imgPath: '${ctxPath}/css'};</script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery-1.7.2.min.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery-ui-1.8.23.custom.min.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery.validationEngine.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery.validationEngine-zh_CN.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery.fixedtableheader.min.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/roll.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery.pagination.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery.rooFixed.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/jquery.ui.datepicker-zh-CN.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/json2.js"></script> 
    <script type="text/javascript" src="${ctxPath}/js/common.js"></script> 



引用的文件很多,并且文件體積沒有壓縮,導(dǎo)致頁面請求的時間非常長.

另外還有一個問題,就是為了能夠充分利用瀏覽器的緩存,靜態(tài)資源的文件名稱最好能夠做到版本化控制.

這樣前端web服務(wù)器就可以放心大膽的開啟緩存功能而不用擔(dān)心緩存過期問題,因為如果一旦靜態(tài)資源文件有修改的話,
會重新生成一個文件名稱.



下面我根據(jù)自己項目的經(jīng)驗,來介紹下如何較好的解決這兩個問題.

分兩步進行.

第一步:引入wro4j,在編譯時期將上述分散的多個文件整合成少數(shù)幾個文件,并且將文件最小化.

第二步:在生成的靜態(tài)資源文件的文件名稱上加入時間信息


這是兩步優(yōu)化之后的引用情況:
Html代碼  收藏代碼

    ${platform:cssFile("/wro/basic") } 
    <script type="text/javascript">var GV = {ctxPath: '${ctxPath}',imgPath: '${ctxPath}/css'};</script> 
    ${platform:jsFile("/wro/basic") } 
    ${platform:jsFile("/wro/custom") } 


只引用了1個css文件,2個js文件.http請求從10幾個減少到3個,并且整體文件體積縮小了近一半.

下面介紹優(yōu)化流程.

第一步:合并并且最小化文件.

1.添加wro4j的maven依賴
Xml代碼  收藏代碼

    <wro4j.version>1.6.2</wro4j.version> 
     
       ... 
     
     <dependency> 
      <groupId>ro.isdc.wro4j</groupId> 
      <artifactId>wro4j-core</artifactId> 
      <version>${wro4j.version}</version> 
      <exclusions> 
       <exclusion> 
     
       <!-- 因為項目中的其他jar包已經(jīng)引入了不同版本的slf4j,所以這里避免jar重疊所以不引入 --> 
        <groupId>org.slf4j</groupId> 
        <artifactId>slf4j-api</artifactId> 
       </exclusion> 
      </exclusions> 
     </dependency> 



2.添加wro4j maven plugin

Xml代碼  收藏代碼

       <plugin> 
        <groupId>ro.isdc.wro4j</groupId> 
        <artifactId>wro4j-maven-plugin</artifactId> 
        <version>${wro4j.version}</version> 
        <executions> 
         <execution> 
          <phase>compile</phase> 
          <goals> 
           <goal>run</goal> 
          </goals> 
         </execution> 
        </executions> 
        <configuration> 
         <targetGroups>basic,custom</targetGroups> 
     
        <!-- 這個配置是告訴wro4j在打包靜態(tài)資源的時候是否需要最小化文件,開發(fā)的時候可以設(shè)成false,方便調(diào)試 --> 
         <minimize>true</minimize> 
         <destinationFolder>${basedir}/src/main/webapp/wro/</destinationFolder> 
         <contextFolder>${basedir}/src/main/webapp/</contextFolder> 
     
    <!-- 這個配置是第二步優(yōu)化需要用到的,暫時忽略 --> 
         <wroManagerFactory>com.rootrip.platform.common.web.wro.CustomWroManagerFactory</wroManagerFactory> 
        </configuration> 
             </plugin> 



如果開發(fā)環(huán)境是eclipse的話,可以下載m2e-wro4j這個插件.

下載地址:http://download.jboss.org/jbosstools/updates/m2e-wro4j/

這個插件的主要功能是能夠幫助我們在開發(fā)環(huán)境下修改對應(yīng)的靜態(tài)文件,或者pom.xml文件的時候能夠自動生成打包好的js和css文件.

對開發(fā)來說就會方便很多.只要修改源文件就能看見修改后的結(jié)果.


3.在WEB-INF目錄下添加wro.xml文件,這個文件的作用就是告訴wro4j需要以怎樣的策略打包jss和css文件.
Java代碼  收藏代碼

    <?xml version="1.0" encoding="UTF-8"?> 
    <groups xmlns="http://www.isdc.ro/wro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://www.isdc.ro/wro wro.xsd"> 
     
     <group name="basic"> 
      <css>/css/basic.css</css> 
      <css>/css/skin.css</css> 
      <css>/css/jquery-ui-1.8.23.custom.css</css> 
      <css>/css/validationEngine.jquery.css</css> 
       
      <js>/js/jquery-1.7.2.min.js</js> 
      <js>/js/jquery-ui-1.8.23.custom.min.js</js> 
      <js>/js/jquery.validationEngine.js</js> 
      <js>/js/jquery.fixedtableheader.min.js</js> 
      <js>/js/roll.js</js> 
      <js>/js/jquery.pagination.js</js> 
      <js>/js/jquery.rooFixed.js</js> 
      <js>/js/jquery.ui.datepicker-zh-CN.js</js> 
      <js>/js/json2.js</js> 
     </group> 
      
     <group name="custom"> 
      <js>/js/jquery.validationEngine-zh_CN.js</js> 
      <js>/js/common.js</js> 
     </group> 
     
    </groups> 



官方文檔:http://code.google.com/p/wro4j/wiki/WroFileFormat

其實這個配置文件很好理解,如果不愿看官方文檔的朋友我在這簡單介紹下.

上面這樣配置的目的就是告訴wro4j要將

<css>/css/basic.css</css>
<css>/css/skin.css</css>
<css>/css/jquery-ui-1.8.23.custom.css</css>
<css>/css/validationEngine.jquery.css</css>

這四個文件整合到一起,生成一個叫basic.css的文件到指定目錄(wro4j-maven-plugin里配置的),將

<js>/js/jquery-1.7.2.min.js</js>
<js>/js/jquery-ui-1.8.23.custom.min.js</js>
<js>/js/jquery.validationEngine.js</js>
<js>/js/jquery.fixedtableheader.min.js</js>
<js>/js/roll.js</js>
<js>/js/jquery.pagination.js</js>
<js>/js/jquery.rooFixed.js</js>
<js>/js/jquery.ui.datepicker-zh-CN.js</js>
<js>/js/json2.js</js>

這幾個文件整合到一起,生成一個叫basic.js的文件到指定目錄.

最后將

<js>/js/jquery.validationEngine-zh_CN.js</js>
<js>/js/common.js</js>

這兩個文件整合到一起,,生成一個叫custom.js的文件到指定目錄.



第一步搞定,這時候如果你的開發(fā)環(huán)境是eclipse并且安裝了插件的話,應(yīng)該就能在你工程的%your webapp%/wor/目錄下看見生成好的

basic.css,basic.js和custom.js這三個文件了.

然后你再將你的靜態(tài)資源引用路徑改成

Html代碼  收藏代碼

    <link rel="stylesheet" type="text/css" href="${ctxPath}/wro/basic.css"/> 
    <script type="text/javascript" src="${ctxPath}/wro/basic.js"></script> 
    <script type="text/javascript" src="${ctxPath}/wro/custom.js"></script> 



就ok了.每次修改被引用到的css或js文件的時候,這些文件都將重新生成.

如果開發(fā)環(huán)境是eclipse但是沒有安裝m2e-wro4j插件的話,pom.xml可能需要額外配置.

請參考:https://community.jboss.org/en/tools/blog/2012/01/17/css-and-js-minification-using-eclipse-maven-and-wro4j



第二步:給生成的文件名稱中加入時間信息并通過el自定義函數(shù)引用腳本文件.

1. 創(chuàng)建DailyNamingStrategy類
Java代碼  收藏代碼

    public class DailyNamingStrategy extends TimestampNamingStrategy { 
      
     protected final Logger log = LoggerFactory.getLogger(DailyNamingStrategy.class); 
     
     @Override 
     protected long getTimestamp() { 
      String dateStr = DateUtil.formatDate(new Date(), "yyyyMMddHH"); 
      return Long.valueOf(dateStr); 
     } 
     
      
     
    } 



2.創(chuàng)建CustomWroManagerFactory類

Java代碼  收藏代碼

    //這個類就是在wro4j-maven-plugin里配置的wroManagerFactory參數(shù) 
    public class CustomWroManagerFactory extends 
      DefaultStandaloneContextAwareManagerFactory { 
     public CustomWroManagerFactory() { 
      setNamingStrategy(new DailyNamingStrategy()); 
     } 
    } 



上面這兩個類的作用是使用wro4j提供的文件命名策略,這樣生成的文件名就會帶上時間信息了.

例如:basic-2013020217.js

但是現(xiàn)在又會發(fā)現(xiàn)一個問題:如果靜態(tài)資源文件名稱不固定的話,那怎么樣引用呢?

這時候就需要通過動態(tài)生成<script>與<link>來解決了.

因為項目使用的是jsp頁面,所以通過el自定義函數(shù)來實現(xiàn)標(biāo)簽生成.


3.創(chuàng)建PlatformFunction類

Java代碼  收藏代碼

    public class PlatformFunction { 
      
     private static Logger log = LoggerFactory.getLogger(PlatformFunction.class); 
      
      
     private static ConcurrentMap<String, String> staticFileCache = new ConcurrentHashMap<>(); 
      
     private static AtomicBoolean initialized = new AtomicBoolean(false); 
      
     private static final String WRO_Path = "/wro/"; 
      
     private static final String JS_SCRIPT = "<script type=\"text/javascript\" src=\"%s\"></script>"; 
     private static final String CSS_SCRIPT = "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">"; 
      
     private static String contextPath = null;  
      
     /**
      * 該方法根據(jù)給出的路徑,生成js腳本加載標(biāo)簽
      * 例如傳入?yún)?shù)/wro/custom,該方法會尋找webapp路徑下/wro目錄中以custom開頭,以js后綴結(jié)尾的文件名稱名稱.
      * 然后拼成<script type="text/javascript" src="${ctxPath}/wro/custom-20130201.js"></script>返回
      * 如果查找到多個文件,返回根據(jù)文件名排序最大的文件
      * @param str
      * @return
      */ 
     public static String jsFile(String filePath) { 
      String jsFile = staticFileCache.get(buildCacheKey(filePath, "js")); 
      if(jsFile == null) { 
       log.error("加載js文件失敗,緩存中找不到對應(yīng)的文件[{}]", filePath); 
      } 
      return String.format(JS_SCRIPT, jsFile); 
     } 
      
     /**
      * 該方法根據(jù)給出的路徑,生成css腳本加載標(biāo)簽
      * 例如傳入?yún)?shù)/wro/custom,該方法會尋找webapp路徑下/wro目錄中以custom開頭,以css后綴結(jié)尾的文件名稱名稱.
      * 然后拼成<link rel="stylesheet" type="text/css" href="${ctxPath}/wro/basic-20130201.css">返回
      * 如果查找到多個文件,返回根據(jù)文件名排序最大的文件
      * @param str
      * @return
      */ 
     public static String cssFile(String filePath) { 
      String cssFile = staticFileCache.get(buildCacheKey(filePath, "css")); 
      if(cssFile == null) { 
       log.error("加載css文件失敗,緩存中找不到對應(yīng)的文件[{}]", filePath); 
      } 
      return String.format(CSS_SCRIPT, cssFile); 
     } 
      
     public static void init() throws IOException { 
      if(initialized.compareAndSet(false, true)) { 
       ServletContext sc = Platform.getInstance().getServletContext(); 
       if(sc == null) { 
        throw new PlatformException("查找靜態(tài)資源的時候的時候發(fā)現(xiàn)servlet context 為null"); 
       } 
       contextPath = Platform.getInstance().getContextPath(); 
       File wroDirectory = new ServletContextResource(sc, WRO_Path).getFile(); 
       if(!wroDirectory.exists() || !wroDirectory.isDirectory()) { 
        throw new PlatformException("查找靜態(tài)資源的時候發(fā)現(xiàn)對應(yīng)目錄不存在[" + wroDirectory.getAbsolutePath() + "]"); 
       } 
       //將wro目錄下已有文件加入緩存 
       for(File file : wroDirectory.listFiles()) { 
        handleNewFile(file); 
       } 
       //監(jiān)控wro目錄,如果有文件生成,則判斷是否是較新的文件,是的話則把文件名加入緩存 
       new Thread(new WroFileWatcher(wroDirectory.getAbsolutePath())).start(); 
      } 
     } 
     
     private static void handleNewFile(File file) { 
      String fileName = file.getName(); 
      Pattern p = Pattern.compile("^(\\w+)\\-\\d+\\.(js|css)$"); 
      Matcher m = p.matcher(fileName); 
      if(!m.find() || m.groupCount() < 2) return; 
      String fakeName = m.group(1); 
      String fileType = m.group(2); 
      //暫時限定只能匹配/wro/目錄下的文件 
      String key = buildCacheKey(WRO_Path + fakeName, fileType); 
      if(staticFileCache.putIfAbsent(key, fileName) != null) { 
       synchronized(staticFileCache) { 
        String cachedFileName = staticFileCache.get(key); 
        if(fileName.compareTo(cachedFileName) > 0) { 
         staticFileCache.put(key, contextPath + WRO_Path + fileName); 
        } 
       } 
      } 
     } 
      
     private static String buildCacheKey(String fakeName, String fileType) { 
      return fakeName + "-" + fileType; 
     } 
      
     static class WroFileWatcher implements Runnable { 
       
      private static Logger log = LoggerFactory.getLogger(WroFileWatcher.class); 
       
      private String wroAbsolutePathStr; 
       
      public WroFileWatcher(String wroPathStr) { 
       this.wroAbsolutePathStr = wroPathStr; 
      } 
     
      @Override 
      public void run() { 
       Path path = Paths.get(wroAbsolutePathStr); 
       File wroDirectory = path.toFile(); 
       if(!wroDirectory.exists() || !wroDirectory.isDirectory()) { 
        String message = "監(jiān)控wro目錄的時候發(fā)現(xiàn)對應(yīng)目錄不存在[" + wroAbsolutePathStr + "]"; 
        log.error(message); 
        throw new PlatformException(message); 
       } 
       log.warn("開始監(jiān)控wro目錄[{}]", wroAbsolutePathStr); 
       try { 
        WatchService watcher = FileSystems.getDefault().newWatchService(); 
        path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); 
         
        while (true) { 
         WatchKey key = null; 
         try { 
          key = watcher.take(); 
         } catch (InterruptedException e) { 
          log.error("", e); 
          continue; 
         } 
         for (WatchEvent<?> event : key.pollEvents()) { 
          if (event.kind() == StandardWatchEventKinds.OVERFLOW) { 
           continue; 
          } 
          WatchEvent<Path> e = (WatchEvent<Path>) event; 
          Path filePath = e.context(); 
          handleNewFile(filePath.toFile()); 
         } 
         if (!key.reset()) { 
          break; 
         } 
        } 
       } catch (IOException e) { 
        log.error("監(jiān)控wro目錄發(fā)生錯誤", e); 
       } 
       log.warn("停止監(jiān)控wro目錄[{}]", wroAbsolutePathStr); 
      } 
     } 
    } 



對應(yīng)的tld文件就不給出了,根據(jù)方法簽名編寫就行了.

其中的cssFile和jsFile方法分別實現(xiàn)引用css和js文件.

在頁面使用的時候類似這樣:

${platform:cssFile("/wro/basic") }

${platform:jsFile("/wro/custom") }

這個類的主要功能就是使用jdk7的WatchService監(jiān)控wro目錄的新增文件事件,

一旦有新的文件加到目錄里,判斷這個文件是不是最新的,如果是的話則使用這個文件名稱引用.

這樣一旦有新加的資源文件放到wro目錄里,則能夠自動被引用,不需要做任何代碼上的修改,并且基本不影響性能.



到此為止功能已經(jīng)實現(xiàn).

但是我考慮到還有兩個問題有待完善:

1.因為生成的文件名稱精確到小時,如果這個小時之內(nèi)有多次代碼修改,生成的文件名都完全一樣.

這樣就算線上的代碼有修改,對于已經(jīng)有該文本緩存的瀏覽器來說,不會重新請求文件,也就看不到文件變化.

不過一般來說線上代碼不會如此頻繁改動,對于大多數(shù)應(yīng)用來說影響不大.

2.在開發(fā)環(huán)境開發(fā)一段時間之后,wro目錄下會生成一大堆的文件(因為m2e-wro4j插件在生成新的文件的時候不會刪除舊文件,如果文件名相同會覆蓋掉以前的文件),

這時候就需要手動刪除時間靠前的舊文件,雖然系統(tǒng)會忽略舊文件,但是我相信大多數(shù)程序員和我一樣是有些許潔癖的吧.

解決辦法還是不少,比如可以寫腳本定期清理掉舊文件.

時間有限,有些地方考慮的不是很完善,歡迎拍磚.

參考資料:
http://meri-stuff.blogspot.sk/2012/08/wro4j-page-load-optimization-and-lessjs.html#Configuration
https://community.jboss.org/en/tools/blog/2012/01/17/css-and-js-minification-using-eclipse-maven-and-wro4j
http://code.google.com/p/wro4j/wiki/MavenPlugin
http://code.google.com/p/wro4j/wiki/WroFileFormat
http://java.dzone.com/articles/using-java-7s-watchservice    
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
jQuery---jQuery插件
web的各種前端打印方法之jquery打印插件jqprint實現(xiàn)網(wǎng)頁打印,JavaScript教程,JavaScript案例,JavaScript實例
bootstrap 快速搭建
Struts2+JQuery+Json及JQuery相關(guān)插件的例子(好)
Modernizr作為開發(fā)HTML5必要的js工具
前端jquery技術(shù)一些簡單控件,以及數(shù)據(jù)綁定傳輸問題
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服