CSS는 항상 자바 스크립트보다 우선해야합니까?


897

수많은 온라인 사이트에서 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=500CSS를 전송하는 데 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&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 초가 걸립니다.

CSS 우선

JavaScript를 먼저 포함하면 페이지를 렌더링하는 데 1.4 초가 걸립니다.

자바 스크립트 우선

Chrome, Firefox 및 Internet Explorer에서 비슷한 결과를 얻습니다. 그러나 Opera에서는 순서가 중요하지 않습니다.

일어나고있는 것처럼 보이는 것은 JavaScript 해석기가 모든 CSS를 다운로드 할 때까지 시작을 거부한다는 것입니다. 따라서 JavaScript 스레드를 더 많이 실행하면 JavaScript를 먼저 포함하는 것이 더 효율적입니다.

내가 빠뜨린 것이 있습니까? JavaScript가 포함되기 전에 CSS를 포함시키는 것이 좋습니다?

비동기를 추가하거나 setTimeout을 사용하여 렌더링 스레드를 비우거나 JavaScript 코드를 바닥 글에 넣거나 JavaScript 로더를 사용할 수 있음이 분명합니다. 여기서 요점은 필수 JavaScript 비트와 CSS 비트의 순서에 관한 것입니다.


120
1511 vs 1422는 통계적으로 유의미한 차이입니까? 6 %입니다. 평균 대 사람 성능 차이의 일반적인 임계 값은 약 20 %입니다.
Jeff Atwood 2012

15
요점은 재정렬이이 임의의 지연을 제거한다는 것입니다. 지연을 원하는 것으로 설정하면됩니다. 문제의 데모 일뿐입니다.
Sam Saffron

3
지연이 100ms입니까? 스크린 샷의 차이는 89ms입니다. 당신의 URL에서 그것은이다 delay=400&amp;jsdelay=1000delay=500아무 곳에도 가까운이 100ms 또는 89ms입니다있다. 당신이 말하는 숫자가 확실하지 않은 것 같습니다.
Jeff Atwood

4
"Javascript가 먼저 포함되면 Javascript 엔진은 다음 자원 세트로 계속 진행하기 전에 모든 것을 구문 분석해야합니다. 이는 렌더링 스레드에 필요한 모든 스타일이 없기 때문에 페이지를 완전히 표시 할 수 없음을 의미합니다. " -JS include가 헤드에 있으면 CSS include가 이전 또는 이후인지에 관계없이 페이지가 렌더링되기 전에 JS가 실행됩니다.
nnnnnn

162
이것을 고려했는지 확실하지 않지만 로드 시간에 대한 인식도 중요합니다. 예를 들어 CSS를 먼저로드하면 페이지 배경색 / 질감 만 제공되면 더 빠른 것 같습니다. 절대로드 시간이이를 나타내지 않을 수 있습니다.
Rakesh Pai

답변:


712

이것은 매우 흥미로운 질문입니다. 나는 항상 CSS를 CSS <link href="...">앞에 놓았습니다. <script src="...">왜냐하면 "한번 더 나아 졌기 때문입니다." 그래서 당신이 맞습니다. 우리가 실제 연구를 수행 할 시간입니다!

Node에서 자체 테스트 하네스를 설정했습니다 (아래 코드). 기본적으로 나는 :

  • HTTP 캐싱이 없는지 확인하여 페이지가로드 될 때마다 브라우저가 전체 다운로드를 수행해야합니다.
  • 현실을 시뮬레이트하기 위해 jQuery와 H5BP CSS를 포함 시켰습니다.
  • 한 페이지는 스크립트 전 CSS, 다른 하나는 스크립트 후 CSS를 사용하여 두 페이지를 설정합니다.
  • 에서 외부 스크립트 <head>를 실행 하는 데 걸린 시간을 기록했습니다.
  • 에서 인라인 스크립트 <body>를 실행 하는 데 걸린 시간을 기록 했습니다 DOMReady.
  • CSS 및 / 또는 스크립트를 브라우저에 500ms까지 지연시킵니다.
  • 3 개의 주요 브라우저에서 테스트를 20 번 실행했습니다.

결과

먼저 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

