中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
使用wro4j和maven在編譯期間壓縮js和css文件


最近在對(duì)一個(gè)web系統(tǒng)做性能優(yōu)化. 
而對(duì)用到的靜態(tài)資源文件的壓縮整合則是前端性能優(yōu)化中很重要的一環(huán). 
好處不僅在于能夠減小請(qǐng)求的文件體積,而且能夠減少瀏覽器的http請(qǐng)求數(shù). 

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

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

Html代碼   
  1. <link rel="stylesheet" type="text/css" href="${ctxPath}/css/skin.css"/>  
  2. <link rel="stylesheet" type="text/css" href="${ctxPath}/css/jquery-ui-1.8.23.custom.css"/>  
  3. <link rel="stylesheet" type="text/css" href="${ctxPath}/css/validationEngine.jquery.css"/>  
  4.   
  5. <script type="text/javascript">var GV = {ctxPath: '${ctxPath}',imgPath: '${ctxPath}/css'};</script>  
  6. <script type="text/javascript" src="${ctxPath}/js/jquery-1.7.2.min.js"></script>  
  7. <script type="text/javascript" src="${ctxPath}/js/jquery-ui-1.8.23.custom.min.js"></script>  
  8. <script type="text/javascript" src="${ctxPath}/js/jquery.validationEngine.js"></script>  
  9. <script type="text/javascript" src="${ctxPath}/js/jquery.validationEngine-zh_CN.js"></script>  
  10. <script type="text/javascript" src="${ctxPath}/js/jquery.fixedtableheader.min.js"></script>  
  11. <script type="text/javascript" src="${ctxPath}/js/roll.js"></script>  
  12. <script type="text/javascript" src="${ctxPath}/js/jquery.pagination.js"></script>  
  13. <script type="text/javascript" src="${ctxPath}/js/jquery.rooFixed.js"></script>  
  14. <script type="text/javascript" src="${ctxPath}/js/jquery.ui.datepicker-zh-CN.js"></script>  
  15. <script type="text/javascript" src="${ctxPath}/js/json2.js"></script>  
  16. <script type="text/javascript" src="${ctxPath}/js/common.js"></script>  



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

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

這樣前端web服務(wù)器就可以放心大膽的開啟緩存功能而不用擔(dān)心緩存過期問題,因?yàn)槿绻坏╈o態(tài)資源文件有修改的話, 
會(huì)重新生成一個(gè)文件名稱. 



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

分兩步進(jìn)行. 

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

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


這是兩步優(yōu)化之后的引用情況: 

Html代碼   
  1. ${platform:cssFile("/wro/basic") }  
  2. <script type="text/javascript">var GV = {ctxPath: '${ctxPath}',imgPath: '${ctxPath}/css'};</script>  
  3. ${platform:jsFile("/wro/basic") }  
  4. ${platform:jsFile("/wro/custom") }  


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

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

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

1.添加wro4j的maven依賴 

Xml代碼   
  1. <wro4j.version>1.6.2</wro4j.version>  
  2.   
  3.    ...  
  4.   
  5.  <dependency>  
  6.   <groupId>ro.isdc.wro4j</groupId>  
  7.   <artifactId>wro4j-core</artifactId>  
  8.   <version>${wro4j.version}</version>  
  9.   <exclusions>  
  10.    <exclusion>  
  11.   
  12.    <!-- 因?yàn)轫?xiàng)目中的其他jar包已經(jīng)引入了不同版本的slf4j,所以這里避免jar重疊所以不引入 -->  
  13.     <groupId>org.slf4j</groupId>  
  14.     <artifactId>slf4j-api</artifactId>  
  15.    </exclusion>  
  16.   </exclusions>  
  17.  </dependency>  



2.添加wro4j maven plugin 

