about 5 years ago

前面的章節皆在探討 JavaScript 核心,與執行環境無關;本篇則著重於 browser 上的相關 pattern。

Separation of Concerns

  • Concerns 有三:
    1. Context:文件內容,即 HTML
    2. Presentation:外觀表現,即 CSS
    3. Behavior:使用者互動或文件動態改變,即 JavaScript
  • 當關閉 CSS 或 JavaScript 時,應確保頁面仍可正常閱讀,且主要功能仍可正常運作
  • 避免將 CSS 或 JavaScript 內嵌在 context 中
  • 應直接檢測明確的 method 或 property,避免使用 user agent sniffing

DOM Scripting

  • 避免在 loop 中存取 DOM,應 assign 其 reference 給 local variable
  • 盡量使用 selector API(如 document.querySelector()document.querySelectorAll()),而 id="" 是尋找節點最快的方式(document.getElementById()
  • 更新 DOM 會使 browser 進行 repain(重新繪製畫面)及 reflow(重新計算元素的幾何結構),因此應在 "live" DOM tree 之外進行操作(如:新增時先用 document fragment 容納所有節點,待一連串的動作完成後再將這個已定案的 fragment 加至 DOM;修改時則可先在 clone 中處理,完成後再替換原本的節點)

Events

  • 使用 addEventListener()/attachEvent() 時,適時加上 stopPropagation()/cancelBubble=truepreventDefault()/returnValue=false
  • 利用 event delegation 減少 event listeners 的總量(如 div 內有十個 button,可在 div 上加一個 listener 就好而不是在每一個 button 都加)

Long-Running Scripts

  • JavaScript 中雖沒有 thread,但可藉由 setTimeOut() 模擬,或使用較新的 browser 所支援的 Web Workers,以避免因 lag 而使 user 不能操作畫面

Remote Scripting

  • XMLHttpRequest (AJAX)
  • JSONP (for cross-domain)
  • iframe
  • image beacon(只需送 request 不需接 response 時可用,response 傳 HTTP 204 為佳)

Deploying JavaScript

  • 合併 scripts 以減少 HTTP request,可用 cat 命令操作
  • 使用 minify 工具壓縮,縮小檔案大小
  • 開啟 gzip 壓縮,增快載入速度
    .htaccess
    AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml application/javascript application/json
    
  • 使用 Expires header,增加檔案待在 cache 的機會
    .htaccess
    ExpiresActive On
    ExpiresByType application/x-javascript "access plus 10 years"
    
  • 使用 CDN,讓各地 user 可更快速存取檔案

Loading Strategies

  • <script> 的 attribute 不要加上 languagetype 等歷史遺跡,可加 defer 或 HTML5 的 async 使其不會 block 網頁的下載流程(browser 會同時下載多個檔案,但遇到外部 script 會暫停下一步下載直到該 script 完成下載並分析與執行完畢);async 尚未廣泛支援,因此可將外部 script 放置頁面底端(</body> 前),或動態加入 <script> 元素實現 asyncronous 下載(document.createElement("script")),後者需注意各 script 檔之間的相依性(因各檔案下載完成的時機未必如同預期順序)
  • 當頁面需在 server-side 進行複雜運算時,可使用 chunked encoding 分批傳送頁面片段,利用 server 尚未完成工作時先將部分靜態內容送給 client-side
Strategy of Loading a Big Script
  • lazy loading:先載入 core 使主要功能開始運作,再用 onload 動態加 <script> 載入其他次要功能(如特效、XHR 實作等)
  • loading on demand:需要時才載入,並在完成後執行 callback
    require("extra.js", function () {
        functionDefinedInExtraJS();
    });
    function require(file, callback) {
        var script = document.getElementsByTagName('script')[0],
        newjs = document.createElement('script');
        // IE
        newjs.onreadystatechange = function () {
                if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') {
                        newjs.onreadystatechange = null;
                        callback();
                }
        };
        // others
        newjs.onload = function () {
                callback();
        };
        newjs.src = file;
        script.parentNode.insertBefore(newjs, script);
    }
    
  • preloading:若希望單純只下載 script 檔案而不進行分析及執行,IE 可用 image beacon,其他 browser 可用 <object> 替代 <script>
← JavaScript Patterns 閱讀筆記 (7) Design Patterns CSS3 學習筆記 →
 
comments powered by Disqus