다음으로 jQuery를 CSS 대신 500ms 지연하도록 설정했습니다.

     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>문서의 끝과 끝 에서 스크립트에 링크 할 수있는 이유에 대한 다양한 주장이 있지만이 답변의 범위를 벗어납니다. 이것은 s에서 s <script>보다 먼저 갈지 여부 <link>에 관한 것 <head>입니다.

최신 DESKTOP 브라우저에서 CSS에 연결 하면 성능이 향상 되지 않습니다 . CSS를 스크립트 뒤에 놓으면 CSS와 스크립트가 모두 지연 될 때 사소한 양의 이득을 얻을 수 있지만 CSS가 지연되면 큰 이득을 얻을 수 있습니다. last첫 번째 결과 집합의 열로 표시됩니다 .

CSS에 마지막으로 연결해도 성능이 저하되지 않지만 특정 상황에서 이점 얻을 수 있으므로 이전 브라우저의 성능이 중요하지 않은 경우 데스크톱 브라우저에서만 외부 스크립트에 연결 한 후 외부 스타일 시트에 연결해야합니다 . 모바일 상황을 읽으십시오.

왜?

역사적으로 브라우저가 <script>외부 리소스를 가리키는 태그를 발견 하면 브라우저는 HTML 구문 분석 을 중지 하고 스크립트를 검색 한 후 실행 한 다음 HTML 구문 분석을 계속합니다. 반대로, 브라우저가 <link>외부 스타일 시트를 발견 한 경우 CSS 파일을 가져 오는 동안 HTML을 계속 구문 분석합니다 (병렬).

따라서 스타일 시트를 먼저 배치하라는 널리 반복되는 조언 – 먼저 다운로드하고 다운로드 할 첫 스크립트를 병렬로로드 할 수 있습니다.

그러나 최신 브라우저 (위에서 테스트 한 모든 브라우저 포함)는 추측 분석 을 구현 하여 브라우저에서 HTML을 " 예상 "하고 스크립트를 다운로드하고 실행 하기 전에 리소스 다운로드 하기 시작합니다 .

추측 분석이없는 오래된 브라우저에서는 스크립트를 먼저 배치하면 병렬로 다운로드되지 않으므로 성능에 영향을줍니다.

브라우저 지원

추론 파싱은 다음에서 처음 구현되었습니다. (2012 년 1 월 현재이 버전을 사용하는 전 세계 데스크톱 브라우저 사용자의 비율과 함께)

  • 크롬 1 (WebKit 525) (100 %)
  • IE 8 (75 %)
  • 파이어 폭스 3.5 (96 %)
  • 사파리 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 의 환상적인 새로운 원격 디버거 에 연결했으며 네트워크 탭에서 브라우저가 실제로 다운로드 대기 중임을 나타 냈습니다 자바 스크립트가 완전히로드 될 때까지 CSS, 즉 최신 버전의 Android 용 WebKit조차도 추론 파싱을 지원하지 않는 것으로 보입니다. 모바일 장치 고유의 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였습니다.


137
과학이용해 주셔서 감사합니다 . 귀하의 결과에 따르면 "현대 브라우저에서는 CSS에 연결하면 성능이 향상되지 않습니다" 라는 질문에 대한 대답은 ' ' 라고 생각합니다 . CSS의 오래된 조언은 분명히 유효하지 않습니다.
Jeff Atwood 2012

모바일에서의 역수에 대한 @ josh3736의 업데이트와 관련하여 ...이 중요한 변화에서 총을 뛰지 않는 경우입니다. 모바일 성능이 다른 모바일 브라우저 (웹킷, 도마뱀, 프레스토, 트라이던트 등)가 어떻게 더 중요한지 궁금합니다.
scunliffe

1
느린 서버의 속도를 시뮬레이션하기 위해 CSS / JS 인쇄 속도를 약간 낮추어야합니다.
kirb

1
"먼저, 나는 <head>문서의 끝에 스크립트가 있다는 가정하에 운영되고 있음을 주목하는 것이 중요하다 <body>." 상단에서와 같이 답변에서 훨씬 일찍 강조 표시합니다 . 외부 파일을 나타내는를 포함하는 script것은 head거의 모든 관점에서 (거의 성능이 아닌) 거의 정확하지 않습니다. 실생활에서해야했던 일을 기억 나지 않습니다. 인라인 스크립트 의 홀수 줄이나 둘이 될 수도 있지만 그게 전부입니다. 아주 좋은 이유가 없는 기본값 은 신체의 끝이어야합니다.
TJ Crowder

