library - javascript動畫教學




建議在JavaScript無效之前包含CSS嗎? (9)

Personally, I would not place too much emphasis on such "folk wisdom." What may have been true in the past might well not be true now. I would assume that all of the operations relating to a web-page's interpretation and rendering are fully asynchronous ("fetching" something and "acting upon it" are two entirely different things that might be being handled by different threads, etc. ), and in any case entirely beyond your control or your concern.

I'd put CSS references in the "head" portion of the document, along with any references to external scripts. (Some scripts may demand to be placed in the body, and if so, oblige them.)

除此之外......如果你觀察到“這看起來比這更快/更慢,在這個/那個瀏覽器上,”把這個觀察看作是一個有趣但不相干的好奇心,不要讓它影響你的設計決策。太多事情變化太快。(任何人都希望在Firefox團隊發布其產品的另一個臨時版本之前多少分鐘內下注?Yup,我也沒有。)

在網上的無數地方,我看到了在JavaScript之前包含CSS的建議。 推理通常是這種形式

當談到訂購你的CSS和JavaScript時,你希望你的CSS排在第一位。 原因是呈現線程具有呈現頁面所需的所有樣式信息。 如果JavaScript包含第一,JavaScript引擎必須在繼續下一組資源之前解析它。 這意味著渲染線程無法完全顯示頁面,因為它沒有所需的所有樣式。

我的實際測試揭示了非常不同的東西

我的測試用具

我使用下面的Ruby腳本為各種資源生成特定的延遲:

require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'
require 'date'

class Handler  < EventMachine::Connection
  include EventMachine::HttpServer

  def process_http_request
    resp = EventMachine::DelegatedHttpResponse.new( self )

    return unless @http_query_string

    path = @http_path_info
    array = @http_query_string.split("&").map{|s| s.split("=")}.flatten
    parsed = Hash[*array]

    delay = parsed["delay"].to_i / 1000.0
    jsdelay = parsed["jsdelay"].to_i

    delay = 5 if (delay > 5)
    jsdelay = 5000 if (jsdelay > 5000)

    delay = 0 if (delay < 0) 
    jsdelay = 0 if (jsdelay < 0)

    # Block which fulfills the request
    operation = proc do
      sleep delay 

      if path.match(/.js$/)
        resp.status = 200
        resp.headers["Content-Type"] = "text/javascript"
        resp.content = "(function(){
            var start = new Date();
            while(new Date() - start < #{jsdelay}){}
          })();"
      end
      if path.match(/.css$/)
        resp.status = 200
        resp.headers["Content-Type"] = "text/css"
        resp.content = "body {font-size: 50px;}"
      end
    end

    # Callback block to execute once the request is fulfilled
    callback = proc do |res|
        resp.send_response
    end

    # Let the thread pool (20 Ruby threads) handle request
    EM.defer(operation, callback)
  end
end

EventMachine::run {
  EventMachine::start_server("0.0.0.0", 8081, Handler)
  puts "Listening..."
}

上述小型服務器允許我為JavaScript文件(服務器和客戶端)以及任意CSS延遲設置任意延遲。 例如, http://10.0.0.50:8081/test.css?delay=500 delay=500給我一個500毫秒的延遲傳輸CSS。

我使用下面的頁面來測試。

<!DOCTYPE html>
<html>
  <head>
      <title>test</title>
      <script type='text/javascript'>
          var startTime = new Date();
      </script>
      <link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet">
      <script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&amp;jsdelay=1000"></script> 
  </head>
  <body>
    <p>
      Elapsed time is: 
      <script type='text/javascript'>
        document.write(new Date() - startTime);
      </script>
    </p>    
  </body>
</html>

當我首先包含CSS時,該頁面需要1.5秒來渲染:

當我首先包含JavaScript時,該頁面需要1.4秒來渲染:

Chrome,Firefox和Internet Explorer中的結果類似。 然而,在Opera中,排序並不重要。

看起來正在發生的事情是JavaScript解釋器拒絕啟動,直到所有的CSS被下載。 所以,當JavaScript線程獲得更多運行時間時,似乎首先使JavaScript包含效率更高。

我是否缺少一些東西,建議放置CSS包括之前的JavaScript包含不正確的東西?

很明顯,我們可以添加異步或使用setTimeout來釋放渲染線程或將JavaScript代碼放入頁腳,或者使用JavaScript加載器。 這裡的重點是關於頭部基本JavaScript位和CSS位的排序。


更新2017-12-16

我不確定OP中的測試。 我決定嘗試一點,最終破壞了一些神話。

同步<script src...>將阻止下載其下的資源,直到它被下載並執行

這不再是事實 。 看看由Chrome 63生成的瀑布:

