僅僅一行 JavaScript 代碼就能給現(xiàn)今的許多網(wǎng)絡日志[1]技術提供動力 -- JavaScript 小應用[2]、共享工具、訪問者跟蹤、廣告客戶。在很多時候,一個網(wǎng)志作者所需要的僅僅是一行 JavaScript 代碼,用來給自己的網(wǎng)志增加一個新的技術。現(xiàn)在的問題是,假如許多這樣的代碼累積起來,事情會變成怎樣的呢?
物理學上有一個著名的現(xiàn)象叫做“非線性”:大量不同的個體相互作用將產(chǎn)生難以預知的結果。在這一點上,軟件也一樣 -- 當許多組件被放在一起,就無法知道接下來會發(fā)生什么。這是因為,各個組件工作時都當其他組件不存在,實際上,它們正在爭奪實實在在的資源和人們的關注。事實是:這場戰(zhàn)爭傷害了所有的人 -- 讀者、網(wǎng)志作者,以及網(wǎng)絡服務本身。每個人都體會到了挫折感。
在這個帖子里,我們將了解是什么使得頁面因為過多的 JavaScript 語句而遲滯,以及對此應該采取什么對策。
網(wǎng)志作者 - 意料之外的受害者
在網(wǎng)志作者這里存在下來的是新的單調(diào)的、微塊化[3]的內(nèi)容。網(wǎng)志作者熱愛在他們的網(wǎng)址上展示個性和喜愛的內(nèi)容。這也是為什么人們急著要安裝新的 JavaScript 小應用(例如:來自于del.icio.us,F(xiàn)lickr,Twitter,AddThis,Sphere的 JavaScript 小應用)的原因 -- 因為它們確實有用,而且對于它們有著旺盛的需求。
如果你熟悉 HTML 和你所使用的網(wǎng)志平臺的話,安裝 JavaScript 小應用是一項相當容易的工作。你所要做的只是將代表 JavaScript 小應用的 HTML 代碼粘貼到你想要放置它的位置。有的時候需要把代碼放到 HTML 文檔的頭部(header),這樣做也并不困難。如果你對技術有一定的了解,你就可以這樣做,或者通過一個類似于 Widgetbox 的平臺自動安裝所需的 JavaScript 小應用。
這樣作很容易,因此人們正在往他們的網(wǎng)志里塞入越來越多的 JavaScript 小應用;就是從這時起,一切開始變得讓人不那么愉快 -- 例如:載入網(wǎng)志頁面所需的時間越來越長。
不是所有網(wǎng)頁小應用都生而相同
現(xiàn)在有兩種實現(xiàn)網(wǎng)頁小應用的主要技術:Flash 和 JavaScript。Flash 小應用有它們自己的問題:太重量級、不能改變大小、不能操縱 DOM(文檔對象模型)。然而,問題通常卻并不是 Flash 小應用帶來的,而是 JavaScript 小應用。
具有諷刺意味的是,JavaScript 一開始就被想象和設計成客戶端的一種支持最小交互性和能夠迅速操縱 DOM 的輕量級語言。但我們的技術帶領我們走上了一條扭曲的發(fā)展道路,結果是 JavaScript 逐漸成長為一種網(wǎng)絡編程語言。 從 Ajax 到 JavaScript 小應用,JavaScript 如今被用于許多前沿項目。但事實是:JavaScript 有自己的問題。接下來讓我們看一下都有那些...
瀏覽器如何處理 JavaScript 代碼
對于任何一個老練的技術人員來說,也許最令人震驚的真相是:JavaScript 是一個單線程語言。這譯為著 JavaScript 代碼是順序而不是并行執(zhí)行(除了 Ajax 調(diào)用的例外情況)。當一段 JavaScript 代碼正在被加載和求值時,其他所有代碼都必須等待。
這同時也意味著,一段執(zhí)行速度很慢的 JavaScript 代碼會使整個網(wǎng)志的加載速度變慢。這就是正在網(wǎng)志世界里發(fā)生的事情。那么,怎么解決這個問題呢?
JavaScript 小應用能做到更好更快嗎?
很不幸,對于這個問題不存在什么萬試萬靈的解決辦法。也就是說不存在一種單一的技巧或技術能夠解決這個問題。雖然企業(yè)能夠通過組合一些方法去減輕使用其他 JavaScript 小應用造成的影響,最終 -- 如果使用的 JavaScript 小應用足夠多的話 -- 問題還是必定出現(xiàn)。當我們作為一個行業(yè)在仔細考慮能夠做些什么的時候,JavaScript 提供者應該思考以下一些指導性原則:
1. 推遲 JavaScript 代碼的執(zhí)行
一個經(jīng)常被提到的問題是,所喲iud JavaScript 代碼都應該在頁面載入時立即執(zhí)行,但實際可以不這樣做。假如一段代碼不需要在頁面載入時修改頁面內(nèi)容,那么這段代碼應該被推遲到頁面載入后 執(zhí)行(使用 script 標簽的 defer 屬性)。這樣做,頁面的內(nèi)容就會先顯示出來。不走運的是,不是所有的瀏覽器都會遵守這個延遲的命令。
2. 盡量減少頁面載入時需要執(zhí)行的代碼總量
在頁面載入的同時執(zhí)行的代碼,無一例外都會延緩頁面的載入。這種情況下需要運行的代碼越少越好。另一個有關的問題是遍歷整個頁面尋找某些特定的東西。這是一個應該絕對避免的做法,因為這樣做會導致瀏覽器彈出 ”腳本停止響應“ 的對話框。一般來說,運行時間超過一定時間(通常是5秒鐘)的 JavaScript 代碼會產(chǎn)生這個問題。一個適當(也很痛苦)的解決方案是:使用定時機制 來分割一個較長的執(zhí)行過程。
3. 通過生成不同的 URL 對請求做負載均衡
大多數(shù) JavaScript 代碼只提供同一個 URL,例如:www.mycoolwidget.com。這樣做不利于系統(tǒng)伸縮(scale)。JavaScript 小應用使用得越廣泛,同一個服務器接受到的并發(fā)請求的數(shù)目就越多。一個更好的嘗試是使用不同的 URL,例如像這樣:server1.mycoolwidget.com,server2.mycoolwidget.com,等等。當前可以暫時把所有這些 URL 指向同一個域,作為未來分流流量的一個可以選擇的后備方案。
4. 使用標準庫
因為編寫 JavaScript 代碼容易出錯,所以重復發(fā)明輪子(reinventing the wheel)的嘗試可能是最糟糕的一種做法。JavaScript 與 Java 不同,沒有所謂的標準庫,但某些庫(比如:prototype )正在變成事實上的標準。這些庫由富有經(jīng)驗、了解系統(tǒng)特性的開發(fā)者編寫,重用他們的代碼是一個理想的選擇。
5. 最要重要的是要考慮到別人
要認識到在最終用戶的網(wǎng)站上還運行著其他的 JavaScript 代碼,這是最要緊的事情。腦袋里有了 “我是一個系統(tǒng)的一部分” 的想法,開發(fā)者就能夠在最大程度上避免破壞其他 JavaScript 小應用的正常運行,從而帶來全面、流暢的用戶體驗。
從現(xiàn)在起能做些什么?
做一個良好 JavaScript 公民是受到鼓勵的行為,然而,開發(fā)者還可以做得更多。作為開發(fā)者,你不能預測你的 JavaScript 小應用會在哪里、會被怎樣使用,以及除了你的 JavaScript 小應用之外還安裝了什么東西。不了解這些,就無法對代碼做進一步的性能調(diào)整。而不好的結果卻要讓網(wǎng)志作者和網(wǎng)志讀者來承擔。那么我們要怎么做呢?
如果我們將目光投向 Java 社區(qū),就會看到這個問題已經(jīng)被解決了許多次。Applet、Servlet 甚至 EJB 在概念上和 JavaScript 小應用都沒有什么本質(zhì)的不同。最主要的差別在于Applet、Servlet 、EJB都被容器管理。
容器是一種寄存環(huán)境,提供傳送基礎設施和通信界面。容器處理載入、卸載、回調(diào)、點擊、消息等等所有這些工程師熱愛而非技術人士害怕聽到的東西。簡而言之,我們需要 JavaScript 的容器,從而給混亂的組件帶來秩序。
結論
JavaScript 小應用和 JavaScript 工具看起來確實很酷,也很有用,但現(xiàn)在還沒有合適的基礎設施能夠保證讓它們好好工作。網(wǎng)志載入越來越慢的初始癥狀現(xiàn)在已經(jīng)出現(xiàn),隨著更多的 JavaScript 小應用和 JavaScript 代碼進入網(wǎng)志的世界,情況會變得更糟。而要求網(wǎng)志作者去理解組合使用 JavaScript 小應用帶來的復雜性、相互依賴性等問題顯然并不合適。
我們需要自動化、標準化的方法傳送 JavaScript 小應用。我們應該在觀念上學習軟件行業(yè)中已經(jīng)成功的做法。Java 社區(qū)已經(jīng)取得了巨大的成功,充分利用他們?nèi)〉玫慕?jīng)驗對于剛起步的 JavaScript 小應用開發(fā)企業(yè)來說有著重要的意義。
和往常一樣,請告訴我們你的想法。如果你是一個 JavaScript 小應用開發(fā)者,我們很想知道你如何優(yōu)化你的代碼使之對環(huán)境更友好、運行得更快。
Blog 統(tǒng)一譯為 網(wǎng)絡日志/網(wǎng)志。
Widget 統(tǒng)一譯為 JavaScript 小應用。
微塊化(microchunking)就是把原來不可分割、渾然一體的產(chǎn)品,區(qū)分成通用的模塊和特殊的模塊,或者可以自由組合的模塊,最后根據(jù)需求的不同,進行不同的排列組合。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1754993