1
다운 투표, jQuery는 JavaScript가 아니며 페이지를 더 많이 부풀 리므로 페이지를 사용한 결과는 객관적이지 않습니다.
John

303

CSS를 JavaScript보다 우선하는 두 가지 주요 이유가 있습니다.

  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 태그 위에서 발생하므로 페이지 헤더가 렌더링 됩니다 .


10
존경하는 스티브가 답을 얻었으나 그가 언급 한 것과 관련된 기사를 추가하겠습니다 : stevesouders.com/blog/2009/04/27/…
Juan Pablo Buritica

4
지원되는 브라우저를 참조 async- 그는 "더 나은 비동기 적으로 그들을로드"말할 때 스티브가 여기에 추천되는 속성, stackoverflow.com/questions/1834077/...
제프 앳 우드

왜 누군가가 CSS 파일을 @import지시문 과 연결하는지 말해 줄 수 있습니까?
Josh Stodola

6
2)의 출처는 무엇이며, 사실이라면 페이지가 콘텐츠로드를 마치는 이유를 설명 할 수 있습니까? 그런 다음 CSS가 1-2 초 후에 적용됩니까? (이것은 CSS가 <head> 태그에있는 내 자신의 페이지에서는 거의 발생하지 않았습니다)
Izkata

2
페이지 끝에 jQuery+ jQuery UI+ $(document).ready(function () { });를 넣어야 합니까? 윌 항상 예상대로 작동?
Olivier Pons 2018

42

나는 당신이 얻은 결과에 대해 너무 강조하지 않고 주관적이라고 생각하지만 js 전에 CSS에 넣는 것이 낫다는 것을 설명 할 이유가 있습니다.

웹 사이트를로드하는 동안 다음과 같은 두 가지 시나리오가 있습니다.

CASE 1 : 흰색 화면> 스타일이 적용되지 않은 웹 사이트> 스타일의 웹 사이트> 상호 작용> 스타일 및 대화 형 웹 사이트

CASE 2 : 흰색 화면> 스타일이 적용되지 않은 웹 사이트> 상호 작용> 스타일 웹 사이트> 스타일 및 대화 형 웹 사이트


솔직히 케이스 2를 선택하는 사람이 상상할 수없는 것은이 의미하는 것 인터넷 연결 속도가 느린 방문자는 스타일이 지정되지 않은 웹 사이트를 접하게되므로 자바 스크립트 (이미로드 된 이후)를 사용하여 웹 사이트와 상호 작용할 수 있습니다. 또한 스타일이 지정되지 않은 웹 사이트를 보는 데 소요되는 시간은 이러한 방식으로 극대화됩니다. 왜 누군가가 그것을 원할까요?

또한 jQuery 상태 로 더 잘 작동합니다.

"CSS 스타일 속성의 값에 의존하는 스크립트를 사용하는 경우 스크립트를 참조하기 전에 외부 스타일 시트를 참조하거나 스타일 요소를 포함시키는 것이 중요합니다."

파일이 잘못된 순서로로드되면 (먼저 JS, CSS) CSS 파일에 설정된 속성 (예 : div의 너비 또는 높이)에 의존하는 Javascript 코드가 올바르게로드되지 않습니다. 잘못된 로딩 순서로 올바른 속성이 Javascript에 알려진 '때때로'인 것 같습니다 (아마도 이것이 경쟁 조건으로 인한 것입니까?). 이 효과는 사용하는 브라우저에 따라 크거나 작게 보입니다.


2
자바 스크립트가 실행되기 전에 모든 CSS 가로 드되도록 보장하는 방법은 무엇입니까? 너는 할수 있니? 또는 스타일을로드 할 필요가없는 상황을 처리 할 수있을만큼 자바 스크립트가 강력해야합니다.
Jonnio 2012

@Jonnio JS에 종속성이 있으면 해당 종속성을 명시 적으로 만들어야합니다. 그렇지 않으면 항상 드문 타이밍 문제가 발생합니다. ES6 모듈을 사용하는 것이 좋은 방법이지만 사용할 수있는 라이브러리가 많이 있습니다.
kmkemp

