日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JSP 性能优化

發布時間:2025/5/22 javascript 79 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JSP 性能优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

無論當前 JavaScript 代碼是內嵌還是在外鏈文件中,頁面的下載和渲染都必須停下來等待腳本執行完成。JavaScript 執行過程耗時越久,瀏覽器等待響應用戶輸入的時間就越長。瀏覽器在下載和執行腳本時出現阻塞的原因在于,腳本可能會改變頁面或 JavaScript 的命名空間,它們對后面頁面內容造成影響。一個典型的例子就是在頁面中使用document.write()。例如清單 1
清單 1 JavaScript 代碼內嵌示例

  • <html>?
  • <head>?
  • ????<title>Source?Example</title>?
  • </head>?
  • <body>?
  • ????<p>?
  • ????<script?type="text/javascript">?
  • ????????document.write("Today?is?"?+?(new?Date()).toDateString());?
  • ????</script>?
  • ????</p>?
  • </body>?
  • </html>?
  • 當瀏覽器遇到<script>標簽時,當前?HTML?頁面無從獲知?JavaScript?是否會向<p>?標簽添加內容,或引入其他元素,或甚至移除該標簽。因此,這時瀏覽器會停止處理頁面,先執行?JavaScript代碼,然后再繼續解析和渲染頁面。同樣的情況也發生在使用?src?屬性加載?JavaScript的過程中,瀏覽器必須先花時間下載外鏈文件中的代碼,然后解析并執行它。在這個過程中,頁面渲染和用戶交互完全被阻塞了。

    腳本位置

    HTML 4 規范指出?<script>?標簽可以放在 HTML 文檔的<head>或<body>中,并允許出現多次。Web 開發人員一般習慣在?<head>?中加載外鏈的 JavaScript,接著用?<link>?標簽用來加載外鏈的 CSS 文件或者其他頁面信息。例如清單 2

    清單 2 低效率腳本位置示例

  • <html>?
  • <head>?
  • ????<title>Source?Example</title>?
  • ????<script?type="text/javascript"?src="script1.js"></script>?
  • ????<script?type="text/javascript"?src="script2.js"></script>?
  • ????<script?type="text/javascript"?src="script3.js"></script>?
  • ????<link?rel="stylesheet"?type="text/css"?href="styles.css">?
  • </head>?
  • <body>?
  • ????<p>Hello?world!</p>?
  • </body>?
  • </html>?
  • 然而這種常規的做法卻隱藏著嚴重的性能問題。在清單 2 的示例中,當瀏覽器解析到?<script>?標簽(第 4 行)時,瀏覽器會停止解析其后的內容,而優先下載腳本文件,并執行其中的代碼,這意味著,其后的 styles.css 樣式文件和<body>標簽都無法被加載,由于<body>標簽無法被加載,那么頁面自然就無法渲染了。因此在該 JavaScript 代碼完全執行完之前,頁面都是一片空白。圖 1 描述了頁面加載過程中腳本和樣式文件的下載過程。

    圖 1 JavaScript 文件的加載和執行阻塞其他文件的下載

    ?

    我們可以發現一個有趣的現象:第一個 JavaScript 文件開始下載,與此同時阻塞了頁面其他文件的下載。此外,從 script1.js 下載完成到 script2.js 開始下載前存在一個延時,這段時間正好是 script1.js 文件的執行過程。每個文件必須等到前一個文件下載并執行完成才會開始下載。在這些文件逐個下載過程中,用戶看到的是一片空白的頁面。

    從 IE 8、Firefox 3.5、Safari 4 和 Chrome 2 開始都允許并行下載 JavaScript 文件。這是個好消息,因為<script>標簽在下載外部資源時不會阻塞其他<script>標簽。遺憾的是,JavaScript 下載過程仍然會阻塞其他資源的下載,比如樣式文件和圖片。盡管腳本的下載過程不會互相影響,但頁面仍然必須等待所有 JavaScript 代碼下載并執行完成才能繼續。因此,盡管最新的瀏覽器通過允許并行下載提高了性能,但問題尚未完全解決,腳本阻塞仍然是一個問題。

    由于腳本會阻塞頁面其他資源的下載,因此推薦將所有<script>標簽盡可能放到<body>標簽的底部,以盡量減少對整個頁面下載的影響。例如清單 3

    清單 3 推薦的代碼放置位置示例

  • <html>?
  • <head>?
  • ????<title>Source?Example</title>?
  • ????<link?rel="stylesheet"?type="text/css"?href="styles.css">?
  • </head>?
  • <body>?
  • ????<p>Hello?world!</p>?
  • ??
  • ????<!--?Example?of?efficient?script?positioning?-->?
  • ????<script?type="text/javascript"?src="script1.js"></script>?
  • ????<script?type="text/javascript"?src="script2.js"></script>?
  • ????<script?type="text/javascript"?src="script3.js"></script>?
  • </body>?
  • </html>?
  • 這段代碼展示了在 HTML 文檔中放置<script>標簽的推薦位置。盡管腳本下載會阻塞另一個腳本,但是頁面的大部分內容都已經下載完成并顯示給了用戶,因此頁面下載不會顯得太慢。這是優化 JavaScript 的首要規則:將腳本放在底部。

    組織腳本

    由于每個<script>標簽初始下載時都會阻塞頁面渲染,所以減少頁面包含的<script>標簽數量有助于改善這一情況。這不僅針對外鏈腳本,內嵌腳本的數量同樣也要限制。瀏覽器在解析 HTML 頁面的過程中每遇到一個<script>標簽,都會因執行腳本而導致一定的延時,因此最小化延遲時間將會明顯改善頁面的總體性能。

    這個問題在處理外鏈 JavaScript 文件時略有不同。考慮到 HTTP 請求會帶來額外的性能開銷,因此下載單個 100Kb 的文件將比下載 5 個 20Kb 的文件更快。也就是說,減少頁面中外鏈腳本的數量將會改善性能。

    通常一個大型網站或應用需要依賴數個 JavaScript 文件。您可以把多個文件合并成一個,這樣只需要引用一個<script>標簽,就可以減少性能消耗。文件合并的工作可通過離線的打包工具或者一些實時的在線服務來實現。

    需要特別提醒的是,把一段內嵌腳本放在引用外鏈樣式表的<link>之后會導致頁面阻塞去等待樣式表的下載。這樣做是為了確保內嵌腳本在執行時能獲得最精確的樣式信息。因此,建議不要把內嵌腳本緊跟在<link>標簽后面。

    無阻塞的腳本

    減少 JavaScript 文件大小并限制 HTTP 請求數在功能豐富的 Web 應用或大型網站上并不總是可行。Web 應用的功能越豐富,所需要的 JavaScript 代碼就越多,盡管下載單個較大的 JavaScript 文件只產生一次 HTTP 請求,卻會鎖死瀏覽器的一大段時間。為避免這種情況,需要通過一些特定的技術向頁面中逐步加載 JavaScript 文件,這樣做在某種程度上來說不會阻塞瀏覽器。

    無阻塞腳本的秘訣在于,在頁面加載完成后才加載 JavaScript 代碼。這就意味著在?window?對象的?onload事件觸發后再下載腳本。有多種方式可以實現這一效果。

    延遲加載腳本

    HTML 4 為<script>標簽定義了一個擴展屬性:defer。Defer?屬性指明本元素所含的腳本不會修改 DOM,因此代碼能安全地延遲執行。defer?屬性只被 IE 4 和 Firefox 3.5 更高版本的瀏覽器所支持,所以它不是一個理想的跨瀏覽器解決方案。在其他瀏覽器中,defer?屬性會被直接忽略,因此<script>標簽會以默認的方式處理,也就是說會造成阻塞。然而,如果您的目標瀏覽器支持的話,這仍然是個有用的解決方案。清單 4 是一個例子

    ?

    清單 4 defer 屬性使用方法示例

  • <script?type="text/javascript"?src="script1.js"?defer></script>?
  • 帶有?defer?屬性的<script>標簽可以放置在文檔的任何位置。對應的 JavaScript 文件將在頁面解析到<script>標簽時開始下載,但不會執行,直到 DOM 加載完成,即onload事件觸發前才會被執行。當一個帶有?defer?屬性的 JavaScript 文件下載時,它不會阻塞瀏覽器的其他進程,因此這類文件可以與其他資源文件一起并行下載。

    任何帶有?defer?屬性的<script>元素在 DOM 完成加載之前都不會被執行,無論內嵌或者是外鏈腳本都是如此。清單 5 的例子展示了defer屬性如何影響腳本行為:

    清單 5 defer 屬性對腳本行為的影響

  • <html>?
  • <head>?
  • ????<title>Script?Defer?Example</title>?
  • </head>?
  • <body>?
  • ????<script?type="text/javascript"?defer>?
  • ????????alert("defer");?
  • ????</script>?
  • ????<script?type="text/javascript">?
  • ????????alert("script");?
  • ????</script>?
  • ????<script?type="text/javascript">?
  • ????????window.onload?=?function(){?
  • ????????????alert("load");?
  • ????????};?
  • ????</script>?
  • </body>?
  • </html>?
  • ?

    這段代碼在頁面處理過程中彈出三次對話框。不支持?defer?屬性的瀏覽器的彈出順序是:“defer”、“script”、“load”。而在支持?defer屬性的瀏覽器上,彈出的順序則是:“script”、“defer”、“load”。請注意,帶有?defer?屬性的<script>元素不是跟在第二個后面執行,而是在?onload?事件被觸發前被調用。

    如果您的目標瀏覽器只包括 Internet Explorer 和 Firefox 3.5,那么?defer?腳本確實有用。如果您需要支持跨領域的多種瀏覽器,那么還有更一致的實現方式。

    HTML 5 為<script>標簽定義了一個新的擴展屬性:async。它的作用和?defer?一樣,能夠異步地加載和執行腳本,不因為加載腳本而阻塞頁面的加載。但是有一點需要注意,在有?async?的情況下,JavaScript 腳本一旦下載好了就會執行,所以很有可能不是按照原本的順序來執行的。如果 JavaScript 腳本前后有依賴性,使用?async?就很有可能出現錯誤。

    動態腳本元素

    文檔對象模型(DOM)允許您使用 JavaScript 動態創建 HTML 的幾乎全部文檔內容。<script>元素與頁面其他元素一樣,可以非常容易地通過標準 DOM 函數創建:

    清單 6 通過標準 DOM 函數創建<script>元素

  • var?script?=?document.createElement?("script");?
  • ???script.type?=?"text/javascript";?
  • ???script.src?=?"script1.js";?
  • ???document.getElementsByTagName("head")[0].appendChild(script);?
  • ?

    新的<script>元素加載 script1.js 源文件。此文件當元素添加到頁面之后立刻開始下載。此技術的重點在于:無論在何處啟動下載,文件的下載和運行都不會阻塞其他頁面處理過程。您甚至可以將這些代碼放在<head>部分而不會對其余部分的頁面代碼造成影響(除了用于下載文件的 HTTP 連接)。

    當文件使用動態腳本節點下載時,返回的代碼通常立即執行(除了 Firefox 和 Opera,他們將等待此前的所有動態腳本節點執行完畢)。當腳本是“自運行”類型時,這一機制運行正常,但是如果腳本只包含供頁面其他腳本調用調用的接口,則會帶來問題。這種情況下,您需要跟蹤腳本下載完成并是否準備妥善??梢允褂脛討B?<script>?節點發出事件得到相關信息。

    Firefox、Opera, Chorme 和 Safari 3+會在<script>節點接收完成之后發出一個?onload?事件。您可以監聽這一事件,以得到腳本準備好的通知:

    清單 7 通過監聽 onload 事件加載 JavaScript 腳本

  • var?script?=?document.createElement?("script")?
  • script.type?=?"text/javascript";?
  • ??
  • //Firefox,?Opera,?Chrome,?Safari?3+?
  • script.onload?=?function(){?
  • ????alert("Script?loaded!");?
  • };?
  • ??
  • script.src?=?"script1.js";?
  • document.getElementsByTagName("head")[0].appendChild(script);?
  • Internet Explorer 支持另一種實現方式,它發出一個?readystatechange?事件。<script>元素有一個?readyState?屬性,它的值隨著下載外部文件的過程而改變。readyState?有五種取值:

    • “uninitialized”:默認狀態
    • “loading”:下載開始
    • “loaded”:下載完成
    • “interactive”:下載完成但尚不可用
    • “complete”:所有數據已經準備好

    微軟文檔上說,在<script>元素的生命周期中,readyState?的這些取值不一定全部出現,但并沒有指出哪些取值總會被用到。實踐中,我們最感興趣的是“loaded”和“complete”狀態。Internet Explorer 對這兩個?readyState?值所表示的最終狀態并不一致,有時<script>元素會得到“loader”卻從不出現“complete”,但另外一些情況下出現“complete”而用不到“loaded”。最安全的辦法就是在readystatechange?事件中檢查這兩種狀態,并且當其中一種狀態出現時,刪除?readystatechange?事件句柄(保證事件不會被處理兩次):

    清單 8 通過檢查 readyState 狀態加載 JavaScript 腳本

  • var?script?=?document.createElement("script")?
  • script.type?=?"text/javascript";?
  • ??
  • //Internet?Explorer?
  • script.onreadystatechange?=?function(){?
  • ?????if?(script.readyState?==?"loaded"?||?script.readyState?==?"complete"){?
  • ???????????script.onreadystatechange?=?null;?
  • ???????????alert("Script?loaded.");?
  • ?????}?
  • };?
  • ??
  • script.src?=?"script1.js";?
  • document.getElementsByTagName("head")[0].appendChild(script);?
  • 大多數情況下,您希望調用一個函數就可以實現 JavaScript 文件的動態加載。下面的函數封裝了標準實現和 IE 實現所需的功能:

    清單 9 通過函數進行封裝

  • function?loadScript(url,?callback){?
  • ????var?script?=?document.createElement?("script")?
  • ????script.type?=?"text/javascript";?
  • ????if?(script.readyState){?//IE?
  • ????????script.onreadystatechange?=?function(){?
  • ????????????if?(script.readyState?==?"loaded"?||?script.readyState?==?"complete"){?
  • ????????????????script.onreadystatechange?=?null;?
  • ????????????????callback();?
  • ????????????}?
  • ????????};?
  • ????}?else?{?//Others?
  • ????????script.onload?=?function(){?
  • ????????????callback();?
  • ????????};?
  • ????}?
  • ????script.src?=?url;?
  • ????document.getElementsByTagName("head")[0].appendChild(script);?
  • }?
  • 此函數接收兩個參數:JavaScript 文件的 URL,和一個當 JavaScript 接收完成時觸發的回調函數。屬性檢查用于決定監視哪種事件。最后一步,設置?src?屬性,并將<script>元素添加至頁面。此?loadScript()?函數使用方法如下:

    清單 10 loadScript()函數使用方法

  • loadScript("script1.js",?function(){?
  • ????alert("File?is?loaded!");?
  • });?
  • 您可以在頁面中動態加載很多 JavaScript 文件,但要注意,瀏覽器不保證文件加載的順序。所有主流瀏覽器之中,只有 Firefox 和 Opera 保證腳本按照您指定的順序執行。其他瀏覽器將按照服務器返回它們的次序下載并運行不同的代碼文件。您可以將下載操作串聯在一起以保證他們的次序,如下:

    清單 11 通過 loadScript()函數加載多個 JavaScript 腳本

  • loadScript("script1.js",?function(){?
  • ????loadScript("script2.js",?function(){?
  • ????????loadScript("script3.js",?function(){?
  • ????????????alert("All?files?are?loaded!");?
  • ????????});?
  • ????});?
  • });?
  • ?

    此代碼等待 script1.js 可用之后才開始加載 script2.js,等 script2.js 可用之后才開始加載 script3.js。雖然此方法可行,但如果要下載和執行的文件很多,還是有些麻煩。如果多個文件的次序十分重要,更好的辦法是將這些文件按照正確的次序連接成一個文件。獨立文件可以一次性下載所有代碼(由于這是異步進行的,使用一個大文件并沒有什么損失)。

    動態腳本加載是非阻塞 JavaScript 下載中最常用的模式,因為它可以跨瀏覽器,而且簡單易用。

    使用 XMLHttpRequest(XHR)對象

    此技術首先創建一個 XHR 對象,然后下載 JavaScript 文件,接著用一個動態?<script>?元素將 JavaScript 代碼注入頁面。清單 12 是一個簡單的例子:

    清單 12 通過 XHR 對象加載 JavaScript 腳本

  • var?xhr?=?new?XMLHttpRequest();?
  • xhr.open("get",?"script1.js",?true);?
  • xhr.onreadystatechange?=?function(){?
  • ????if?(xhr.readyState?==?4){?
  • ????????if?(xhr.status?>=?200?&&?xhr.status?<?300?||?xhr.status?==?304){?
  • ????????????var?script?=?document.createElement?("script");?
  • ????????????script.type?=?"text/javascript";?
  • ????????????script.text?=?xhr.responseText;?
  • ????????????document.body.appendChild(script);?
  • ????????}?
  • ????}?
  • };?
  • xhr.send(null);?
  • ?

    此代碼向服務器發送一個獲取 script1.js 文件的 GET 請求。onreadystatechange?事件處理函數檢查?readyState?是不是 4,然后檢查 HTTP 狀態碼是不是有效(2XX 表示有效的回應,304 表示一個緩存響應)。如果收到了一個有效的響應,那么就創建一個新的<script>元素,將它的文本屬性設置為從服務器接收到的?responseText?字符串。這樣做實際上會創建一個帶有內聯代碼的<script>元素。一旦新<script>元素被添加到文檔,代碼將被執行,并準備使用。

    這種方法的主要優點是,您可以下載不立即執行的 JavaScript 代碼。由于代碼返回在<script>標簽之外(換句話說不受<script>標簽約束),它下載后不會自動執行,這使得您可以推遲執行,直到一切都準備好了。另一個優點是,同樣的代碼在所有現代瀏覽器中都不會引發異常。

    此方法最主要的限制是:JavaScript 文件必須與頁面放置在同一個域內,不能從 CDN 下載(CDN 指”內容投遞網絡(Content Delivery Network)”,所以大型網頁通常不采用 XHR 腳本注入技術。

    總結

    減少 JavaScript 對性能的影響有以下幾種方法:

    • 將所有的<script>標簽放到頁面底部,也就是</body>閉合標簽之前,這能確保在腳本執行前頁面已經完成了渲染。
    • 盡可能地合并腳本。頁面中的<script>標簽越少,加載也就越快,響應也越迅速。無論是外鏈腳本還是內嵌腳本都是如此。
    • 采用無阻塞下載 JavaScript 腳本的方法:
      • 使用<script>標簽的 defer 屬性(僅適用于 IE 和 Firefox 3.5 以上版本);
      • 使用動態創建的<script>元素來下載并執行代碼;
      • 使用 XHR 對象下載 JavaScript 代碼并注入頁面中。

    通過以上策略,可以在很大程度上提高那些需要使用大量 JavaScript 的 Web 網站和應用的實際性能。

    ?

    ?

    原文鏈接地址:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/index.html

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的JSP 性能优化的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。