[RFC] 支持 CriticalCSS
背景
Critical CSS 可以显著提升 FCP 和 Speed Index 的数据,实测使用后 FCP 从 1.8 -> 0.9s,原因是消除了首屏 css 对首屏渲染的阻塞,目前 rax 没有关于 Critical CSS 的官方最佳实践
关于 Critical CSS
可以看到,外链的 CSS 文件加载会阻塞页面的渲染
而将首屏用到的样式使用 <style></style> 标签内联至 head,同时将 <link rel="stylesheet" /> 标记为非阻塞的资源(或者挪到 <Root /> 后面),可以让页面提前开始渲染,可以节省中间 CSS 文件下载和解析导致的阻塞时间(这个和 SSR vs CSR 是类似的,SSR 也是节省了客户端下载和执行 JS 的时间,让首屏提前渲染)
同时这个方案还有另一个优点
如果我们对 CSS 文件进行覆盖率收集,会发现首屏往往只用到了其中 50% 左右的样式,剩余 50% 都不是首屏需要用到的(这存在额外的下载和解析开销),Critical CSS 方案可以只提取首屏用到的样式,可以避免多余的下载和解析开销
如何使用
import { CriticalCSS } from 'rax-document'
export default () => {
return <html>
<head>
<meta ...>
{ /* 自定义 CriticalCSS 的位置,这里实际渲染出来大概是这样: <style>.header {...}</style> */ }
<CriticalCSS />
</head>
<body>
<Root />
<Data />
{ /* 这里特地把 Style 放到了 Root 后面,避免阻塞首屏渲染 */ }
<Style />
<Script />
</body>
</html>
}
实现思路
从 initialHtml 中提取出所有的 class,再去页面对应的 css 文件中捞出对应的样式,作为 <style></style> 的 children
dynamic import 是不是可以满足这个需求?
dynamic import是不是可以满足这个需求?
应该解决不了,critical css 的核心是要把 <link rel="stylesheet" /> 换成 <style></style>,而且有些组件即使是首屏的,但是需要根据链接参数决定是否展示,也无法简单地归类到 dynamic import 里面
可以提一个较详细 RFC
可以提一个较详细 RFC
已更新,稍微补充了下,核心部分已经实现好了,可以直接来个 PR
可以补充下,无 document 模式应该怎么使用