26

테스트는 개인용 컴퓨터 나 웹 서버에서 수행 되었습니까? 빈 페이지이거나 이미지, 데이터베이스 등이있는 복잡한 온라인 시스템입니까? 스크립트가 간단한 호버 이벤트 동작을 수행합니까, 아니면 웹 사이트가 사용자를 렌더링하고 상호 작용하는 방법의 핵심 구성 요소입니까? 여기에 고려해야 할 몇 가지 사항이 있으며 이러한 권장 사항의 관련성은 거의 항상 높은 수준의 웹 개발에 투자 할 때 규칙이됩니다.

규칙은 "하단에서 상단과 스크립트에 넣어 스타일"의 목적은 즉, 일반적으로 최적 달성하기 위해 가장 좋은 방법이다 진보적 인 렌더링 , 사용자 경험에 매우 중요합니다.

그 밖의 모든 것을 제쳐두고 : 테스트가 유효하고, 일반적인 규칙과 달리 실제로 결과를 생성한다고 가정하면 실제로 놀라운 결과는 아닙니다. 모든 웹 사이트 (그리고 모든 것이 사용자의 화면에 나타나게하는 데 필요한 모든 것)는 다르며 인터넷은 끊임없이 발전하고 있습니다.


1
나는 당신이 굵게 만들고있는 점에 감사하지만, 영업 이익은 당신이 순서 다를 때 발생하는 일에 대해 이야기 를 모두 상단도 하단에.
nnnnnn

1
따라서 "[그의] 테스트가 유효하다고 가정합니다."
skippr

21

다른 이유로 Javascript 앞에 CSS 파일을 포함시킵니다.

내 자바 스크립트가 일부 페이지 요소의 동적 크기 조정을 수행 해야하는 경우 (CSS가 실제로 주요한 코너 경우) JS가 종료 된 후 CSS를로드하면 경쟁 조건이 생길 수 있습니다. 여기서 CSS 스타일보다 요소의 크기가 조정됩니다 스타일이 마침내 시작될 때 이상하게 보입니다. CSS를 미리로드하면 원하는 순서대로 실행되고 최종 레이아웃이 내가 원하는 것을 보장 할 수 있습니다.


2
일부 브라우저에서 언젠가는 중단됩니다. 나는 추측하지 않습니다.
jcolebrand

1
jcolebrand : 그렇습니다, 나는 이것을 쓸 때 충분한 커피를 마시지 않았다고 생각합니다. (돌이켜 보면 중요한 것은 CSS의 동적로드를 피하고 동적 크기 조정이 필요한 경우 JS를 domReady 이벤트에 넣는 것입니다)
hugomg

스크립트는 표시를 변경해서는 안됩니다. 이것이 CSS 작업입니다. HTML = 내용, CSS = 내용을 표시하는 방법, 자바 스크립트는 내용을 동적으로 변경합니다. 또한 js는 DOMContentLoaded가 아주 작지만 매우 구체적인 상황으로 실행 된 후에 만 ​​작동해야합니다.
brunoais

@brunoais : 일부 레이아웃은 Javascript로만 만들 수 있습니다. 예를 들어, 동적으로 크기를 조정해야하는 것은 Javascript를 통해 작성해야하며 일부 브라우저 (예 : 100 %-20px)는 이전 브라우저에서 이식 가능하게 Javascript를 수행해야합니다.
hugomg

@missingno이 경우 어쨌든 DOMContentLoaded 이벤트를 사용하십시오. 그러나 나는 당신이 무엇을 의미하는지 이해합니다. (Stupid IE!)
brunoais

10

JavaScript 전에 CSS를 포함하도록 권장하는 것이 유효하지 않습니까?

단순히 추천으로 취급한다면 아닙니다. 그러나 당신이 그것을 단단하고 빠른 규칙으로 취급한다면, 그렇습니다, 그것은 유효하지 않습니다.

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

스타일 시트는 블록 스크립트 실행을로드하므로, <script> 이후에 <link rel="stylesheet" ...>페이지가 구문 분석을 완료하지 않으면 스타일 시트가로드 될 때까지 DOMContentLoaded가 실행되지 않습니다.