<head>
<script src="//alias-0.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=1"></script>
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=2"></script>
<script src="//alias-2.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=3"></script>
</head>

<link rel=stylesheet>不會阻止它下面的腳本的下載和執行

這是不正確的 。 樣式表不會阻止下載,但它阻止腳本的執行( 這裡有一些小解釋 )。 看看由Chrome 63生成的性能圖表:

<link href="//alias-0.redacted.com/payload.php?type=css&amp;delay=666" rel="stylesheet">
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;block=1000"></script>

牢記上述內容,OP中的結果可以解釋如下:

CSS第一:

CSS Download  500ms:<------------------------------------------------>
JS Download   400ms:<-------------------------------------->
JS Execution 1000ms:                                                  <-------------------------------------------------------------------------------------------------->
DOM Ready   @1500ms:                                                                                                                                                      ◆

JS第一:

JS Download   400ms:<-------------------------------------->
CSS Download  500ms:<------------------------------------------------>
JS Execution 1000ms:                                        <-------------------------------------------------------------------------------------------------->
DOM Ready   @1400ms:                                                                                                                                            ◆

在JavaScript之前放置CSS有兩個主要原因。

  1. 舊版瀏覽器(Internet Explorer 6-7,Firefox 2等)會在開始下載腳本時阻止所有後續下載。 所以如果你有a.js後跟b.css他們會按順序下載:先a然後b。 如果你有b.css後跟a.js它們會並行下載,因此頁面加載速度更快。

  2. 在所有樣式表下載完成之前不會呈現任何內容 - 所有瀏覽器都是如此。 腳本是不同的 - 它們阻止渲染頁面中腳本標記下的所有DOM元素。 如果將腳本放在HEAD中,則意味著整個頁面都將被阻止呈現,直到下載了所有樣式表和所有腳本。 雖然阻止所有的樣式表渲染是非常有意義的(所以你第一次得到正確的樣式並且避免未格式化內容FOUC的閃光),但是阻止為腳本渲染整個頁面是沒有意義的。 通常,腳本不會影響任何DOM元素或DOM元素的一部分。 最好在頁面中盡可能低地加載腳本,或者更好地將腳本加載到異步。

Cuzillion創造例子很有趣。 例如, 此頁面在HEAD中有一個腳本,因此整個頁面在完成下載之前都是空白的。 但是,如果我們將腳本移動到BODY塊的末尾,則頁面標題將呈現,因為這些DOM元素出現在SCRIPT標記上方,如您在此頁面上所看到的那樣。


建議在JavaScript無效之前包含CSS嗎?

不是,如果你只是把它當作推薦。 但是,如果你把它當作一條堅強而快速的規則呢,是的,它是無效的。

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded

樣式表加載阻止腳本執行,所以如果在<link rel="stylesheet" ...> <script>之後有<script>頁面不會完成分析 - 並且DOMContentLoaded不會觸發 - 直到加載樣式表。

看起來您需要知道每個腳本所依賴的內容,並確保腳本的執行延遲到正確完成事件之後。 如果腳本僅依賴於DOM,那麼它可以在ondomready / domcontentloaded中恢復,如果它依賴於要加載的圖像或要應用的樣式表,那麼如果我正確讀取上述引用,那麼必須將該代碼推遲到onload事件。

我不認為襪子尺寸適合所有人,儘管這是他們銷售的方式,我知道一種鞋子尺寸不適合所有人。 我不認為有一個確定的答案來加載首先,樣式或腳本。 更重要的是,按照什麼樣的順序加載什麼以及什麼可以推遲到什麼時候才能被放在“關鍵路徑”上。

與觀察者交談,他表示最好延遲用戶交互的能力,直到表單變得可愛為止。 你們中有很多人在那裡,而你們感到相反的是你們。 他們來到一個網站來完成一個目的,並拖延他們與網站互動的能力,同時等待無關緊要的事情來完成加載是非常令人沮喪的。 我並不是說你錯了,只是你應該意識到存在另一個不同意你的優先權的派別。

這個問題特別適用於所有放在網站上的廣告。 如果網站作者僅為廣告內容呈現佔位符div,並確保在onload事件中註入廣告之前已加載並互動網站,我會很喜歡它。 儘管如此,我還是希望看到廣告一次性加載,而不是一次性加載,因為它們會影響我在加載臃腫廣告的同時滾動網站內容的能力。 但這只是一個人的觀點。

  • 了解你的用戶和他們的價值。
  • 了解你的用戶和他們使用的瀏覽環境。
  • 知道每個文件的功能,以及它的先決條件是什麼。 一切工作都將優先於速度和美觀。
  • 使用在開發時向您顯示網絡時間線的工具。
  • 在用戶使用的每個環境中進行測試。 可能需要動態地(服務器端,創建頁面時)根據用戶環境改變加載順序。
  • 如有疑問,請改變順序並再次測量。
  • 加載順序中的混用風格和腳本可能是最佳的; 不是所有其他人都是。
  • 不僅要試驗加載文件的順序,還要在哪裡進行實驗。 頭? 在身體? 身體後? DOM就緒/加載? 裝?
  • 在適當的時候考慮異步和推遲選項,以減少用戶在能夠與頁面交互之前所經歷的淨延遲。 測試以確定它們是否有幫助或受傷。
  • 評估最佳加載順序時總會考慮折衷因素。 漂亮與響應只是一個。

