JS 實現完美include載入實現代碼

來源:互聯網
上載者:User

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的一些問題
  在寫這個之前在網上搜尋了些資料,發現以前寫的include都存在2個問題,這也是include需要解決的比較重要的2個問題。
  1、相對路徑的問題: 在a.js中使用include("../js/common.js"); include 函數中肯定是使用相對路徑,是相對a.js的路徑。而a.js在html中使用<script>嵌入有可能是相對路徑,有可能是絕對路徑。 include函數如何才能真正確定common.js的絕對路徑,或者是相對html的相對路徑。網上一些為瞭解決這個問題,還需要加一些js變數,不方便。
  2、引用的問題。 網上include函數的實現幾乎都是使用下面2種方式插入common.js
      document.write("<script src='" + .. + "></script>")
    或者
      var s = document.createElement("script");
      s.src = ...;
      head.insertAfter(s,...);
    document.write 輸出的指令碼會在a.js後面載入,而createElement("script")建立的指令碼是非阻塞載入。 所以如果在common.js載入完畢之前,a.js中調用了common.js的函數就會報錯。
實現
  解決上面2個問題,就可以實現js include。
  第1個問題,我的方法是先擷取到a.js在html中的絕對路徑(如果是相對路徑,就轉為絕對路徑),然後再把common.js的路徑轉為絕對路徑。
  第2個問題,採用同步的ajax來請求common.js,這樣就不會出現引用問題。
  實現代碼如下: 複製代碼 代碼如下:// 根據相對路徑擷取絕對路徑
function getPath(relativePath,absolutePath){
var reg = new RegExp("\\.\\./","g");
var uplayCount = 0; // 相對路徑中返回上層的次數。
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 動態添加的js會在當前js的後面,可能會有js引用問題
// 動態建立script指令碼,是非阻塞下載,也會出現引用問題
$.ajax({type:'GET',url:getPath(jssrc,src),async:false,dataType:'script'});
}
}

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

多請求的問題
  使用上面的include看上去挺爽的,不過卻帶來另外1個嚴重的問題,就是多發送了1個ajax的請求。
  我們常常為了WEB效能,而合并js,減少請求。但使用include後卻偏偏多了請求。如果這個問題不解決,相信很多人都不會在正式產品中使用include的了,除非是區域網路產品。

  如何解決這個多請求的問題,我也思考很久,最後覺的單單使用用戶端js是沒辦法解決了。所以就想到了使用服務端代碼來解決
  還記的我之前有文章介紹 "js、css的合并、壓縮、緩衝管理"的時候,就通過伺服器端代碼在程式啟動時候去合并js。

  所以我把include多請求的解決方案也加到裡面去。就是在程式啟動的時候去尋找所有的js,發現有使用include的就把include中common.js的原始碼替換該include函數。這樣a.js中在啟動並執行時候就沒有include函數,而是真真包含了common.js的內容的js檔案

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

  個人覺得,每個產品都應該要區分開發環境和產品環境(一般通過設定檔進行區分),在開發環境應該以開發效率為首要,而產品環境則以效能為首。所以這裡的inlcude就應該要區分對待,在開發環境中使用js include來提高開發和維護效率,而在產品環境中則自動把所有include替換成真真的js檔案的內容。
[作者]:BearRui(AK-47)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.