posts - 36, comments - 419, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          JS 實現(xiàn)完美include

          Posted on 2010-08-09 08:29 BearRui(AK-47) 閱讀(3115) 評論(7)  編輯  收藏 所屬分類: javascript

            js為什么需要include?讓我們想想這樣1個場景,a.js 需要用到1個公用的common.js,當然你可以在用到a.js的頁面使用<script src="common.js">,但假設有5個頁面用到了a.js,你是不是要寫5遍<script。而且要是以后a.js 又需要引用common2.js,你是不是又的修改5個頁面了?

           

          已有js include的一些問題

              在寫這個之前在網(wǎng)上搜索了些資料,發(fā)現(xiàn)以前寫的include都存在2個問題,這也是include需要解決的比較重要的2個問題。

             1、相對路徑的問題:  在a.js中使用include("../js/common.js");  include 函數(shù)中肯定是使用相對路徑,是相對a.js的路徑。而a.js在html中使用<script>嵌入有可能是相對路徑,有可能是絕對路徑。  include函數(shù)如何才能真正確定common.js的絕對路徑,或者是相對html的相對路徑。網(wǎng)上一些為了解決這個問題,還需要加一些js變量,不方便。  

             2、引用的問題。  網(wǎng)上include函數(shù)的實現(xiàn)幾乎都是使用下面2種方式插入common.js     

                document.write("<script src='" + .. + "></script>")  

              或者    

                var s = document.createElement("script");    

                s.src = ...;    

                head.insertAfter(s,...);    

              document.write 輸出的腳本會在a.js后面加載,而createElement("script")創(chuàng)建的腳本是非阻塞加載。  所以如果在common.js加載完畢之前,a.js中調用了common.js的函數(shù)就會報錯。

           

          實現(xiàn)

               解決上面2個問題,就可以實現(xiàn)js include。  

             第1個問題,我的方法是先獲取到a.js在html中的絕對路徑(如果是相對路徑,就轉為絕對路徑),然后再把common.js的路徑轉為絕對路徑。  

             第2個問題,采用同步的ajax來請求common.js,這樣就不會出現(xiàn)引用問題。

           

            實現(xiàn)代碼如下:

           // 根據(jù)相對路徑獲取絕對路徑

          function getPath(relativePath,absolutePath){
              
          var reg = new RegExp("\\.\\./","g");
              
          var uplayCount = 0;        // 相對路徑中返回上層的次數(shù)。
              var m = relativePath.match(reg);
              
          if(m) uplayCount = m.length;
              
              
          var lastIndex = absolutePath.length-1
              
          for(var i=0;i<=uplayCount;i++){
                  lastIndex 
          = absolutePath.lastIndexOf("/",lastIndex);
              }
              
          return absolutePath.substr(0,lastIndex+1+ relativePath.replace(reg,"");
          }         

          function include(jssrc){
              
          // 先獲取當前a.js的src。a.js中調用include,直接獲取最后1個script標簽就是a.js的引用。
              var scripts = document.getElementsByTagName("script");
              
          var lastScript = scripts[scripts.length-1];
              
          var src = lastScript.src;
              
          if(src.indexOf("http://")!=0 && src.indexOf("/"!=0){        
                  
          // a.js使用相對路徑,先替換成絕對路徑
                  var url = location.href;
                  
          var index = url.indexOf("?");
                  
          if(index != -1){
                      url 
          = url.substring(0, index-1);
                  }
                  
                  src 
          = getPath(src,url);
              }
              
          var jssrcs = jssrc.split("|");    // 可以include多個js,用|隔開
              for(var i=0;i<jssrcs.length;i++){
                  
          // 使用juqery的同步ajax加載js.
                  // 使用document.write 動態(tài)添加的js會在當前js的后面,可能會有js引用問題
                  // 動態(tài)創(chuàng)建script腳本,是非阻塞下載,也會出現(xiàn)引用問題
                  $.ajax({type:'GET',url:getPath(jssrc,src),async:false,dataType:'script'});
              }
          }

            在a.js中直接使用 include("../js/common.js");

           

          多請求的問題

            使用上面的include看上去挺爽的,不過卻帶來另外1個嚴重的問題,就是多發(fā)送了1個ajax的請求。

            我們常常為了WEB性能,而合并js,減少請求。但使用include后卻偏偏多了請求。如果這個問題不解決,相信很多人都不會在正式產品中使用include的了,除非是局域網(wǎng)產品。

           

            如何解決這個多請求的問題,我也思考很久,最后覺的單單使用客戶端js是沒辦法解決了。所以就想到了使用服務端代碼來解決

            還記的我之前有文章介紹 "js、css的合并、壓縮、緩存管理"的時候,就通過服務器端代碼在程序啟動時候去合并js。

           

            所以我把include多請求的解決方案也加到里面去。就是在程序啟動的時候去查找所有的js,發(fā)現(xiàn)有使用include的就把include中common.js的源代碼替換該include函數(shù)。這樣a.js中在運行的時候就沒有include函數(shù),而是真真包含了common.js的內容的js文件

           

          后語

            丫的。說到最后,怎么又把所有的include都替換掉了,哪之前說的那么多不白說了。

           

            個人覺得,每個產品都應該要區(qū)分開發(fā)環(huán)境和產品環(huán)境(一般通過配置文件進行區(qū)分),在開發(fā)環(huán)境應該以開發(fā)效率為首要,而產品環(huán)境則以性能為首。所以這里的inlcude就應該要區(qū)分對待,在開發(fā)環(huán)境中使用js include來提高開發(fā)和維護效率,而在產品環(huán)境中則自動把所有include替換成真真的js文件的內容。

           

            都說完了,歡迎大家拍磚討論。



          [作者]:BearRui(AK-47)
          [博客]: http://www.aygfsteel.com/bearrui/
          [聲明]:本博所有文章版權歸作者所有(除特殊說明以外),轉載請注明出處.
          英雄,別走啊,幫哥評論下:  

          精彩推薦 好文要頂 水平一般 看不懂 還需努力

          評論

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-09 11:25 by DNF免費外掛
          http://www.1ploan.com http://www.51pkwg.com http://www.h0701.com

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-10 14:48 by hanmiao
          有幾個錯別字,文章寫得不錯。

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-10 15:18 by BearRui(AK-47)
          @hanmiao
          呵呵,不好意思,有點粗心了。

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-16 18:01 by kevon
          文章很精彩,推薦一下!

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-16 18:02 by kevon
          好文章,頂一下!

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-16 18:02 by kevon
          文章很精彩,推薦一下!

          # re: JS 實現(xiàn)完美include  回復  更多評論   

          2010-08-16 18:02 by kevon
          好文章,頂一下!
          主站蜘蛛池模板: 沧源| 萨嘎县| 故城县| 莱阳市| 台湾省| 巨鹿县| 安图县| 尚义县| 塘沽区| 宁河县| 临沧市| 喀喇| 洪雅县| 鄄城县| 桦南县| 洛扎县| 沾化县| 沙雅县| 东源县| 盖州市| 宁强县| 凌海市| 祁阳县| 凤翔县| 额尔古纳市| 吴堡县| 河北省| 寿光市| 孝感市| 会同县| 墨脱县| 武威市| 延川县| 华阴市| 雅江县| 北海市| 桐庐县| 永济市| 宕昌县| 天柱县| 金山区|