关于SSR框架调研
背景
调研一下remix这个SSR框架,顺便把市面上的vue和react的SSR框架都评估一下。
SSR解决什么问题
- 更好的SEO
因为SPA页面的内容是通过Ajax获取,而搜索引擎爬取工具并不会等待Ajax异步完成后再抓取页面内容,所以在SPA中是抓取不到页面通过Ajax获取到的内容的;而SSR是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面; - 更利于首屏渲染
首屏的渲染是node发送过来的html字符串,并不依赖于js文件了,这就会使用户更快的看到页面的内容。尤其是针对大型单页应用,打包后文件体积比较大,普通客户端渲染加载所有所需文件时间较长,首页就会有一个很长的白屏等待时间。
概念
- FCP: FCP (First Contentful Paint) 首次内容绘制 标记浏览器渲染来自 DOM 第一位内容的时间点,该内容可能是文本、图像、SVG 甚至 元素.
- TTI: TTI (Time to Interactive) 可交互时间: 指标用于标记应用已进行视觉渲染并能可靠响应用户输入的时间点.
CSR客户端渲染
SSR服务端渲染
从上面几张图片,我们可以看到:
- 首屏渲染CSR比SSR要慢很多
- SEO提供给搜索引擎的内容SSR比CSR要丰富得多
- 数据的获取CSR在前端通过接口可查看,而SSR在服务端不可查看
SSR框架
Vue:
- Nuxt.js
React:
- Next.js
- Remix.js
Nuxt.js
对标Next.js
2016 年 10 月 25 日,zeit.co背后的团队对外发布了Next.js,一个 React 的服务端渲染应用框架。几小时后,与 Next.js 异曲同工,一个基于Vue.js的服务端渲染应用框架应运而生,我们称之为:Nuxt.js。
我的关注点对比
Next.js(react) | Nuxt.js(vue) | Remix.js(react) | |
---|---|---|---|
静态站点生成 | ☑️内置 next export | ☑️内置 nuxt generate | 🚫不支持 |
请求接口 | ☑️fetch | ☑️axios | ☑️Fetch API Request 和 Response 接口 |
数据库访问 | ☑️支持,更倾向api接口获取 | ☑️支持,更倾向api接口获取 | ☑️支持 |
访问路由 Routing | 基于文件系统的路由 | 基于文件系统的路由,可根据文件目录自动生成路由配置 | 基于文件系统的路由 |
api路由 API Routes | pages/api目录下 | 自定义路由 | 自定义路由 |
数据加载 Data Fetching | ☑️内置 通过 getServerSideProps | ☑️内置 通过 asyncData | ☑️内置 通过 loader |
路由
Remix.js
路由地址 | 组件 |
---|---|
/ | App.js > routes/index.js |
/invoices | App.js > routes/invoices.js > routes/invoices/index.js |
/invoices/late | App.js > routes/invoices.js > routes/invoices/late.js |
/invoices/123 | App.js > routes/invoices.js > routes/invoices/$id.js |
/invoices/123/edit | App.js > routes/invoices.js > routes/invoices/$id.edit.js |
/invoices/no/match | App.js > routes/404.js |
/invoices/new | App.js > routes/invoices.new.js |
/contact | App.js > routes/contact.js |
nuxt.js
Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置
目录
1 | pages/ |
自动生成
1 | router: { |
next.js
1 | pages/index.js → / |
数据加载对比
Remix.js
每个路由模块都可以导出一个组件和一个
loader
.useLoaderData
将加载器的数据提供给您的组件
useLoaderData
这个钩子从你的路由的loader函数返回JSON解析数据
1 | import { useLoaderData } from "remix"; |
nuxt.js
1 | <template> |
next.js
1 | function Product({ products }) { |