适合内联的是首屏必需、体积小、无外部依赖的资源:critical.css(≤10KB)和纯同步的theme.js;绝对不可内联fetch、React/Vue启动代码等有依赖或体积大的JS,以及受CSP限制的内联脚本和样式。

哪些资源适合内联,哪些绝对不能动
内联 <script> 和 <style> 只对「首屏必需、体积小、无外部依赖」的资源有效。CSS 中的首屏关键样式(如 header、hero 区块)可以内联;JS 中仅限极小的初始化逻辑(比如设置 data-theme、触发骨架屏),fetch、React、Vue 启动代码都别碰——它们体积大、有执行时序依赖,硬塞进 HTML 会导致解析阻塞加剧,反而更慢。
常见错误现象:Refused to execute inline script because it violates the following Content Security Policy。一旦用了 CSP(尤其生产环境),内联 JS/CSS 默认被禁,必须显式加 'unsafe-inline'(不推荐)或用 nonce/hash 白名单——这点很多人上线后才踩坑。
- ✅ 推荐内联:首屏用到的
critical.css(压缩后 ≤ 10KB)、theme.js(纯同步逻辑, - ❌ 绝对禁止:含
import/require的模块、带async或await的函数、任何调用第三方 SDK 的代码 - ⚠️ 兼容性注意:HTTP/2 下内联收益下降明显,因为多路复用已缓解请求开销;但 HTTP/1.1 环境仍值得做
怎么安全生成和注入关键 CSS
手写 critical CSS 不现实,得靠工具提取。主流方案是 Puppeteer 驱动真实浏览器渲染首屏,抓取实际用到的样式规则——不是简单截取 <head> 里的 <style>,而是模拟 viewport 尺寸 + 用户交互(如 hover 状态)后计算出的最小集合。
实操建议:
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- 用
critters(Vite/webpack 插件)或penthouse(Node CLI 工具),避免自己写 Puppeteer 脚本——容易漏伪类、媒体查询断点 - 输出前务必
minify,并检查是否混入了未使用的字体声明、@keyframes 动画(它们不会被渲染但会增大体积) - 如果站点有暗色模式切换,critical CSS 必须同时包含
@media (prefers-color-scheme: dark)规则,否则首屏闪白/闪黑
JS 内联的三个硬约束条件
能内联的 JS 必须同时满足:同步执行、无副作用、不依赖 DOM 就绪。哪怕只有一条不满足,就该扔进 <script defer> 或外部文件。
典型反例:
-
document.querySelector('.main')—— 若脚本在<head>,DOM 还没解析完,必报错 -
fetch('/api/config')—— 网络请求不可控延迟,破坏首屏可交互时间(TTI) -
new Promise(...)—— 即使没 await,也会把任务推入 microtask 队列,干扰渲染流程
安全做法:只保留类似 if (window.matchMedia('(max-width: 768px)').matches) { document.body.classList.add('mobile') } 这种纯判断逻辑,且确保所有变量/函数都在当前作用域定义(不依赖外部模块)。
内联后如何验证是否真起作用
别信 Lighthouse 分数。打开 Chrome DevTools → Network 标签页,刷新页面,过滤 doc 类型,点击 HTML 请求 → 查看 **“Preview”** 或 **“Response”**,确认 <style> 和 <script> 内容确实存在且精简;再切到 **“Coverage”**(Cmd+Shift+P → 输入 Coverage),刷新后看 CSS/JS 文件里有多少字节实际被用到——如果内联了 5KB CSS,但 Coverage 显示只有 1.2KB 被执行,说明提取过度或策略有误。
最容易被忽略的一点:服务端渲染(SSR)框架如 Next.js、Nuxt 默认会把关键 CSS 注入 <head>,但若你手动又加了一层内联,反而造成重复,增加 HTML 体积。先关掉框架的自动注入,再统一走自己的 critical pipeline。


