我不會過分強調你所得到的結果,我相信這是主觀的,但我有理由向你解釋,在js之前放置CSS更好。

在加載您的網站時,您會看到兩種情況:

案例1:白屏>無風格網站>風格網站>互動>風格互動網站

案例2:白屏>無風格網站>互動>風格網站>風格互動的網站

我真的無法想像任何人選擇第二種情況。這意味著使用慢速互聯網連接的訪問者將面臨一個沒有樣式的網站,允許他們使用Javascript進行交互(因為已經加載)。 此外,通過這種方式可以最大限度地縮短查看未打版網站的時間。 為什麼會有人想要這樣?

它也可以像jQuery那樣更好地工作

“當使用依賴於CSS樣式屬性值的腳本時,在引用腳本之前引用外部樣式表或嵌入樣式元素非常重要。”

當文件以錯誤順序(第一個JS,然後是CSS)加載時,任何依賴於CSS文件中設置的屬性的Javascript代碼(例如div的寬度或高度)將無法正確加載。 似乎加載順序錯誤,正確的屬性“有時”是Javascript已知的(也許這是由競態條件引起的)。 取決於所使用的瀏覽器,此效果似乎更大或更小。


我不確定你的測試如何“渲染”你的Java腳本。 不過考慮一下

您網站上的一個頁面是50k,這不是不合理的。 用戶位於東海岸,而服務器位於西部。 MTU絕對不是10K,所以會有幾次來回。 接收您的頁面和样式表可能需要1/2秒。 通常(對我來說)javascript(通過jquery插件等)遠遠超過CSS。 這也是當你的互聯網連接在頁面中途窒息時發生的事情,但讓我們忽略(偶爾發生在我身上,我相信css呈現,但我不是100%確定)。

由於css在頭部,可能會有其他連接來獲取它,這意味著它可能會在頁面完成之前完成。 反正在類型期間頁面的其餘部分需要和JavaScript文件(這是更多的字節)的頁面是無風格的,這使得站點/連接看起來很慢。

即使JS解釋器在CSS完成之前拒絕啟動,下載JavaScript代碼所用的時間也會縮短,特別是當服務器距離服務器很遠時,會縮短CSS時間,這會使網站看起來不太漂亮。

它是一個小的優化,但這是它的原因。


我認為這對所有情況都不會是真的。 因為CSS會下載並行但js不能。 考慮同樣的情況,

而不是單一的CSS,拿2或3個CSS文件,並嘗試這些方法,

1)css..css..js 2)css..js..css 3)js..css..css

我相信css..css..js會比其他所有人都有更好的結果。


由於其他原因,我在Javascript之前包含CSS文件。

如果我的Javascript需要動態調整一些頁面元素的大小(對於那些CSS真的是主要背景的角落案例),那麼在JS出現問題之後加載CSS可能會導致競爭狀況,其中元素在CSS樣式之前調整大小應用程序,因此看起來很奇怪,當樣式終於踢了。如果我事先加載CSS,我可以保證東西運行在預定的順序,最終的佈局是我想要的。


這裡是上述所有主要答案的摘要 (或者可能在下文中:)

對於現代瀏覽器,將css放在任何你喜歡的地方。 他們會分析你的HTML文件(他們稱之為推測性解析 ),並開始下載與HTML解析並行的CSS。

對於舊的瀏覽器,將css放在頂部(如果您不想首先顯示裸體但交互式的頁面)。

對於所有瀏覽器,盡可能將JavaScript放在頁面上,因為它會停止解析你的html。 優選地,異步下載(即,ajax調用)

還有一些關於特定情況的實驗結果,聲稱把JavaScript放在第一位(相對於傳統的把CSS放在第一位的方式),這樣可以提供更好的性能,但沒有給出邏輯推理,並且缺乏對廣泛適用性的驗證,所以你可以現在忽略它。

所以,回答這個問題:是的。 在JS之前包含CSS的建議對現代瀏覽器無效。 盡可能將CSS放在任何你喜歡的地方,並儘可能地將JS放到最後。





performance