开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情
前言
Next.js 的很大一特点就是首屏性能好,因为首屏是服务端渲染或者静态化页面直出,本篇主要分析一下 Next.js 首屏资源加载顺序,来看它在首屏渲染上做了什么优化让页面显示更快。
分析
我先贴上一份 SSG 生成的页面的 html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charSet="utf-8" />
<title>Title</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<meta name="next-head-count" content="5" />
<link rel="preload" href="/_next/static/css/8520f1841c61f5b0.css" as="style" />
<link rel="stylesheet" href="/_next/static/css/8520f1841c61f5b0.css" data-n-g="" />
<link rel="preload" href="/_next/static/css/2c988b00b1cdca34.css" as="style" />
<link rel="stylesheet" href="/_next/static/css/2c988b00b1cdca34.css" data-n-p="" /><noscript data-n-css=""></noscript>
<script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script>
<script src="/_next/static/chunks/webpack-ee7e63bc15b31913.js" defer=""></script>
<script src="/_next/static/chunks/framework-ac88a2a245aea9ab.js" defer=""></script>
<script src="/_next/static/chunks/main-c760948dd93bcd41.js" defer=""></script>
<script src="/_next/static/chunks/pages/_app-a3178476cb569be3.js" defer=""></script>
<script src="/_next/static/chunks/pages/index-bc9743d9fd9c2c08.js" defer=""></script>
<script src="/_next/static/BLXmOaA7hQwR0DZ3Rpu9h/_buildManifest.js" defer=""></script>
<script src="/_next/static/BLXmOaA7hQwR0DZ3Rpu9h/_ssgManifest.js" defer=""></script>
</head>
<body>
<div id="__next">页面内容</div>
<script id="__NEXT_DATA__"
type="application/json">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"BLXmOaA7hQwR0DZ3Rpu9h","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script>
</body>
</html>
可以看出页面资源结构如下:
head 中的 meta 信息是 next 打包注入的默认信息,favicon 和 title 忽略即可。
body 中的信息只有页面内容和记录页面页面组件 props 内容的一个 script 标签,页面内容忽略掉,记录页面页面组件 props 内容是用来客户端进行 hydrate 时用的,也不用关注。
除去上面所说,那么只剩下了 style link 和 js script,切都在 head 内。
style link 放在 head 内,是为了让页面内容显示出来时是带有样式的内容,因此需要提前加载 css 样式。至于这里每一个样式链接,都使用了 rel="preload" 进行提前加载,下面又立马使用了 rel="stylesheet" 来加载,可能会有小伙伴感到疑惑,是因为 preload 可以安排它以更高的优先级进行下载和缓存,可以去看一下 # rel=preload MDN 文档说明。
使用了 rel=preload:
未使用 rel=preload:
从图中可以看出优先级提升了不少,等待时间变短了很多,经过多次测试数据都类似。
js script 放在 head 内,但是实际上并不会影响页面的渲染,因为都添加了 defer 属性,因此 script 实际会在页面渲染完成后才会执行,不会阻塞页面的渲染,可以看下 你不知道的 script 标签的 defer 与 async 属性 这篇文章。
SSR 和 SSG 产物是完全类似的,只有加载的页面 js 和与页面内容有关部分不一样,如图所示:
到这里静态页面上的内容已经分析完毕。(注意分析的都是首屏页面渲染之前的资源加载,如果使用了 Link 组件,首屏显示完成之后还会进行预请求其他页面的资源)
总结
Next.js 致力于让页面性能和开发体验更好,除了关键资源(css样式等影响页面首屏渲染效果的内容),其他资源都会在页面渲染之后再去加载,大家都可以去尝试尝试,也能从 Next.js中 学到不少知识。
创作不易,欢迎大家➕关注➕点赞➕收藏,有问题欢迎评论区提出。