각 스크립트가 의존하는 것을 알고 올바른 완료 이벤트가 끝날 때까지 스크립트 실행이 지연되는지 확인해야합니다. 스크립트가 DOM에만 의존하는 경우 ondomready / domcontentloaded에서 다시 시작할 수 있습니다.로드 할 이미지 또는 적용 할 스타일 시트에 의존하는 경우 위의 참조를 올바르게 읽으면 onload 이벤트까지 해당 코드를 연기해야합니다.

양말 크기가 모두 판매되는 방식이지만 양말 크기가 모두 맞는 것은 아니라고 생각합니다. 스타일이나 스크립트를 먼저로드 할 결정적인 답은 없다고 생각합니다. 어떤 순서로로드해야하는지, 그리고 "중요한 경로"에 있지 않은 것으로 나중에 지연 될 수있는 것을 결정하는 경우가 더 많습니다.

관찰자에게 말하면 시트가 예쁘게 될 때까지 사용자의 상호 작용 능력을 지연시키는 것이 좋습니다. 거기에는 많은 사람들이 있으며 그 반대를 느끼는 상대방을 귀찮게합니다. 그들은 목적을 달성하기 위해 현장에 왔습니다. 적재를 마치는 데 중요하지 않은 것들을 기다리는 동안 사이트와 상호 작용하는 능력이 지연되어 매우 실망 스럽습니다. 나는 당신이 틀렸다고 말하는 것이 아니라, 당신의 우선 순위를 공유하지 않는 또 다른 진영이 있다는 것을 알아야한다는 것입니다.

이 질문은 특히 웹 사이트에 게재되는 모든 광고에 적용됩니다. 사이트 작성자가 광고 콘텐츠에 대해 자리 표시 자 div 만 렌더링하고 onload 이벤트에 광고를 삽입하기 전에 사이트가로드되고 대화 형인지 확인하고 싶을 것입니다. 그럼에도 불구하고 부풀린 광고가로드되는 동안 사이트 콘텐츠를 스크롤하는 기능에 영향을 미치기 때문에 광고가 한 번에 모두 대신 직렬로로드되는 것을보고 싶습니다. 그러나 그것은 한 사람의 관점 일뿐입니다.

  • 사용자와 그들이 무엇을 중요하게 생각하는지 알아보십시오.
  • 사용자와 이들이 사용하는 브라우징 환경을 파악하십시오.
  • 각 파일의 기능과 전제 조건이 무엇인지 파악하십시오. 모든 것이 작동하게 만드는 것은 속도와 예쁘기보다 우선합니다.
  • 개발시 네트워크 타임 라인을 보여주는 도구를 사용하십시오.
  • 사용자가 사용하는 각 환경에서 테스트하십시오. 사용자 환경에 따라로드 순서를 동적으로 변경해야 할 수도 있습니다 (페이지 작성시 서버 측).
  • 확실하지 않은 경우 순서를 변경하고 다시 측정하십시오.
  • 로드 순서에서 혼합 스타일과 스크립트가 최적 일 수 있습니다. 하나가 아니라 다른 하나가 아닙니다.
  • 파일을로드하는 순서뿐만 아니라 위치를 실험하십시오. 머리? 몸에? 바디 후? DOM 준비 /로드? 짐을 실은?
  • 적절한 경우 비동기 및 지연 옵션을 고려하여 페이지와 상호 작용하기 전에 사용자가 경험하는 순 지연을 줄입니다. 그들이 도움이되는지 아프게되는지 테스트하십시오.
  • 최적의로드 오더를 평가할 때는 항상 고려해야 할 트레이드 오프가 있습니다. 예쁜 대 반응 형은 하나입니다.

1
링크 된 기사는 더 이상 "스타일 시트로드 블록 스크립트 실행"을 주장하지 않습니다. 더 이상 사실이 아닙니까?
Greg Greg

@Greg-여전히 그렇습니다. 스크립트는 DOM .style 속성을 쿼리 할 수 ​​있어야하므로 스타일 시트는 여전히 스크립트 실행을 차단합니다. 그들은 수있는 스크립트를 차단하지 로드 가 똑똑하면,하지만 그들은 script.onLoad 이벤트를 차단합니다.
지미 브렉-McKye

10

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>

Chrome Net 인스펙터-> 폭포

<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>

Chrome 개발 도구-> 성능


위의 사항을 염두에두고 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:                                                                                                                                            

