findxc / blog

88 stars 5 forks source link

React 官网为什么这么快 #47

Open findxc opened 3 years ago

findxc commented 3 years ago

写在开头

React 官网 源码见 https://github.com/reactjs/reactjs.org ,你会发现它是用 Gatsby 来构建的。

Build your own React 这个网站也是用 Gatsby 来构建的,源码见 https://github.com/pomber/site

Overreacted — A blog by Dan Abramov 这个网站也也是用 Gatsby 来构建的,源码见 https://github.com/gaearon/overreacted.io

如果你想先去了解一下 Gatsby ,见 The Fastest Frontend for the Modern Web | Gatsby

一些预加载/预处理资源的方式

preload

通过rel="preload"进行内容预加载 - HTML(超文本标记语言) | MDN

比如 <link as="script" rel="preload" href="/webpack-runtime-732352b70a6d0733ac95.js">

在浏览器的主渲染机制介入前就进行预加载,资源可以更早的得到加载并可用,且更不易阻塞页面的初步渲染,进而提升性能。

<head>
  <meta charset="utf-8">
  <title>JS and CSS preload example</title>

  <link rel="preload" href="style.css" as="style">
  <link rel="preload" href="main.js" as="script">

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h1>bouncing balls</h1>
  <canvas></canvas>

  <script src="main.js"></script>
</body>

as 其它可能的值:fetch、image、video 等等。

prefetch

Link types: prefetch - HTML: HyperText Markup Language | MDN

比如 <link rel="prefetch" href="/page-data/docs/getting-started.html/page-data.json" crossorigin="anonymous" as="fetch">

告诉浏览器用户未来可能需要这些资源,这样浏览器可以提前获取这些资源。

preconnect

Link types: preconnect - HTML: HyperText Markup Language | MDN

告诉浏览器会从这个域获取资源,浏览器可以提前建立连接。

比如 <link rel="preconnect" href="https://www.google-analytics.com">

dns-prefetch

Link types: dns-prefetch - HTML: HyperText Markup Language | MDN

比如 <link rel="dns-prefetch" href="https://www.google-analytics.com">

告诉浏览器会从这个域获取资源,浏览器可以提前做 DNS 解析。

如果你是使用 Gatsby 来构建网站,以上这些它会自动帮你做好,是不是特别省心。

Gatsby

Gatsby 是什么

Gatsby 是一个性能很好,开发很自由的,基于 React 和 GraphQL 来构建网站的库。一般用于构建静态网站,比如博客、企业官网等,或者说静态内容相对比较多的网站。

一些使用了 Gatsby 的网站 :Showcase of Gatsby Websites | Gatsby

在 Gatsby 中,你希望界面长什么样是完全自定义的,它会给你页面相关的数据,然后具体页面长啥样你自己写代码去实现,特别自由。

Gatsby 的另外一个很重要的特点是,它做了很多性能优化方面的事情(preload 和 prefetch 等),页面加载特别快。

它在打包的时候就生成了所有页面对应的 HTML 文件以及数据文件等,这样当你访问某个页面时,服务端可以直接返回 HTML ,另外一方面当页面中有使用它的 Link 时,会提前加载这个页面对应的数据,这样点击跳转后页面加载很快。

比如当你在 React 官网展开菜单时,会去请求菜单下面所有页面相关的数据:

Kapture 2021-04-28 at 20 47 15

Gatsby 的性能优化方面的一些介绍:Behind the Scenes: What makes Gatsby Great | Gatsby

一个简单示例

比如这个 Gatsby Starter Blog ,对应的代码在 https://github.com/gatsbyjs/gatsby-starter-blog

如果你想实际感受一下 Gatsby 是怎么工作的,可以去过一遍 Tutorial | Gatsby

Link 对应的预加载是怎么实现的

相关源码见 packages/gatsby-link/src/index.js#L77

它会监听 Link 元素出现到可见区域,出现时去预加载对应页面的一些资源,这样当用户点击跳转过去时由于资源已经请求好了页面加载会特别快。

具体实现是使用 Intersection Observer 来实现的,相关介绍见 IntersectionObserver API 使用教程 - 阮一峰的网络日志 ,有写到图片懒加载和无限滚动也可以使用这个 API 去实现。

PS,这个预加载的思路和 Building Great User Experiences with Concurrent Mode and Suspense – React Blog 这里是类似的,当跳转路由前,希望能提前加载新页面的文件和数据,如果这个真的实现了的话,React 单页面应用也会变得快很多,想想点击路由后秒开是不是有点小激动 hhh 。