Hank Lin

A new blog

JavaScript的處理方式

| Comments

每個原始檔要先最小化,然後依照引用的順序合併。檔名可以在佈署時動態產生,常用的選擇有亂數、佈署版本的號碼或名稱、最後修改的檔案時間戳記、或可閱讀的曰期時間字串。

每個頁面所引用的JavaScript檔,組合會有很多種。所以對整個網站考量時,就有幾種合併的作法,以下是比較常用的。

  • 整個網站用到的所有JavaScript,都合併成一個檔案

    適合所有頁面引用的JavaScript,組合並不多時。並且引用的順序都一樣,也就是順序不影響的時候。這種作法當然網站速度最快,但是常常每個頁面引用的JavaScript,都有不同。而且有些JavaScript檔案,只在一、二個網頁被引用到,這個比例高的話,就變成每一頁都還要引用原本只需要在那一個網頁要讀取的JavaScript。有一些這類的JavaScript函式庫還滿大的,例如所見即所得編輯器(WYSIWYG),所以實務上不見得是最適合的作法。
  • 將所有頁面,或是超過一半的頁面,都有引用到的JavaScript,合併成一個檔案

    這個JavaScript會被全部的網頁所引用,然後每個網頁再各自去合併自已的專屬JavaScript檔案。也就是變成一個是整個網站都用到的合併檔,另一個是這個網頁用到的合併檔。這樣的作法,會減少單一頁面的傳輸量,不至於包含了過多沒有用到的JavaScript檔案,但是至少會有兩次的JavaScript請求。適合每個網頁所引用的JavaScript很分歧,而且檔案又不算小的時候。這也是一般常見的情況。
  • 每一個網頁各自合併自己引用的檔案

    這樣每個網頁只會有一個JavaScript請求,而且不會有多餘的內容,也容許相同組合的JavaScript以不同順序引用。缺點就是你可能需要把JavaScript合併成多種組合,最多到和網頁數一樣多。如果在各網頁間,引用相同的JavaScrip檔案數量很少時,就適合用這個作法。其實這個作法不用管理”共同的”及”各別的”JavaScript檔案,是我比較喜歡的作法。

合併完成後,再來就是要最小化(minify)。JavaScript很適合最小化,可以用語法解析器(parser)檢查,並把不需要的空白去掉。例如使用rhino、jslint。

在合併完後,尤其是最小化之後,JavaScript原始檔會變得完全不能由人去編輯,所以合併及最小化的工作必須在佈署時期,由工具幫我們作。最好是命令列的工具,可以整合進專案的自動管理流程。 如果原本的一個JavaScript檔案,被合併到多個合併後的檔案。那麼,即使你只改了原始檔的一個字,所有合併後的檔案,都要重新產生,使用者也應該重新下載。 這裡可能有二個問題:

  • 我們有設定快取標頭,如何通知使用者(瀏覽器)下載新的合併檔?
  • 只改一個檔案的一個字,就要使用者重新下載合併的檔案,會不會影響速度?

第一個問題,只要改變下載合併檔的URL,下次使用者到這個網頁,就會重新下載這個合併檔。麻煩的地方在於,我們要把所有修改過的合併檔,傳到伺服器上。也就是說,一定要再走一次佈署流程,把所有合併檔都產生好,再佈署上去,即使有工具幫我們作,負擔也是不小,過程也很多地方可能會出錯。所以使用「lazy initialization」,在伺服器端作「合併」、「最小化」的工作,也是一個不錯的方法。 第二個問題,我認為影響不大。因為我們的目標是,即使客戶端完全沒有快取,也要能很快的顯示網頁。以每一個網頁只使用一到兩個

我們常常需要在我們的網站上,引用第三方的JavaScript函式庫,如社羣網站API、測量工具、或廣告商等。以前通常會對放置JavaScript的區塊作限制,甚至要求要用document.write()的語法,對我們網站的效能造成嚴重的限制。我真的不希望使用者看我的網頁,要先等廣告render好,才出現真正的內容。尤其是JavaScript的請求會擋住(block)網頁的render,如果第三方的網站回應較慢,還會連累我們的網站,讓使用者等半天,只看到白畫面。 還好,現在比較大的第三方JavaScript函式庫,都支援了非同步的JavaScript使用法。所以我們也要把這些JavaScript,在HTML文件和資源都準備好(onload)之後,再去呼叫初始化。初始化的步驟通常是用JavaScript插入一段引用第三方JavaScript函式庫的

inline又分成兩種,一種是寫在靜態HTML裡,如果量不多倒是還好。另一種是隨著伺服器端腳本(server side script)或範本(template)工具動態產生的HTML寫出去的。

這兩種作法都會造成許多管理、開發、和優化的麻煩,所以要從一開始就要儘量避免。

如果要最小化這些源始碼,必須先把inline的一段段

這種程式碼是很難進行自動化優化的,而且維護成本非常高,無論如何你都應該避免這種寫法。