그렇기 때문에 document.write ()가 HTMLDOM에있어 최악의 아이디어 중 하나 인 이유입니다.
brunoais

1
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load. javascript.info/… JS가 처음 인 경우 왜 같은 가정이 적용되지 않습니까? 나에게별로 이해가되지 않습니다. 실행 된 JS의 순서는 그 목적에 대해 아무 것도 말하지 않습니다.
Thorsten Schöning

4

자바 스크립트를 사용하여 테스트가 어떻게 '렌더링'되는지 정확히 모르겠습니다. 그러나 이것을 고려하십시오

귀하의 사이트에있는 한 페이지는 50k이며 이는 합리적이지 않습니다. 서버가 서쪽에있는 동안 사용자는 동해안에 있습니다. MTU는 확실히 10k가 아니므로 몇 번의 여행이있을 것입니다. 페이지와 스타일 시트를받는 데 1/2 초가 걸릴 수 있습니다. 일반적으로 (나를 위해) javascript (jquery 플러그인 등을 통해)는 CSS 이상입니다. 또한 인터넷 연결이 페이지 중간에 질식 할 때 발생하지만 무시할 수 있습니다 (때로는 발생하며 CSS 렌더링은 믿지만 100 % 확실하지는 않습니다).

CSS가 머리에 있기 때문에 추가 연결이있을 수 있으므로 페이지보다 먼저 완료 될 수 있습니다. 어쨌든 유형 동안 페이지의 나머지 부분을 차지하고 자바 스크립트 파일 (더 많은 바이트)은 스타일이 지정되지 않아 사이트 / 연결이 느리게 나타납니다.

CSS가 완료 될 때까지 JS 인터프리터가 시작하지 않더라도 자바 스크립트 코드를 다운로드하는 데 걸리는 시간이 특히 서버에서 멀어 질 때 CSS 시간이 단축되어 사이트가 예쁘지 않게 보일 수 있습니다.

작은 최적화이지만 그 이유가 있습니다.


1
서버는 동쪽 해안에 있습니다. 또한 현재 CDN을 사용하고 있다는 사실을 모릅니다.
jcolebrand

3

위의 모든 주요 답변에 대한 요약 은 다음과 같습니다.

최신 브라우저의 경우 원하는 곳에 CSS를 넣으십시오. 그들은 html 파일을 분석하고 ( 추론 적 파싱이라고 함 ) html 파싱과 동시에 CSS 다운로드를 시작합니다.

오래된 브라우저의 경우 CSS를 맨 위에 두십시오 (알몸이지만 대화 형 페이지를 먼저 표시하지 않으려는 경우).

모든 브라우저의 경우 자바 스크립트가 가능한 한 페이지 아래쪽에 배치하면 HTML 구문 분석이 중단됩니다. 바람직하게는 비동기 적으로 다운로드하십시오 (즉, 아약스 호출)

또한 자바 스크립트를 먼저 배치한다고 주장하는 (CSS를 우선적으로 배치하는 기존의 지혜와 달리) 일부 실험 결과가 있지만 더 나은 성능을 제공하지만 논리적 추론은 없으며 광범위한 적용 가능성에 대한 검증이 부족하므로 지금은 무시하십시오.

따라서 질문에 대답하려면 : 그렇습니다. JS 전에 CSS를 포함하도록 권장하는 것은 최신 브라우저에서 유효하지 않습니다. 원하는 곳에 CSS를 놓고 가능한 한 끝에 JS를 넣으십시오.


1

Steve Souders는 이미 결정적인 대답을했지만 ...

Sam의 원래 테스트와 Josh의 반복 테스트에 문제가 있는지 궁금합니다.

TCP 연결을 설정하는 데 드는 비용이 적은 대기 시간이 짧은 연결에서 두 테스트가 모두 수행 된 것으로 보입니다.

이것이 테스트 결과에 어떤 영향을 미치는지 확실하지 않으며 '정상'대기 시간 연결을 통한 테스트를 위해 폭포를보고 싶지만 ...

다운로드 된 첫 번째 파일은 해야 HTML 페이지에 사용되는 연결을 얻고, 두 번째 파일은 새 연결을 얻을 것이다 다운로드. (초기 플러싱은 역 동성을 변경하지만 여기서는 수행되지 않습니다)

