질문 : CSS가 항상 Javascript보다 우선해야합니까?
온라인의 수많은 곳에서 JavaScript 이전에 CSS를 포함하라는 권장 사항을 보았습니다. 그 이유는 일반적으로 다음 과 같은 형식입니다 .
CSS와 자바 스크립트를 주문할 때 CSS가 먼저 나오기를 원합니다. 그 이유는 렌더링 스레드에 페이지를 렌더링하는 데 필요한 모든 스타일 정보가 있기 때문입니다. JavaScript 포함이 먼저 오는 경우 JavaScript 엔진은 다음 리소스 세트로 계속 진행하기 전에 모든 것을 구문 분석해야합니다. 이것은 렌더링 스레드가 필요한 모든 스타일을 가지고 있지 않기 때문에 페이지를 완전히 표시 할 수 없음을 의미합니다.
내 실제 테스트는 매우 다른 것을 보여줍니다.
My test harness
다음 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 전송을 500ms 지연시킵니다.
다음 페이지를 사용하여 테스트합니다.
<!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에서는 순서가 중요하지 않습니다.
일어나는 것처럼 보이는 것은 모든 CSS가 다운로드 될 때까지 JavaScript 인터프리터가 시작을 거부한다는 것입니다. 따라서 JavaScript 스레드가 더 많은 런타임을 얻음에 따라 JavaScript 포함을 먼저 사용하는 것이 더 효율적으로 보입니다.
내가 뭔가를 놓치고 있는데, JavaScript 포함 전에 CSS 포함을 배치하라는 권장 사항이 올바르지 않습니까?
비동기를 추가하거나 setTimeout을 사용하여 렌더링 스레드를 비우거나 바닥 글에 JavaScript 코드를 넣거나 JavaScript 로더를 사용할 수 있다는 것은 분명합니다. 여기서 요점은 머리에서 필수 JavaScript 비트와 CSS 비트의 순서에 관한 것입니다.
답변
이것은 매우 흥미로운 질문입니다. 나는 항상 내 CSS <link href="...">
를 내 JS <script src="...">
앞에 두었습니다. "나는 그것이 더 낫다는 것을 한 번 읽었 기 때문입니다." 그래서, 당신이 옳습니다. 실제 조사를 할 때입니다!
Node에서 자체 테스트 하네스를 설정했습니다 (아래 코드). 기본적으로 나는 :
- HTTP 캐싱이 없는지 확인하여 페이지가로드 될 때마다 브라우저가 전체 다운로드를 수행해야합니다.
- 현실을 시뮬레이션하기 위해 jQuery와 H5BP CSS를 포함했습니다 (따라서 구문 분석 할 스크립트 / CSS의 양이 적당합니다).
- 두 페이지를 설정합니다. 하나는 스크립트 이전에 CSS를 사용하고 다른 하나는 스크립트 이후에 CSS를 사용합니다.
<head>
의 외부 스크립트를 실행하는 데 걸린 시간을 기록했습니다.DOMReady
<body>
의 인라인 스크립트를 실행하는 데 걸린 시간을 기록했습니다.- 브라우저에 CSS 및 / 또는 스크립트 전송을 500ms 지연했습니다.
- 3 개의 주요 브라우저에서 테스트를 20 회 실행했습니다.
Results
먼저 CSS 파일이 500ms 지연된 경우 :
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
마지막으로 jQuery와 CSS를 모두 500ms 지연하도록 설정했습니다.
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>
의 스크립트에 연결하는 이유에 대한 다양한 주장이 있지만이 답변의 범위를 벗어납니다. <head>
에서 <script>
<link>
앞에 와야하는지 여부에 관한 것입니다.
최신 데스크톱 브라우저에서는 CSS에 연결하는 것이 성능 향상을 제공 하지 않는 것처럼 보입니다. 스크립트 뒤에 CSS를 배치하면 CSS와 스크립트가 모두 지연 될 때 약간의 이득을 얻을 수 있지만 CSS가 지연되면 큰 이득을 얻을 수 있습니다. (첫 번째 결과 집합의 last
열에 표시됩니다.)
마지막으로 CSS에 연결하는 것이 성능을 저하 시키지는 않지만 특정 상황에서 이점을 제공 할 수 있으므로 이전 브라우저의 성능이 문제가되지 않는 경우 데스크톱 브라우저에서만 외부 스크립트에 연결 한 후 외부 스타일 시트에 연결해야합니다. 모바일 상황에 대해 읽어보십시오.
이유
역사적으로 브라우저가 외부 리소스를 가리키는 <script>
태그를 발견하면 브라우저는 HTML 구문 분석을 중지 하고 스크립트를 검색하고 실행 한 다음 HTML 구문 분석을 계속했습니다. 반대로 브라우저가 외부 스타일 시트에 대한 <link>
를 발견하면 CSS 파일을 가져 오는 동안 (병렬로) HTML을 계속 구문 분석합니다.
따라서 스타일 시트를 먼저 배치하라는 널리 반복되는 조언은 먼저 다운로드하고 다운로드 할 첫 번째 스크립트를 병렬로로드 할 수 있습니다.
그러나 최신 브라우저 (위에서 테스트 한 모든 브라우저 포함)는 브라우저가 HTML에서 "미리 살펴보고"스크립트를 다운로드하고 실행 하기 전에 리소스를 다운로드하기 시작하는 추론 적 구문 분석을 구현했습니다.
추측 적 구문 분석이없는 오래된 브라우저에서 스크립트를 먼저 배치하면 병렬로 다운로드되지 않으므로 성능에 영향을 미칩니다.
브라우저 지원
추측 파싱은 다음에서 처음 구현되었습니다. (2012 년 1 월 현재이 버전 이상을 사용하는 전 세계 데스크톱 브라우저 사용자의 비율과 함께)
- Chrome 1 (WebKit 525) (100 %)
- IE 8 (75 %)
- Firefox 3.5 (96 %)
- Safari 4 (99 %)
- 오페라 11.60 (85 %)
현재 사용중인 데스크톱 브라우저의 약 85 %가 예측 로딩을 지원합니다. CSS 앞에 스크립트를 넣으면 전 세계 사용자의 15 %에 대한 성능 저하가 발생합니다. 사이트의 특정 잠재 고객을 기반으로 한 YMMV. (그리고 숫자가 줄어들고 있음을 기억하십시오.)
모바일 브라우저에서는 모바일 브라우저와 OS 환경이 얼마나 이질적인 지로 인해 정확한 수치를 얻는 것이 조금 더 어렵습니다. 추측 적 렌더링은 WebKit 525 (2008 년 3 월 출시)에서 구현되었고 거의 모든 가치있는 모바일 브라우저가 WebKit을 기반으로했기 때문에 "대부분의"모바일 브라우저 가이를 지원해야한다고 결론을 내릴 수 있습니다. quirksmode 에 따르면 iOS 2.2 / Android 1.0은 WebKit 525를 사용합니다. Windows Phone이 어떻게 생겼는지 모르겠습니다.
하지만 내 Android 4 기기에서 테스트를 실행했는데 데스크톱 결과와 비슷한 수치를 보았지만 Android 용 Chrome의 환상적인 새 원격 디버거 에 연결했고 네트워크 탭에 브라우저가 실제로 다운로드를 기다리고 있음이 표시되었습니다. 즉, 최신 버전의 Android 용 WebKit조차도 추론 적 구문 분석을 지원하지 않는 것으로 보입니다. 모바일 장치 고유의 CPU, 메모리 및 / 또는 네트워크 제약으로 인해 꺼져있을 수 있습니다.
Code
엉성함을 용서하십시오 – 이것은 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[
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였습니다.
출처 : https://stackoverflow.com/questions/9271276/should-css-always-preceed-javascript
'프로그래밍 언어 > HTML,CSS,JS' 카테고리의 다른 글
를 입력하는 대신 HTML에 탭 문자를 삽입하는 방법 (0) | 2021.11.19 |
---|---|
CSS input 테두리의 모서리를 둥글게 하는 방법 (0) | 2021.11.18 |
동적으로 명명 된 속성을 JavaScript 개체에 추가 하는 방법 (0) | 2021.11.16 |
JavaScript에서 문자열을 여러 번 반복하는 방법 (0) | 2021.11.16 |
javascript 배열을 복사하는 방법 (0) | 2021.11.16 |