Xml代碼   
  1.    <plugin>  
  2.     <groupId>ro.isdc.wro4j</groupId>  
  3.     <artifactId>wro4j-maven-plugin</artifactId>  
  4.     <version>${wro4j.version}</version>  
  5.     <executions>  
  6.      <execution>  
  7.       <phase>compile</phase>  
  8.       <goals>  
  9.        <goal>run</goal>  
  10.       </goals>  
  11.      </execution>  
  12.     </executions>  
  13.     <configuration>  
  14.      <targetGroups>basic,custom</targetGroups>  
  15.   
  16.     <!-- 這個(gè)配置是告訴wro4j在打包靜態(tài)資源的時(shí)候是否需要最小化文件,開發(fā)的時(shí)候可以設(shè)成false,方便調(diào)試 -->  
  17.      <minimize>true</minimize>  
  18.      <destinationFolder>${basedir}/src/main/webapp/wro/</destinationFolder>  
  19.      <contextFolder>${basedir}/src/main/webapp/</contextFolder>  
  20.   
  21. <!-- 這個(gè)配置是第二步優(yōu)化需要用到的,暫時(shí)忽略 -->  
  22.      <wroManagerFactory>com.rootrip.platform.common.web.wro.CustomWroManagerFactory</wroManagerFactory>  
  23.     </configuration>  
  24.          </plugin>  



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

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

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

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


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

Java代碼   
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <groups xmlns="http://www.isdc.ro/wro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.  xsi:schemaLocation="http://www.isdc.ro/wro wro.xsd">  
  4.   
  5.  <group name="basic">  
  6.   <css>/css/basic.css</css>  
  7.   <css>/css/skin.css</css>  
  8.   <css>/css/jquery-ui-1.8.23.custom.css</css>  
  9.   <css>/css/validationEngine.jquery.css</css>  
  10.     
  11.   <js>/js/jquery-1.7.2.min.js</js>  
  12.   <js>/js/jquery-ui-1.8.23.custom.min.js</js>  
  13.   <js>/js/jquery.validationEngine.js</js>  
  14.   <js>/js/jquery.fixedtableheader.min.js</js>  
  15.   <js>/js/roll.js</js>  
  16.   <js>/js/jquery.pagination.js</js>  
  17.   <js>/js/jquery.rooFixed.js</js>  
  18.   <js>/js/jquery.ui.datepicker-zh-CN.js</js>  
  19.   <js>/js/json2.js</js>  
  20.  </group>  
  21.    
  22.  <group name="custom">  
  23.   <js>/js/jquery.validationEngine-zh_CN.js</js>  
  24.   <js>/js/common.js</js>  
  25.  </group>  
  26.   
  27. </groups>  



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

其實(shí)這個(gè)配置文件很好理解,如果不愿看官方文檔的朋友我在這簡(jiǎn)單介紹下. 

上面這樣配置的目的就是告訴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> 

這四個(gè)文件整合到一起,生成一個(gè)叫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> 

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

最后將 

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

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



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

basic.css,basic.js和custom.js這三個(gè)文件了. 

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

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



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

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

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



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

1. 創(chuàng)建DailyNamingStrategy類 

Java代碼   
  1. public class DailyNamingStrategy extends TimestampNamingStrategy {  
  2.    
  3.  protected final Logger log = LoggerFactory.getLogger(DailyNamingStrategy.class);  
  4.   
  5.  @Override  
  6.  protected long getTimestamp() {  
  7.   String dateStr = DateUtil.formatDate(new Date(), "yyyyMMddHH");  
  8.   return Long.valueOf(dateStr);  
  9.  }  
  10.   
  11.    
  12.   
  13. }  



2.創(chuàng)建CustomWroManagerFactory類 

Java代碼   
  1. //這個(gè)類就是在wro4j-maven-plugin里配置的wroManagerFactory參數(shù)  
  2. public class CustomWroManagerFactory extends  
  3.   DefaultStandaloneContextAwareManagerFactory {  
  4.  public CustomWroManagerFactory() {  
  5.   setNamingStrategy(new DailyNamingStrategy());  
  6.  }  
  7. }  



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

例如:basic-2013020217.js 

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

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

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


3.創(chuàng)建PlatformFunction類 