최신 브라우저에서는 두 번째 TCP 연결이 추측 적으로 열리므로 연결 오버 헤드가 줄어들고 사라집니다. 이전 브라우저에서는 그렇지 않으며 두 번째 연결은 열림 오버 헤드가 있습니다.

이것이 테스트 결과에 어떤 영향을 미치는지 확실하지 않습니다.


엄청나게 드물게 파이프 라이닝을하지 않으면 연결 설정을 줄일 가능성이 거의 없습니다 ... 낮은 대기 시간에 테스트를 반복해야한다는 데 동의하십시오
Sam Saffron

이 폭포를 보면 Chrome이 필요하기 전에 두 번째 연결을 추측 적으로 여는 위치를 볼 수 있습니다. webpagetest.org/result/… ... (IE9도 동일) ... 저는 TCP가 아닌 일반적인 지연 시간을 생각했습니다-어떤 정렬 환경 테스트가 수행 되었습니까?
Andy Davies

2
Re : "Steve Souders는 이미 명확한 답변을했지만 ..."웹 진화의 것은 확실한 답변이 없다는 것입니다. :) 스크립트를로드하는 방법은 3-4 가지가 있으며 변경 사항이 있습니다. 실제로 올바른 의미론은 Steve가 "동기 JavaScript 전에 CSS 넣기"라고 말해야했을 것입니다. 그렇지 않으면 사람들은 모든 스크립트의 규칙으로 일반화하여 잘못 이해합니다.
hexalys

예. 그러나 대부분의 사람들은 스크립트를 동기식으로 포함하기 때문에 Steve의 조언은 시작하지 않은 사람들에게 좋습니다.
앤디 데이비스

1

나는 이것이 모든 경우에 사실이 아니라고 생각합니다. CSS는 병렬로 다운로드되지만 JS는 다운로드 할 수 없기 때문입니다. 같은 경우를 고려하십시오.

단일 CSS가 아닌 2 또는 3 CSS 파일을 가져 와서 다음과 같이 시도하십시오.

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

나는 css..css..js가 다른 모든 것보다 더 나은 결과를 줄 것이라고 확신합니다.


0

새로운 브라우저는 자바 스크립트 엔진, 파서 등에서 작동하여 <= IE8과 같은 고대 브라우저에서 발생하는 문제가 더 이상 관련이없는 방식으로 일반적인 코드 및 마크 업 문제를 최적화했습니다. 마크 업뿐만 아니라 JavaScript 변수, 요소 선택기 등의 사용과 관련하여 기술이 더 이상 문제가되지 않는 시점에 도달 한 상황을 볼 수 있습니다.


성능은 항상 문제입니다. 나는 스펙을 따르지 않는 브라우저가 존재한다는 것을 거의 무시합니다. 사양을 따르는 코드가 최고 속도로 작동하고 다른 코드는 작동하도록 코드를 준비합니다. 예를 들어 IE8에서만 작동한다면 괜찮습니다.
brunoais

-5

개인적으로, 나는 그러한 "민중의 지혜"를 너무 강조하지 않을 것입니다. 과거에 사실이었던 것은 지금은 사실이 아닐 수도 있습니다. 웹 페이지의 해석 및 렌더링과 관련된 모든 작업이 완전히 비동기 적이라고 가정합니다 ( "가져 오기"및 "동작")는 다른 스레드 등에서 처리 될 수있는 완전히 다른 두 가지입니다 . ) 및 어쨌든 귀하의 통제 또는 우려를 완전히 넘어서는 것입니다.

CSS 참조를 외부 스크립트에 대한 참조와 함께 문서의 "헤드"부분에 넣었습니다. (일부 스크립트는 본문에 배치하도록 요구할 수 있으며, 필요한 경우이를 준수해야합니다.)

그 외에도 ... "이 브라우저보다 더 빠르거나 느린 것 같습니다."라는 관찰이 흥미롭지 만 관련이없는 호기심으로 여기고 디자인 결정에 영향을 미치지 않도록하십시오. 너무 많은 것들이 너무 빨리 변합니다. ( 파이어 폭스 팀이 제품의 또 다른 임시 출시를 발표하기까지 몇 분이 걸렸는가에 대한 베팅을 원 하십니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.