Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] 支持 CriticalCSS #828

Open
fengzilong opened this issue Sep 12, 2021 · 5 comments
Open

[RFC] 支持 CriticalCSS #828

fengzilong opened this issue Sep 12, 2021 · 5 comments

Comments

@fengzilong
Copy link
Contributor

fengzilong commented Sep 12, 2021

背景

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 方案可以只提取首屏用到的样式,可以避免多余的下载和解析开销

图片来自:Defer non-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

@SoloJiang
Copy link
Contributor

dynamic import 是不是可以满足这个需求?

@fengzilong
Copy link
Contributor Author

fengzilong commented Sep 13, 2021

dynamic import 是不是可以满足这个需求?

应该解决不了,critical css 的核心是要把 <link rel="stylesheet" /> 换成 <style></style>,而且有些组件即使是首屏的,但是需要根据链接参数决定是否展示,也无法简单地归类到 dynamic import 里面

@SoloJiang
Copy link
Contributor

可以提一个较详细 RFC

@fengzilong
Copy link
Contributor Author

可以提一个较详细 RFC

已更新,稍微补充了下,核心部分已经实现好了,可以直接来个 PR

@SoloJiang
Copy link
Contributor

可以补充下,无 document 模式应该怎么使用

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants