Faster Marketing Pages: Removing the Render-Blocking Tailwind Script
Faster Marketing Pages: Removing the Render-Blocking Tailwind Script
Release: v1.0.69 · Ticket: PERF-24
Background
BlockManOS renders marketing content inside a sandboxed <iframe> via the MarketingIframe component. The component takes an HTML string as a prop and injects it into the iframe's srcDoc attribute — a self-contained HTML document rendered entirely in-browser without a separate network request for the iframe source.
Until v1.0.69, the generated srcDoc document included this tag in its <head>:
<script src="/tailwindcss-browser.js"></script>
The Problem
1. Render-blocking behaviour
A <script> tag placed in the <head> of an HTML document — including an inline srcdoc document — is synchronous by default. The browser will:
- Pause HTML parsing
- Fetch the script file
- Execute it
- Only then continue parsing and rendering the rest of the document
This means the entire iframe content was blocked from rendering until /tailwindcss-browser.js was fully downloaded and executed on every marketing page load.
2. The file was already empty
/tailwindcss-browser.js was originally a 271 KB Tailwind CSS browser runtime used during an early development phase when styles were applied dynamically in-browser. That approach was replaced with build-time CSS processing — Tailwind is now compiled into a static stylesheet at build time, and no browser runtime is needed.
The file had already been emptied down to a 274-byte comment-only placeholder, but the <script> reference in marketing-iframe.tsx was never removed. Every page load was therefore paying the cost of a blocking script request to fetch a file that did nothing.
The Fix
The <script src="/tailwindcss-browser.js"></script> line was removed from the srcDoc template in src/components/marketing-iframe.tsx.
A comment was added above the srcDoc definition to document the decision and prevent the tag from being re-introduced:
// NOTE: No external script tags are injected here.
// Tailwind CSS is processed at build time — no browser runtime is needed.
// The formerly referenced /tailwindcss-browser.js is an empty placeholder
// and must not be loaded as a synchronous script (would block iframe render).
const srcDoc = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<style>html,body{margin:0;padding:0;overflow:hidden}</style>
</head>
<body>${html}</body>
</html>`;
Impact
| Metric | Before | After |
|---|---|---|
Blocking scripts in iframe <head> | 1 | 0 |
| HTTP requests per marketing page load | +1 (no-op file) | 0 |
| Functional / visual change | — | None |
Also in This Release
The /api/health route was refactored to use NextResponse.json() — the idiomatic Next.js helper — replacing a manually constructed Response with JSON.stringify. Behaviour is identical; the code is simpler and more consistent with the rest of the codebase.