Panduan Render-Blocking Resources

What render-blocking resources adalah, how CSS dan synchronous JavaScript delay critical rendering path, why itu hurts Core Web Vitals (dan indirectly SEO), cara temukan them, dan cara fix them dengan async, defer, critical CSS, dan media kueri.

Pertama kali diterbitkan: 26 Jun 2026 · Terakhir diperbarui: 3 Agu 2026 · Advanced
Bahasa

Render-blocking resources adalah CSS dan synchronous JavaScript files sebuah browser harus download dan process sebelum ini dapat paint anything. sebuah applicable stylesheet di head adalah render-blocking oleh default; sebuah <script> di head without async atau defer adalah parser-blocking oleh default (sebuah related tetapi formally distinct mechanism dari HTML spec's explicit blocking="render" _(terjemahan)_ “render” attribute). async memuat di parallel dan runs when ready (unordered); defer memuat di parallel dan runs setelah parsing, di order; module scripts defer oleh default. mereka dapat delay pertama Contentful Paint dan Largest Contentful Paint, dan LCP adalah digunakan oleh Google's Core Web Vitals peringkat sistem — sebuah tiebreaker, not sebuah documented dominant peringkat factor. semua eligible 200-status halaman enter Google's rendering queue regardless dari whether JavaScript adalah present; Google fetches di sebagian besar 2 MB per non-PDF URL (including headers), separately untuk setiap referenced file, which adalah sebuah fetch limit, not sebuah render-blocking-spesifik penalty. temukan them dengan saat ini Lighthouse 13 'Render blocking permintaan' Insight dan Chrome DevTools Coverage tab; fix oleh deferring non-critical JS, inlining hanya critical CSS where sebuah trace menampilkan ini adalah bottleneck, dan menggunakan media attributes untuk conditional stylesheets — lalu re-test pada sebuah repeated trace.

TL;DR — Render-blocking resources delay sebuah halaman’s pertama paint. sebuah applicable CSS stylesheet di <head> blocks oleh default (non-matching media, disabled, atau dynamic insertion dengan no explicit blocking="render" don’t). sebuah parser-inserted classic <script> without async/defer adalah parser-blocking oleh default — pausing HTML parsing — which adalah sebuah related tetapi distinct mechanism dari formal “render-blocking” (terjemahan) “render-blocking” attribute model. async memuat di parallel dan executes when downloaded (unordered, dapat interrupt parsing); defer memuat di parallel dan executes setelah HTML adalah parsed (di order); module scripts defer oleh default. ini delays dapat push back FCP dan LCP, dan LCP adalah digunakan oleh Google’s peringkat sistem — tetapi ini adalah sebuah tiebreaker, not sebuah dominant factor, dan Google documents no direct render-blocking peringkat weight. Google fetches di sebagian besar 2 MB per non-PDF URL (including headers), separately untuk setiap referenced JS/CSS file — sebuah truncation boundary, not sebuah render-blocking-spesifik penalty — dan semua eligible 200-status halaman enter Google’s rendering queue whether atau not mereka gunakan JavaScript. temukan blockers dengan saat ini Lighthouse 13 “Render-blocking requests” (terjemahan) “Render-blocking permintaan” Insight dan DevTools Coverage tab; fix dengan defer, critical CSS hanya where sebuah trace menampilkan ini adalah bottleneck, media attributes, dan menghapus unused code — lalu re-test dengan sebuah repeated, matched trace.

Evidence for this claim Stylesheets participate in the critical rendering path and can block first render until CSS is processed. Scope: Current official or standards documentation. Confidence: high · Verified: web.dev: Critical rendering path Evidence for this claim Classic scripts without async or defer can block HTML parsing while fetched and executed. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: script element

critical rendering path

untuk draw sebuah halaman, sebuah browser runs sebuah fixed sequence: parse HTML ke DOM, parse CSS ke CSSOM, combine them ke sebuah render tree, lay ini out, dan paint. itu sequence adalah critical rendering path, dan anything itu stalls ini delays pertama pixel. sebagai Google’s Ilya Grigorik framed ini, “optimizing the critical rendering path refers to prioritizing the display of content that relates to the current user action.” (terjemahan) “optimizing critical rendering path refers untuk prioritizing display dari konten itu relates untuk saat ini pengguna tindakan.” Render-blocking resources adalah things sitting di itu path dengan mereka hand up, membuat browser wait.

CSS adalah render-blocking oleh default — when ini adalah applicable

browser akan not paint styled konten until ini memiliki CSSOM dibangun dari setiap applicable blocking stylesheet, dan MDN’s <link> reference adalah explicit tentang scope: “only link elements in the document’s <head> can possibly block rendering. By default, a link element with rel="stylesheet" in the <head> blocks rendering when the browser discovers it during parsing.” (terjemahan) “hanya undefined elements di document’s undefined dapat possibly block rendering. oleh default, sebuah undefined element dengan undefined di undefined blocks rendering when browser discovers ini selama parsing.” dari web.dev’s mengoptimalkan LCP guide: “Style sheets loaded from the HTML markup will block rendering of all content that follows them.” (terjemahan) “Style sheets dimuat dari HTML markup akan block rendering dari semua konten itu mengikuti them.” ini adalah intentional — painting unstyled HTML pertama dan re-styling ini produces sebuah ugly flash — tetapi “by default” (terjemahan) “oleh default” memiliki nyata edges:

  • sebuah stylesheet dengan sebuah non-matching media attribute (e.g. media="print" pada sebuah screen visit) adalah fetched tetapi doesn’t block.
  • sebuah stylesheet dengan disabled set isn’t dimuat atau applied until Anda jelas attribute.
  • sebuah stylesheet ditambahkan dynamically via script isn’t render-blocking unless Anda juga set blocking="render" pada ini explicitly — dynamic insertion opts out dari default.

di dalam -nya applicable scope, sebuah bloated blocking stylesheet dapat masih hold whole halaman hostage: when ini takes longer untuk muat daripada Anda LCP image itself, LCP element dapat’t render bahkan setelah -nya own resource memiliki finished downloading.

Scripts: parser-blocking oleh default, formally render-blocking pada permintaan

sebuah parser-inserted classic <script> di <head> without async atau defer adalah parser-blocking oleh default: browser stops membangun DOM, fetches script, executes ini, dan hanya lalu resumes. Google’s legacy PageSpeed docs spell out cost: “whenever the parser encounters a script it has to stop and execute it before it can continue parsing the HTML. In the case of an external script the parser is also forced to wait for the resource to download, which may incur one or more network roundtrips and delay the time to first render of the page.” (terjemahan) “whenever parser encounters sebuah script ini memiliki untuk stop dan execute ini sebelum ini dapat continue parsing HTML. di case dari sebuah external script parser adalah juga forced untuk wait untuk resource untuk download, which dapat incur one atau more network roundtrips dan delay time untuk pertama render dari halaman.” sebagai mengoptimalkan LCP guide puts ini bluntly, “it is almost never necessary to add synchronous scripts… to the <head> of your pages.” (terjemahan) “ini adalah almost tidak pernah necessary untuk tambahkan synchronous scripts… untuk undefined dari Anda halaman.”

Worth menjadi precise here: parser-blocking dan HTML spec’s formal render-blocking attribute model adalah related tetapi distinct mechanisms. Per MDN’s <script> reference, blocking="render" token “explicitly indicates that certain operations should be blocked until the script has executed,” (terjemahan) “explicitly indicates itu certain operations seharusnya menjadi blocked until script memiliki executed,” dan “only script elements in the document’s <head> can possibly block rendering” (terjemahan) “hanya undefined elements di document’s undefined dapat possibly block rendering” ini cara — “if such a script element is added dynamically via script, you must set blocking = "render" for it to block rendering.” (terjemahan) “jika such sebuah undefined element adalah ditambahkan dynamically via script, Anda harus set undefined untuk ini untuk block rendering.” dalam praktik, sebuah default parser-blocking <head> script sudah stalls pipeline enough itu distinction rarely perubahan what Anda melakukan tentang ini; ini penting mainly untuk dynamically inserted scripts, which perlu explicit attribute untuk participate, dan browser mendukung untuk blocking="render" adalah masih limited dan worth memeriksa sebelum Anda rely pada ini.

One more default worth knowing: type="module" scripts defer oleh default (no defer attribute needed) unless async adalah ditambahkan untuk perubahan itu scheduling.

async vs defer — mereka adalah not yang sama

ini adalah single sebagian besar berguna distinction untuk fixing render-blocking JS. Both download script di parallel dengan HTML parsing, so neither adalah parser-blocking selama download. mereka differ di execution:

  • async — executes immediately when download finishes, which dapat interrupt parsing, dan runs di no guaranteed order. baik untuk truly independent ketiga-party scripts (analytics, ads) itu don’t touch Anda DOM atau depend pada setiap lainnya.
  • defer — executes setelah HTML adalah fully parsed, di document order. baik untuk scripts itu depend pada DOM atau pada setiap lainnya (sebagian besar dari Anda own code).
  • Module scripts (type="module") — deferred oleh default; tambahkan async jika Anda specifically ingin module-ready-order execution instead.

jika Anda remember one aturan: defer untuk anything ordered atau DOM-dependent, async hanya untuk fire-dan-forget ketiga-party scripts.

How ini affects SEO

chain adalah nyata tetapi memiliki nyata boundaries. Don’t overstate ini di either direction:

  1. Render-blocking resources delay pertama Contentful Paint — when apa pun konten pertama appears.
  2. mereka dapat delay Largest Contentful Paint — Google’s primary memuat metric — though sebuah flagged resource isn’t proof ini adalah dominant field bottleneck, dan menghapus ini doesn’t guarantee sebuah better LCP; Lighthouse Insight reports sebuah potential delay dari one observed trace, not sebuah guaranteed field effect.
  3. LCP adalah sebuah Core Web Vitals metric, diukur di 75th percentile dari nyata data lapangan di atas 28 days, dan Google says Core Web Vitals “are used by our ranking systems.” (terjemahan) “adalah digunakan oleh kami peringkat sistem.” “good” (terjemahan) “baik” LCP threshold adalah ≤2,5 s.
  4. Google’s halaman-experience documentation doesn’t define sebuah direct render-blocking peringkat weight, chain, atau tiebreaker, dan gives no peringkat guarantee dari menghapus blockers — ini says relevance masih wins, tetapi “having a great page experience can contribute to success in Search” (terjemahan) “having sebuah great halaman experience dapat contribute untuk success di Search” when there’s lots dari similarly helpful konten untuk choose dari.

pertahankan weighting honest. Martin Splitt’s line adalah right calibration: “a fast website is a little more helpful than a slow website,” (terjemahan) “sebuah fast situs web adalah sebuah little more helpful daripada sebuah slow situs web,” tetapi “content is still the king.” (terjemahan) “konten adalah masih king.” Fixing sebuah resource itu’s genuinely delaying Anda LCP adalah worth doing untuk UX dan sebagai one input among banyak Google’s sistem weigh — ini adalah not sebuah lever dengan sebuah documented, dedicated peringkat multiplier.

crawl-efficiency angle — corrected

I previously framed heavy render-blocking JavaScript sebagai something itu “pushes” (terjemahan) “pushes” atau “forces” (terjemahan) “forces” halaman ke Google’s rendering queue. itu’s not accurate, dan ini adalah worth correcting plainly: Google’s saat ini JavaScript SEO documentation states itu “all pages with a 200 HTTP status code are sent to the rendering queue, no matter whether JavaScript is present on the page.” (terjemahan) “semua halaman dengan sebuah 200 HTTP kode status adalah dikirim untuk rendering queue, no penting whether JavaScript adalah present pada halaman.” setiap eligible halaman goes melalui itu queue — render-blocking resources don’t buat special pada-ramp ke ini.

Evidence for this claim Google's current guidance says all eligible pages returning HTTP 200 enter its rendering queue regardless of whether JavaScript is present, so render-blocking JavaScript should not be claimed to force a page into that queue. Scope: crawling, rendering, indexing Confidence: high · Verified: Understand the JavaScript SEO basics

What resource jenis melakukan perubahan adalah how much berfungsi happens once sebuah halaman reaches rendering. Onely’s experiment ditemukan Google needed 9× longer untuk fully crawl JavaScript-rendered halaman daripada identical HTML halaman (313 hours vs. 36 hours) di mereka test setup, because “pages that require rendering have to wait in a rendering queue in addition to the crawl queue which applies to all pages.” (terjemahan) “halaman itu memerlukan rendering memiliki untuk wait di sebuah rendering queue di addition untuk crawl queue which applies untuk semua halaman.” Treat itu sebagai evidence itu konten requiring rendering sisi klien carries sebuah nyata time-untuk-indeks cost di itu study — not sebagai proof itu sebuah spesifik render-blocking CSS atau JS file adalah what triggers queueing.

pada file size: Google’s crawling documentation describes sebuah 2 MB fetch limit per non-PDF URL, including header HTTP, applied separately untuk setiap individual resource ini permintaan — so sebuah besar <head> script atau stylesheet gets -nya own 2 MB counter, not sebuah shared budget dengan HTML. itu’s sebuah fetch/truncation boundary, not sebuah “processing limit,” (terjemahan) “processing limit,” dan Google doesn’t document sebuah special crawl atau pengindeksan penalty tied specifically untuk render-blocking resources beyond itu umum truncation risk.

Evidence for this claim Google currently fetches up to 2 MB, including HTTP headers, for each individual non-PDF URL; referenced resources such as JavaScript and CSS have separate per-URL counters and the same 2 MB fetch limit. This supports a per-resource fetch boundary, but not the article's 'processing limit' wording or a special crawl/indexing penalty for render-blocking resources. Scope: fetching and WRS Confidence: high · Verified: Inside Googlebot: crawling 101

Worth debunking while kami’re here: Google’s renderer memiliki no fixed timeout. sebagai I’ve documented di my JavaScript SEO guide, “there is no fixed timeout for the renderer. It runs with a sped-up timer to see if anything is added at a later time.” (terjemahan) “tidak ada fixed timeout untuk renderer. ini runs dengan sebuah sped-up timer untuk see jika anything adalah ditambahkan di sebuah later time.” concern isn’t sebuah 5-kedua cutoff — ini adalah queueing delay sebelum rendering bahkan begins.

ini bahkan reaches AI crawler now. Gary Illyes argued di 2026 itu “if sites used relatively good HTML and no JavaScript (or SSR), both base model training, and web and agentic RAG would be a piece of cake from raw data processing perspective.” (terjemahan) “jika situs digunakan relatively baik HTML dan no JavaScript (atau SSR), both base model training, dan web dan agentic RAG akan menjadi sebuah piece dari cake dari raw data processing perspective.” Heavy client-side JS adalah sebuah masalah well beyond Googlebot.

cara temukan them

  • Chrome DevTools performa panel / Lighthouse 13 — saat ini “Render blocking requests” (terjemahan) “Render blocking permintaan” Insight (which, sebagai dari Lighthouse 13, adalah where older “Eliminate render-blocking resources” (terjemahan) “Eliminate render-blocking resources” audit moved) flags scripts di <head> missing async/defer dan stylesheets without sebuah disabled atau non-matching media attribute, dan estimates ms Anda’d save dari one observed trace. Connor Clark’s write-up puts ini plainly: “render-blocking requests are network requests that prevent a page’s initial render, potentially delaying Largest Contentful Paint.” (terjemahan) “render-blocking permintaan adalah network permintaan itu mencegah sebuah halaman’s initial render, potentially delaying Largest Contentful Paint.” jika Anda’re reading older PageSpeed Insights output itu masih says “Eliminate render-blocking resources,” (terjemahan) “Eliminate render-blocking resources,” ini adalah yang sama underlying signal di bawah pre-Lighthouse-13 name.
  • Chrome DevTools Coverage tab — marks bytes green (critical — digunakan untuk pertama paint) atau red (unused di pertama paint). Lots dari red CSS/JS adalah Anda candidate list.
  • WebPageTest waterfall — lihat everything sebelum Start Render line.
  • Run ini more daripada once — sebuah single trace reflects itu run’s consent-manager state, ketiga-party tag muat, cache state, dan CSP perilaku. Repeat trace (cold dan warm) sebelum treating one flagged resource sebagai sebuah fixed fact.
Read a waterfall from left to right: first paint cannot cross the boundary until every required blocking request has finished.

An illustrative navigation contains HTML from 0 to 180 milliseconds, blocking CSS from 120 to 420 milliseconds, synchronous JavaScript from 210 to 610 milliseconds, a non-blocking analytics request from 250 to 500 milliseconds, and font loading from 420 to 610 milliseconds. First paint occurs at 610 milliseconds. The example explains timing mechanics; it is not a live trace.

cara fix them

JavaScript

  • defer non-critical scripts<script src="app.js" defer></script>. Parallel download, ordered execution setelah parse. safe default untuk Anda own JS.
  • async untuk independent ketiga-party scripts<script src="analytics.js" async></script>. hanya when order dan DOM-readiness genuinely don’t penting.
  • Move scripts untuk end dari <body> — older fallback when Anda dapat’t tambahkan attributes; parser reaches them last.

CSS — sebagai conditional decisions, not blanket patterns

  • Inline critical CSS hanya when sebuah trace menampilkan CSS adalah actual bottleneck — extract styles needed untuk above—fold konten ke sebuah inline <style> block so pertama paint perlu no round-trip. Google’s own caution applies: “inlining CSS is an advanced performance technique that can improve performance, but can also lead to bugs if not implemented properly.” (terjemahan) “inlining CSS adalah sebuah advanced performa technique itu dapat meningkatkan performa, tetapi dapat juga lead untuk bugs jika not implemented properly.” Inline hanya critical subset, name sebuah owner untuk regenerating ini when templates perubahan, dan periksa untuk drift di seluruh halaman states — sebuah critical-CSS snapshot itu goes stale silently reintroduces flashes dari unstyled konten atau missing styles.
  • Defer rest, matching permintaan exactly — muat full stylesheet dengan <link rel="preload" as="style" onload="this.rel='stylesheet'"> pattern. sebuah preload hanya gets reused untuk eventual permintaan jika URL, as, type, dan crossorigin/CORS mode match — sebuah mismatched hint causes browser untuk fetch resource twice alih-alih skipping round-trip.
  • media attributesmedia="print" atau media="(min-width: 900px)" lets browser download sebuah stylesheet without blocking render when kueri doesn’t match.
  • hapus unused CSS dan minify — less untuk block pada, faster downloads.
  • Verify sebelum shipping — re-periksa untuk duplicate/unused fetches, FOUC, dan baru layout shift setelah apa pun critical-CSS atau preload perubahan, pada sebuah repeated trace, not sebuah single lucky run.

Platform-spesifik (WordPress) — WP Rocket (delay/defer JS, mengoptimalkan CSS delivery), Autoptimize (async/defer JS, inline critical CSS), dan Async JavaScript implement semua dari above melalui plugin UI. mereka’re applying yang sama async/defer/critical-CSS techniques — knowing what setiap setting melakukan adalah how Anda hindari breaking Anda theme.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.