無数のオンラインの場所で、私は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
を指定すると、CSSの転送に500 msの遅延が生じます。
次のページを使ってテストします。
<!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&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を最初に含める方が効率的です。
私は何かが足りないのですが、JavaScriptのインクルードの前にCSSのインクルードを配置することの推奨は正しくありませんか?
非同期を追加するか、setTimeoutを使用してレンダリングスレッドを解放するか、JavaScriptコードをフッターに入れるか、またはJavaScriptローダーを使用できることは明らかです。ここで重要なのは、重要なJavaScriptビットとCSSビットの先頭の順序についてです。
これは非常に興味深い質問です。私はいつもCSS <link href="...">
sをJS <script src="...">
sの前に置いてきました。「一度読んだほうが良いからです」。だから、あなたは正しい。実際の調査を行う時期です。
Nodeに独自のテストハーネスをセットアップします(以下のコード)。基本的に、私:
<head>
での外部スクリプトの実行にかかった時間を記録しました<body>
のインラインスクリプトの実行にかかった時間を記録しました。これはDOMReady
に類似しています。まず、CSSファイルを500ミリ秒遅延させます。
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 583ms 36ms | 559ms 42ms | 565ms 49ms
St Dev | 15ms 12ms | 9ms 7ms | 13ms 6ms
------------|--------------|--------------|------------
Body Exec | | |
Average | 584ms 521ms | 559ms 513ms | 565ms 519ms
St Dev | 15ms 9ms | 9ms 5ms | 13ms 7ms
次に、CSSではなく500msだけ遅延するようにjQueryを設定します。
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 597ms 556ms | 562ms 559ms | 564ms 564ms
St Dev | 14ms 12ms | 11ms 7ms | 8ms 8ms
------------|--------------|--------------|------------
Body Exec | | |
Average | 598ms 557ms | 563ms 560ms | 564ms 565ms
St Dev | 14ms 12ms | 10ms 7ms | 8ms 8ms
最後に、both jQueryとCSSを500ミリ秒遅延するように設定します。
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 620ms 560ms | 577ms 577ms | 571ms 567ms
St Dev | 16ms 11ms | 19ms 9ms | 9ms 10ms
------------|--------------|--------------|------------
Body Exec | | |
Average | 623ms 561ms | 578ms 580ms | 571ms 568ms
St Dev | 18ms 11ms | 19ms 9ms | 9ms 10ms
最初に、スクリプトがドキュメントの<head>
にある(<body>
の終わりではなく)ことを前提として動作していることに注意することが重要です。 <head>
でスクリプトにリンクする理由についてはさまざまな議論がありますが、ドキュメントの最後ではありませんが、それはこの答えの範囲外です。これは、<script>
sが<link>
s内の<head>
sの前に行くべきかどうかに関するものです。
最新のデスクトップブラウザでは最初にCSSにリンクするように見えますneverはパフォーマンスを向上させます。スクリプトの後にCSSを置くと、CSSとスクリプトの両方が遅れる場合にわずかな利益が得られますが、CSSが遅れる場合に大きな利益が得られます。 (最初の結果セットのlast
列で表示されます。)
CSSへの最後のリンクはパフォーマンスを損なうようには見えませんが、特定の状況下ではcanが利益をもたらすことを考えると、外部スタイルシートafter外部ブラウザにリンクしますデスクトップブラウザのみ古いブラウザのパフォーマンスが問題にならない場合。 モバイルの状況について続きを読む。
歴史的に、ブラウザが外部リソースを指す<script>
タグに遭遇すると、ブラウザはstop HTMLの解析、スクリプトの取得、実行、HTMLの解析の続行を行います。対照的に、ブラウザが外部スタイルシートの<link>
に遭遇した場合、CSSファイルを(並行して)フェッチしながらHTMLを解析continueします。
したがって、スタイルシートを最初に配置するという広く繰り返されているアドバイス-最初にダウンロードし、ダウンロードする最初のスクリプトを並行してロードできます。
ただし、最新のブラウザー(上記でテストしたすべてのブラウザーを含む)は、 投機解析 を実装しています。この場合、ブラウザーはHTMLを「先読み」してダウンロードを開始しますリソースbeforeスクリプトがダウンロードおよび実行されます。
投機的解析のない古いブラウザでは、スクリプトを最初に置くと並行してダウンロードされないため、パフォーマンスに影響します。
投機的解析は最初に実装されました:(2012年1月現在、このバージョン以上を使用している世界中のデスクトップブラウザーユーザーの割合)
合計で、現在使用されているデスクトップブラウザーの約85%が投機的読み込みをサポートしています。 CSSの前にスクリプトを置くと、ユーザーの15%でパフォーマンスが低下しますグローバルに;サイトの特定のオーディエンスに基づいたYMMV。 (そして、その数が縮小していることを忘れないでください。)
モバイルブラウザーでは、モバイルブラウザーとOSのランドスケープがどれだけ異質であるかという理由だけで、明確な数値を取得するのが少し難しくなります。投機的レンダリングはWebKit 525(2008年3月リリース)に実装されており、価値のあるモバイルブラウザーのほとんどすべてがWebKitに基づいているため、「ほとんどの」モバイルブラウザーshouldがサポートすると結論付けることができます。 quirksmode によると、iOS 2.2/Android 1.0はWebKit 525を使用します。WindowsPhoneがどのように見えるかわかりません。
ただし、私はAndroid 4デバイスでテストを実行し、デスクトップの結果に似た数字を見ながら、素晴らしい新しい リモートデバッガーに接続しましたAndroidのChrome内の では、JavaScriptが完全に読み込まれるまでブラウザが実際にCSSのダウンロードを待機していることを示しました。つまり、WebKit forの最新バージョンでもAndroidは投機的解析をサポートしていないようです。 CPU、メモリ、モバイルデバイス固有のネットワークの制約などにより、オフになっている可能性があります。
ずさんなことは許してください。これはQ&Dでした。
app.js
var express = require('express')
, app = express.createServer()
, fs = require('fs');
app.listen(90);
var file={};
fs.readdirSync('.').forEach(function(f) {
console.log(f)
file[f] = fs.readFileSync(f);
if (f != 'jquery.js' && f != 'style.css') app.get('/' + f, function(req,res) {
res.contentType(f);
res.send(file[f]);
});
});
app.get('/jquery.js', function(req,res) {
setTimeout(function() {
res.contentType('text/javascript');
res.send(file['jquery.js']);
}, 500);
});
app.get('/style.css', function(req,res) {
setTimeout(function() {
res.contentType('text/css');
res.send(file['style.css']);
}, 500);
});
var headresults={
css: [],
js: []
}, bodyresults={
css: [],
js: []
}
app.post('/result/:type/:time/:exec', function(req,res) {
headresults[req.params.type].Push(parseInt(req.params.time, 10));
bodyresults[req.params.type].Push(parseInt(req.params.exec, 10));
res.end();
});
app.get('/result/:type', function(req,res) {
var o = '';
headresults[req.params.type].forEach(function(i) {
o+='\n' + i;
});
o+='\n';
bodyresults[req.params.type].forEach(function(i) {
o+='\n' + i;
});
res.send(o);
});
css.html
<!DOCTYPE html>
<html>
<head>
<title>CSS first</title>
<script>var start = Date.now();</script>
<link rel="stylesheet" href="style.css">
<script src="jquery.js"></script>
<script src="test.js"></script>
</head>
<body>
<script>document.write(jsload - start);bodyexec=Date.now()</script>
</body>
</html>
js.html
<!DOCTYPE html>
<html>
<head>
<title>CSS first</title>
<script>var start = Date.now();</script>
<script src="jquery.js"></script>
<script src="test.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script>document.write(jsload - start);bodyexec=Date.now()</script>
</body>
</html>
test.js
var jsload = Date.now();
$(function() {
$.post('/result' + location.pathname.replace('.html','') + '/' + (jsload - start) + '/' + (bodyexec - start));
});
jquery.jsは jquery-1.7.1.min.js でした
JavaScriptの前にCSSを使用する主な理由は2つあります。
古いブラウザ(Internet Explorer 6-7、Firefox 2など)は、スクリプトのダウンロードを開始したときにそれ以降のすべてのダウンロードをブロックします。それであなたがa.js
に続いてb.css
を持っているならば、それらは順番にダウンロードされるでしょう。あなたがb.css
に続いてa.js
を持っているなら、それらは並行してダウンロードされるので、ページはより速くロードされます。
すべてのスタイルシートがダウンロードされるまで何もレンダリングされません - これはすべてのブラウザに当てはまります。スクリプトは異なります - ページ内のscriptタグの下であるすべてのDOM要素のレンダリングをブロックします。スクリプトをHEADに入れると、すべてのスタイルシートとすべてのスクリプトがダウンロードされるまで、ページ全体のレンダリングがブロックされます。スタイルシートのすべてのレンダリングをブロックするのは理にかなっていますが(最初に正しいスタイルを作成し、スタイルのないコンテンツFOUCのフラッシュを避ける)、スクリプトのページ全体のレンダリングをブロックするのは意味がありません。多くの場合、スクリプトはDOM要素にもDOM要素の一部にも影響を与えません。 できるだけ低いページ内のスクリプトをロードすることをお勧めします。または、非同期でスクリプトをロードすることをお勧めします。
Cuzillion で例を作成するのは楽しいです。たとえば、 このページ にHEADのスクリプトがあるため、ダウンロードが完了するまでページ全体が空白になります。しかし、スクリプトをBODYブロックの最後に移動すると、 this page に示すように、それらのDOM要素がSCRIPTタグの上にあるため、ページヘッダーがレンダリングされます。
私はあなたが得た結果についてあまり強調しないであろう、私はそれが主観的であると信じるが、私はあなたがjsの前にCSSに入れるほうが良いとあなたに説明する理由がある。
Webサイトの読み込み中に、表示される2つのシナリオがあります。
ケース1:白い画面>スタイルのないWebサイト>スタイルのあるWebサイト>インタラクション>スタイルのある対話型のWebサイト
ケース2:白い画面>スタイルのないWebサイト>インタラクション>スタイルのあるWebサイト>スタイルのある対話型のWebサイト
私が誰かがケース2を選択することは正直に想像できません。これは遅いインターネット接続を使用する訪問者がJavascriptを使用してそれと対話することを可能にするさらに、スタイルのないWebサイトを見るのに費やす時間は、この方法で最大化されます。なぜ誰かがそれを望みますか?
「CSSスタイルプロパティの値に依存するスクリプトを使用する場合は、スクリプトを参照する前に外部スタイルシートを参照するかスタイル要素を埋め込むことが重要です。」.
ファイルが間違った順序(最初はJS、次にCSS)でロードされると、CSSファイルで設定されたプロパティ(例えばdivの幅や高さ)に依存するJavascriptコードは正しくロードされません。ロードの順序が間違っていると、正しいプロパティがJavascriptに「知られる」ことがあります(おそらくこれは競合状態が原因です)。この効果は、使用しているブラウザに応じて大きくなったり小さくなったりします。
あなたのテストはあなたのパソコンで行われましたか、それともウェブサーバーで行われましたか?それは空白のページなのか、それとも画像やデータベースなどを含む複雑なオンラインシステムなのか。あなたのスクリプトは単純なホバーイベントアクションを実行していますか、それともあなたのウェブサイトがどのようにレンダリングされユーザーと対話するかの中心的な要素ですか?ここで考慮しなければならないことがいくつかあります。これらの推奨事項の関連性は、大規模なWeb開発に取り組むときにはほとんどの場合ルールになります。
「スタイルシートを一番上に、スクリプトを一番下に配置する」という規則の目的は、一般に、最適なものを達成するための最善の方法です。{プログレッシブレンダリング、。
それ以外のことは別として、あなたのテストが有効であり、そしてあなたが本当にポピュラーなルールに反して結果を生み出していると仮定すると、それは本当に驚くべきことではないでしょう。すべてのWebサイト(および全体をユーザーの画面に表示するために必要なすべてのもの)は異なり、インターネットは常に進化しています。
私は別の理由でJavascriptの前にCSSファイルを含めます。
私のJavascriptが何らかのCSS要素を動的にサイズ変更する必要がある場合(CSSが実際にメインであるコーナーの場合)、JSが失速した後にCSSをロードすると、CSSスタイルの前に要素のサイズが変更されます。 CSSが事前にロードされていれば、物事が意図した順序で実行され、最終的なレイアウトが希望通りになることを保証できます。
JavaScriptの前にCSSを含めるという推奨は無効ですか?
あなたがそれを単に推薦として扱うならばそうではありません。しかし、あなたがそれを厳しくて速い規則として扱うならば、はい、それは無効です。
https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded から
スタイルシートはブロックスクリプトの実行をロードするので、
<script>
の後に<link rel="stylesheet" ...>
がある場合、スタイルシートがロードされるまでページは解析を終了しません - そしてDOMContentLoadedは起動しません - 。
各スクリプトが依存しているものを知っている必要があり、スクリプトの実行が正しい完了イベントの後まで遅れることを確認する必要があるようです。スクリプトがDOMのみに依存している場合は、ondomready/domcontentloadedで再開できます。ロードする画像または適用するスタイルシートに依存している場合は、上記の参照を正しく読むと、onloadイベントまでコードを延期する必要があります。
それが彼らが売られている方法であるとしても、私は1つの靴のサイズがすべてに合うとは思いません、そして、私は1つの靴のサイズがすべてに合うわけではないことを知っています。最初にロードするのに決定的な答え、スタイルやスクリプトがあるとは思わない。何がどの順序でロードされなければならないか、そして「クリティカルパス」上にいないとして後になるまで何を延期することができるかについては、ケースバイケースの決定である。
シートがきれいになるまでユーザーの対話を遅らせる方が良いとコメントしたオブザーバーと話すこと。あなたの多くがそこにいます、そしてあなたは反対を感じるあなたの対応物をいらいらさせます。彼らは目的を達成するためにサイトにやってきて、ロードを完了することが重要ではないものを待つのが非常にイライラするのを待っている間サイトと対話する彼らの能力の遅れ。私はあなたが間違っていると言っているのではなく、あなたの優先順位を共有しない別の派閥が存在することを知っておくべきであるということだけです。
この質問は、Webサイトに掲載されているすべての広告に特に当てはまります。サイトの作者が広告コンテンツのプレースホルダdivをレンダリングし、onloadイベントに広告を挿入する前に自分のサイトがロードされてインタラクティブであることを確認したなら、私はそれが大好きです。それでも、肥大化した広告が読み込まれている間にサイトのコンテンツをスクロールする能力にも影響するので、一度に全部ではなく直列に読み込まれる広告を見たいと思います。しかしそれは一人の視点です。
2017-12-16に更新
OPのテストについてはわかりませんでした。私は少し実験することを決め、神話のいくつかをつぶすことになりました。
同期
<script src...>
は、ダウンロードして実行されるまで、その下のリソースのダウンロードをブロックします
これはもはや真実ではありません。 Chrome 63によって生成された滝を見てください:
<head>
<script src="//alias-0.redacted.com/payload.php?type=js&delay=333&Rand=1"></script>
<script src="//alias-1.redacted.com/payload.php?type=js&delay=333&Rand=2"></script>
<script src="//alias-2.redacted.com/payload.php?type=js&delay=333&Rand=3"></script>
</head>
<link rel=stylesheet>
は、その下のスクリプトのダウンロードと実行をブロックしません
これは間違っています。スタイルシートはダウンロードをブロックしませんが、はスクリプトの実行をブロックします( 小さな説明はこちら )。 Chrome 63によって生成されたパフォーマンスチャートをご覧ください。
<link href="//alias-0.redacted.com/payload.php?type=css&delay=666" rel="stylesheet">
<script src="//alias-1.redacted.com/payload.php?type=js&delay=333&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: ◆
あなたのテストがあなたのJavaスクリプトを使うのと同じように「レンダリング」されるのか、私は正確にはわかりません。しかしこれを考えなさい
あなたのサイトの1ページは50kですが、これは不合理ではありません。サーバーが西にある間、ユーザーは東海岸にいます。 MTUは間違いなく10kではないので、前後に数回の旅行があるでしょう。あなたのページとスタイルシートを受け取るのに1/2秒かかるかもしれません。通常(私にとっては)javascript(jqueryプラグインなどを介して)はCSSよりはるかに優れています。また、インターネット接続がページの途中で中断しても無視しても問題ありません(たまに起こることもありますし、CSSが表示されると確信していますが、100%確実というわけではありません)。
Cssは頭の中にあるのでそれを取得するための追加の接続があるかもしれません、それはそれが潜在的にページがする前に終了することができることを意味します。とにかくタイプの間にページの残りがとり、JavaScriptファイル(これはもっと多くのバイトです)はスタイルを崩されているのでサイト/接続は遅く見えます。
特にサーバーから遠く離れているときにJavaScriptコードをダウンロードするのにかかる時間がJSインタプリタによって開始されるのを拒否された場合、サイトがきれいに見えなくなるでしょう。
それは小さな最適化ですが、それが理由です。
これは上の(あるいは後で下の場合もありますが): _要約_ です。
最近のブラウザでは、好きな場所にcssを置いてください。彼らはあなたのhtmlファイル(彼らは 投機的解析 と呼ぶ)を分析し、html解析と並行してcssのダウンロードを開始します。
古いブラウザの場合は、CSSを一番上に置いてください(最初に裸でインタラクティブなページを表示したくない場合)。
すべてのブラウザの場合、HTMLの解析が停止するため、JavaScriptをできるだけページの下に配置してください。非同期でダウンロードする(ajaxコール)ことをお勧めします。
また、(CSSを優先するという伝統的な考え方とは対照的に)JavaScriptを優先するという特定のケースについての実験結果もありますが、それに対する論理的な推論はなく、広範な適用性に関する検証に欠けます。今のところ無視してください。
それで、質問に答えるために:はい。最近のブラウザでは、JSの前にCSSを含めるという推奨は無効です。可能な限りCSSを好きな場所に置き、最後にJSを置きます。
Steve Soudersはすでに決定的な答えを出していますが...
SamのオリジナルのテストとJoshのそれの繰り返しの両方に問題があるのだろうか。
どちらのテストも、TCP接続の設定に多大なコストがかかるような低遅延接続で実行されたようです。
これがテストの結果にどのように影響するか私はよくわかりませんが、「通常の」レイテンシ接続でテスト用のウォーターフォールを調べたいのですが...
最初にダウンロードされたファイルは should htmlページに使用される接続を取得し、2番目にダウンロードされたファイルは新しい接続を取得します。 (初期のフラッシュはその動的を変更しますが、それはここで行われていません)
新しいブラウザでは2番目のTCP接続が投機的に開かれるため、接続のオーバーヘッドは減少/消えます。古いブラウザではこれは当てはまりません。2番目の接続には開かれるオーバーヘッドがあります。
かなりこれがテストの結果にどう影響するかどうか、私にはわかりません。
私はこれがすべての場合に当てはまるとは思わない。なぜなら、cssは並行してダウンロードしますがjsは傾けないからです。同じ場合を考えてください。
単一のcssを持つ代わりに、2つか3つのcssファイルを取り、これらの方法でそれを試してみてください、
1)css..css..js 2)css..js..css 3)js..css..css
私はcss..css..jsが他のすべてのものより良い結果をもたらすと確信しています。
新しいブラウザはJavascriptエンジンやパーサなどに働きかけ、一般的なコードやマークアップの問題を最適化し、IE8以下のような古代のブラウザで経験された問題はもはや関係ないようにしました。マークアップだけでなく、JavaScript変数、要素セレクターなどの使用についても同様です。それほど遠くない将来、パフォーマンスがもはや問題にならなくなるまでテクノロジーが進歩している状況を見ることができます。