Java代碼   
  1. public class PlatformFunction {  
  2.    
  3.  private static Logger log = LoggerFactory.getLogger(PlatformFunction.class);  
  4.    
  5.    
  6.  private static ConcurrentMap<String, String> staticFileCache = new ConcurrentHashMap<>();  
  7.    
  8.  private static AtomicBoolean initialized = new AtomicBoolean(false);  
  9.    
  10.  private static final String WRO_Path = "/wro/";  
  11.    
  12.  private static final String JS_SCRIPT = "<script type=\"text/javascript\" src=\"%s\"></script>";  
  13.  private static final String CSS_SCRIPT = "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">";  
  14.    
  15.  private static String contextPath = null;   
  16.    
  17.  /** 
  18.   * 該方法根據(jù)給出的路徑,生成js腳本加載標(biāo)簽 
  19.   * 例如傳入?yún)?shù)/wro/custom,該方法會(huì)尋找webapp路徑下/wro目錄中以custom開頭,以js后綴結(jié)尾的文件名稱名稱. 
  20.   * 然后拼成<script type="text/javascript" src="${ctxPath}/wro/custom-20130201.js"></script>返回 
  21.   * 如果查找到多個(gè)文件,返回根據(jù)文件名排序最大的文件 
  22.   * @param str 
  23.   * @return  
  24.   */  
  25.  public static String jsFile(String filePath) {  
  26.   String jsFile = staticFileCache.get(buildCacheKey(filePath, "js"));  
  27.   if(jsFile == null) {  
  28.    log.error("加載js文件失敗,緩存中找不到對(duì)應(yīng)的文件[{}]", filePath);  
  29.   }  
  30.   return String.format(JS_SCRIPT, jsFile);  
  31.  }  
  32.    
  33.  /** 
  34.   * 該方法根據(jù)給出的路徑,生成css腳本加載標(biāo)簽 
  35.   * 例如傳入?yún)?shù)/wro/custom,該方法會(huì)尋找webapp路徑下/wro目錄中以custom開頭,以css后綴結(jié)尾的文件名稱名稱. 
  36.   * 然后拼成<link rel="stylesheet" type="text/css" href="${ctxPath}/wro/basic-20130201.css">返回 
  37.   * 如果查找到多個(gè)文件,返回根據(jù)文件名排序最大的文件 
  38.   * @param str 
  39.   * @return  
  40.   */  
  41.  public static String cssFile(String filePath) {  
  42.   String cssFile = staticFileCache.get(buildCacheKey(filePath, "css"));  
  43.   if(cssFile == null) {  
  44.    log.error("加載css文件失敗,緩存中找不到對(duì)應(yīng)的文件[{}]", filePath);  
  45.   }  
  46.   return String.format(CSS_SCRIPT, cssFile);  
  47.  }  
  48.    
  49.  public static void init() throws IOException {  
  50.   if(initialized.compareAndSet(falsetrue)) {  
  51.    ServletContext sc = Platform.getInstance().getServletContext();  
  52.    if(sc == null) {  
  53.     throw new PlatformException("查找靜態(tài)資源的時(shí)候的時(shí)候發(fā)現(xiàn)servlet context 為null");  
  54.    }  
  55.    contextPath = Platform.getInstance().getContextPath();  
  56.    File wroDirectory = new ServletContextResource(sc, WRO_Path).getFile();  
  57.    if(!wroDirectory.exists() || !wroDirectory.isDirectory()) {  
  58.     throw new PlatformException("查找靜態(tài)資源的時(shí)候發(fā)現(xiàn)對(duì)應(yīng)目錄不存在[" + wroDirectory.getAbsolutePath() + "]");  
  59.    }  
  60.    //將wro目錄下已有文件加入緩存  
  61.    for(File file : wroDirectory.listFiles()) {  
  62.     handleNewFile(file);  
  63.    }  
  64.    //監(jiān)控wro目錄,如果有文件生成,則判斷是否是較新的文件,是的話則把文件名加入緩存  
  65.    new Thread(new WroFileWatcher(wroDirectory.getAbsolutePath())).start();  
  66.   }  
  67.  }  
  68.   
  69.  private static void handleNewFile(File file) {  
  70.   String fileName = file.getName();  
  71.   Pattern p = Pattern.compile("^(\\w+)\\-\\d+\\.(js|css)$");  
  72.   Matcher m = p.matcher(fileName);  
  73.   if(!m.find() || m.groupCount() < 2return;  
  74.   String fakeName = m.group(1);  
  75.   String fileType = m.group(2);  
  76.   //暫時(shí)限定只能匹配/wro/目錄下的文件  
  77.   String key = buildCacheKey(WRO_Path + fakeName, fileType);  
  78.   if(staticFileCache.putIfAbsent(key, fileName) != null) {  
  79.    synchronized(staticFileCache) {  
  80.     String cachedFileName = staticFileCache.get(key);  
  81.     if(fileName.compareTo(cachedFileName) > 0) {  
  82.      staticFileCache.put(key, contextPath + WRO_Path + fileName);  
  83.     }  
  84.    }  
  85.   }  
  86.  }  
  87.    
  88.  private static String buildCacheKey(String fakeName, String fileType) {  
  89.   return fakeName + "-" + fileType;  
  90.  }  
  91.    
  92.  static class WroFileWatcher implements Runnable {  
  93.     
  94.   private static Logger log = LoggerFactory.getLogger(WroFileWatcher.class);  
  95.     
  96.   private String wroAbsolutePathStr;  
  97.     
  98.   public WroFileWatcher(String wroPathStr) {  
  99.    this.wroAbsolutePathStr = wroPathStr;  
  100.   }  
  101.   
  102.   @Override  
  103.   public void run() {  
  104.    Path path = Paths.get(wroAbsolutePathStr);  
  105.    File wroDirectory = path.toFile();  
  106.    if(!wroDirectory.exists() || !wroDirectory.isDirectory()) {  
  107.     String message = "監(jiān)控wro目錄的時(shí)候發(fā)現(xiàn)對(duì)應(yīng)目錄不存在[" + wroAbsolutePathStr + "]";  
  108.     log.error(message);  
  109.     throw new PlatformException(message);  
  110.    }  
  111.    log.warn("開始監(jiān)控wro目錄[{}]", wroAbsolutePathStr);  
  112.    try {  
  113.     WatchService watcher = FileSystems.getDefault().newWatchService();  
  114.     path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);  
  115.       
  116.     while (true) {  
  117.      WatchKey key = null;  
  118.      try {  
  119.       key = watcher.take();  
  120.      } catch (InterruptedException e) {  
  121.       log.error("", e);  
  122.       continue;  
  123.      }  
  124.      for (WatchEvent<?> event : key.pollEvents()) {  
  125.       if (event.kind() == StandardWatchEventKinds.OVERFLOW) {  
  126.        continue;  
  127.       }  
  128.       WatchEvent<Path> e = (WatchEvent<Path>) event;  
  129.       Path filePath = e.context();  
  130.       handleNewFile(filePath.toFile());  
  131.      }  
  132.      if (!key.reset()) {  
  133.       break;  
  134.      }  
  135.     }  
  136.    } catch (IOException e) {  
  137.     log.error("監(jiān)控wro目錄發(fā)生錯(cuò)誤", e);  
  138.    }  
  139.    log.warn("停止監(jiān)控wro目錄[{}]", wroAbsolutePathStr);  
  140.   }  
  141.  }  
  142. }  



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

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

在頁面使用的時(shí)候類似這樣: 

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

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

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

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

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



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

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

1.因?yàn)樯傻奈募Q精確到小時(shí),如果這個(gè)小時(shí)之內(nèi)有多次代碼修改,生成的文件名都完全一樣. 

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

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

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

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

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

時(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

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
jQuery---jQuery插件
bootstrap 快速搭建
jquery datepicker 彈出日期框選擇之用法(原創(chuàng))
EasyUI入門:如何引入及簡(jiǎn)單使用
母版頁中引用圖片、外部js、css文件的路徑問題
bootstrap table和tableExport導(dǎo)出支持中文的Excel和pdf等表格
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服