- 本阶段将带你学习前端圈子中口碑极佳的 React 框架以及它的一些高阶用法、组件库封装、数据流方案、服务端渲染(SSR)、静态站点生成(SSG),同时深入 React 框架内部,剖析 React 部分核心源码和实现,最后还会结合 TypeScript 和蚂蚁金服的 Ant Design 库做出实战。
模块四 React 服务端渲染专题(原生实现、Next.js 集成框架、Gatsby)
- 本模块中重点介绍 React 体系下的服务端渲染方案,其中包括原生 React 实现服务端 SSR,基于 Next.js 的集成式服务端渲染开发;除此之外,我们还会一起学习目前国外社区非常火热的静态站点生成方案(SSG):Gatsby。
任务一:ReactSSR
-
zl
-
zl
-
zl
-
zl
-
ReactSSR相关观念回顾
- 什么是客户端渲染
- CSR: Client Side Rendering
- 服务器端仅返回JSON数据,DATA和HTML在客户端进行渲染
- 什么事服务器端渲染
- SSR: Server Side Rendering
- 服务器端返回HTML,DATA 和HTML在服务器端进行渲染
- 客户端渲染存在的问题
- 首屏等待时间长,用户体验差
- 首页结构为空,不利于SEO
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ux1x9syc-1630307463408)(./img/m4/1630022480267.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eLvKJn1W-1630307463410)(./img/m4/1630022619699.jpg)]
- React SSR同构
- 同构指的是代码复用,即实现客户端和服务器端最大程度的代码复用
- 项目结构初始化
- 项目结构
- src 源代码文件夹
- client 客户端代码
- server 服务端代码
- share 同构代码
- 在资料下找到 package.lock.json package.json 复制过来
- 实现ReactSSR雏形
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LHfX8sWV-1630307463412)(./img/m4/1630023517463.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vktUU0NK-1630307463414)(./img/m4/1629887115224.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tm5qMJ4J-1630307463415)(./img/m4/1630024105147.jpg)]
- 服务器端程序webpack打包配置
- webpack 打包配置
- 问题:Node 环境不支持ESModule 模块系统,不支持JSX语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ctN2LQI1-1630307463417)(./img/m4/1630024893595.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nal9TFaZ-1630307463418)(./img/m4/1630025122557.jpg)]
- 为组件元素附加事件的方式
- 在客户端对组件进行二次“渲染”,为组件元素附加事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uss5UZpZ-1630307463419)(./img/m4/1630025996061.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qAD6xo5S-1630307463421)(./img/m4/1630025344207.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9TM6zEob-1630307463422)(./img/m4/1630025479994.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VvPazplB-1630307463423)(./img/m4/1630025647869.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-14xsWHlr-1630307463424)(./img/m4/1630025816543.jpg)]
- “web:client-build”: “webpack --config weboack.config.js --watch”
- 优化:合并webpack配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mIB9Fcv-1630307463425)(./img/m4/1630026073825.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UqZbftSg-1630307463426)(./img/m4/1630026221601.jpg)]
- 优化:合并项目启动命令
- 目的:使用一个命令启动项目,解决多个命令启动的繁琐问题,通过npm-run-all工具实现
"dev": "npm-run-all --parallel dev:*"
- 优化:服务器端打包文件体积优化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tTbye19N-1630307463427)(./img/m4/1630029395158.jpg)]
- 优化:代码拆分
- 将启动服务器代码和渲染代码进行模块拆分
- 优化代码组织方式,渲染React组件代码独立功能,所以把它从服务器端入口文件中进行抽离
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UKEoGBEU-1630307463429)(./img/m4/1630030208255.jpg)]
- 实现思路分析
- 在React SSR项目中需要实现两端路由
- 客户端路由是用于支持用户通过点击链接的形式跳转页面
- 服务器端路由是用于支持用户直接从浏览器地址栏访问页面
- 客户端和服务器端公用一套路由规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6QDztY9D-1630307463430)(./img/m4/1630030475437.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WQZc1Vp6-1630307463431)(./img/m4/1630030567230.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NCDpUlby-1630307463432)(./img/m4/1630030593209.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rPvHEyQH-1630307463433)(./img/m4/1630030978469.jpg)]
- 采用数组的方式,而不是组件,是因为在node中更容易解析
- 实现客户端路由
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8bcLMUCd-1630307463435)(./img/m4/1630031117644.jpg)]
- 实现客户端Redux
- 实现思路分析
- 在现实了React SSR的项目中需要实现两端Redux
- 客户端Redux就是通过客户端JavaScript管理Store中的数据
- 服务器端Redux就是在服务器端搭建一套Redux代码,用于管理组件中的数据
- 客户端和服务器端共用一套Reducer代码
- 创建Store的代码由于参数传递不同所以不可以共用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Krpap72P-1630307463436)(./img/m4/1630041057535.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nmKGANYM-1630307463437)(./img/m4/1630040533548.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KyiX3JYo-1630307463439)(./img/m4/1630040789493.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hZv4fvxx-1630307463440)(./img/m4/1630040825948.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rMrIJIj4-1630307463441)(./img/m4/1630040895223.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rd3IED1u-1630307463442)(./img/m4/1630040954772.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xxHobCNc-1630307463444)(./img/m4/1630041012819.jpg)]
- 用到了浏览器不支持的语法,会去填充这个语法
- 实现服务器端Redux(一)
- server/createStore.js
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9KBpBtJE-1630307463445)(./img/m4/1630041138332.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5KHfgHsQ-1630307463446)(./img/m4/1630041181193.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gl17r8VH-1630307463447)(./img/m4/1630041261982.jpg)]
- 实现服务器端Redux(二)
- 服务器端store数据填充
- 问题:服务器端创建的store是空的,组件并不能从store中获取任何数据
- 解决:服务器端在渲染组件之前获取所需要的数据
- 在组件中添加loadData方法,此方法用于获取组件所需数据,方法被服务器端调用
- 将loadData方法保存在当前组件的路由信息对象中
- 服务器端在接收到请求后哦,根据请求地址匹配出要渲染的组件路由信息
- 从路由信息中获取组件中loadData方法并调用方法获取组件所需数据
- 当数据获取完成以后在渲染组件并将结果响应到客户端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zWd0u49X-1630307463449)(./img/m4/1630042098167.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0O9s3REz-1630307463450)(./img/m4/1630042196307.jpg)]
import app from './http';
import renderer from './renderer';
import createStore from './createStore';
import routes from '../share/routes';
import { matchRoutes } from 'react-router-config';
app.get('*', (req, res) => {
const store = createStore();
// 1. 请求地址 req.path
// 2. 获取到路由配置信息 routes
// 3. 根据请求地址匹配出要渲染的组件的路由对象信息
const promises = matchRoutes(routes, req.path).map(({route}) => {
// 如何才能知道数据什么时候获取完成
if (route.loadData) return route.loadData(store)
})
Promise.all(promises).then(() => {
res.send(renderer(req, store));
})
});
- 实现服务器端Redux(三)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ePNFFT5H-1630307463451)(./img/m4/1630042685340.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J2vu652A-1630307463453)(./img/m4/1630042909756.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GIUuktPQ-1630307463454)(./img/m4/1630042969429.jpg)]
- 防止XSS攻击
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q1G1QjuX-1630307463455)(./img/m4/1630043051860.jpg)]
任务二:Next
- Next
- React 服务端渲染框架
- Next.js 是React服务端渲染应用框架,用于构建SEO友好的SPA应用
- 支持两种预报渲染模式,静态生成和服务端渲染
- 基于页面的路由系统,路由零配置
- 自动代码拆分,优化页面加载速度
- 支持静态导出,可将应用导出为静态网站
- 内置 CSS-IN-JS 库styled-jsx
- 方案成熟,可用于生产环境,世界许多公司都在使用
- 应用部署简单,拥有专属部署环境Vercel,也可以部署在其他环境
- 创建Next项目
- 创建:npm init next-app next-guide
- 运行:npm run dev
- 访问:localhost:3000
- 临时安装 create-next-app 用于创建Next.js项目,这样做的好处在于每次都会下载最新的create-next-app,创建的版本也就是最新的
- 基于页面的路由系统-创建页面
- 在Next.js中,页面是被放置在pages文件夹中的React组件
- 组件想要被默认导出
- 组件文件中不需要引入React
- 页面地址与文件地址是对应的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nwLASUa-1630307463456)(./img/m4/1630049070077.jpg)]
- 基于页面的路由系统-页面跳转
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-43zmUavy-1630307463459)(./img/m4/1630049199873.jpg)]
- 预取:页面加载完成,浏览器空闲,next回主动获取link标记对应的页面内容,当点击a标记的时候,页面已经被加载完成了
- Next应用中的静态资源访问
- 应用程序根目录中的public文件夹用于提供静态资源
- 通过以下形式进行访问
- public/images/1.jpg => /images/1.jpg
- public/css/base.css => /css/base.css
- 修改页面中的元数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQCvZs0s-1630307463460)(./img/m4/1630050525034.jpg)]
- Next应用中添加样式的方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LFUFe7bS-1630307463461)(./img/m4/1630050682792.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOvFyKaj-1630307463463)(./img/m4/1630050781219.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aOuQnoyq-1630307463464)(./img/m4/1630050915979.jpg)]
- 预渲染介绍
- 预渲染概述
- 预渲染是指数据和HTML的拼接在服务器端提前完成
- 预渲染可以使SEO更加友好
- 预渲染回带来更好的用户体验,可以无需运行JavaScript即可查看应用程序UI
- 预渲染的两种形式
- 在Next.js中支持两种形式的预渲染:静态生成和服务器端渲染
- 静态生成和服务器端渲染是生成HTML的时机不同
- 静态生成:静态生成是构建时生成HTML。以后的每个请求都共用构建时生成好的HTML
- 服务器端渲染:服务器端渲染是在请求时生成HTML,每个请求都会重新生成HTML
- 两种预渲染方式的选择
- Next.js允许开发者为每个页面选择不同的预渲染方式,不同的预渲染方式拥有不同的特点,应根据场景进行渲染
- 但建议大多数页面使用静态生成
- 静态生成一次构建,反复使用,访问速度快,因为页面都是事先生成好的
- 适用场景:营销页面、博客文章、电子商务产品列表、帮助和文档
- 服务器端渲染访问速度不如静态生成快,但是由于每次请求都会重新渲染,所以适用数据频繁更新的页面或页面内容随请求变化而变化的页面
- 实现静态生成
- 无数据和有数据的静态生成
- 如果组件不需要在其他地方获取数据,直接进行静态生成
- 如果组件想要在其他地方获取数据,在构建Next.js会预先获取组件需要的数据,然后再对组件进行静态生成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XdzbnKSv-1630307463466)(./img/m4/1630052120737.jpg)]
- 实现服务器端渲染
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOTvzuLB-1630307463467)(./img/m4/1630052529311.jpg)]
- 实现基于动态路由的静态生成
- 基于参数为页面组件生成HTML页面,有多少参数就生成多少HTML页面
- 在构建应用时,先获取用户可以访问的所有路由参数,再根据路由参数获取具体数据,然后根据数据生成静态HTML
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KyAzIA27-1630307463469)(./img/m4/1630052978021.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUsIdywP-1630307463470)(./img/m4/1630053044779.jpg)]
- fallback选项的作用
- 如果为false表示展示默认404页面,如果为true,表示服务器端接收请求的一瞬间,服务器端要获取不在范围的路由参数,根据这个路由参数获取对应的数据,再把数据传递给组件进行静态页面的生成,最后把生成的页面返回给客户端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rm1iHKCz-1630307463472)(./img/m4/1630053844814.jpg)]
- 自定义404页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SeD2TTkS-1630307463473)(./img/m4/1630053907053.jpg)]
- API Routes
-
什么是API Routes
- API Routes 可以理解为接口,客户端向服务器端发送请求获取数据的接口
- Next.js应用允许React开发者编写服务器端代码创建数据接口
-
访问API Routes:loaclhsot:3000/api/user
- 不要在getStaticPaths 或 getStaticProps 函数中访问 API Routes,因为这两个函数就是在服务器端运行的,可以直接写服务器端代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DBdPT75L-1630307463475)(./img/m4/1630054119502.jpg)]
- 案例代码初始化配置
- npm init next-app movie
- npm install @chakra-ui/core@next
- npx chakra-cli init --theme
- npm install react-icons @emotion/core @emotion/styled
- npm install @emotion/babel-preset-css-prop --save-dev
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w1ZUl9Xm-1630307463476)(./img/m4/1630071049363.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLPO1e30-1630307463477)(./img/m4/1630071103164.jpg)]
- 实现头部组件布局
- components/Header.js
- 实现导航组件布局
- components/Navigation.js
- 实现轮播图组件布局
- react-responsive-carousel
- components/Swiper.js
- 电影列表布局
- components/Movie.js
- 电影详情页面布局
- components/Layout.js
- pages/detail/[id].js
-
实现首页组件的静态生成:轮播图数据获取与展示
-
实现首页组件的静态生成:电影列表数据的获取与展示
-
实现详情页基于动态路由的静态生成
-
导出静态网站
"export": "next buid && next export
- npm run export
- 自定义Next应用服务器
- npm install express nodemon
"dev": "nodemon server/index.js"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WmptkMF0-1630307463478)(./img/m4/1630074713678.jpg)]
- 部署Next应用到Vercel平台
- vercel.com
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eGVRUSsx-1630307463480)(./img/m4/1630074891113.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DclTZ611-1630307463481)(./img/m4/1630074926722.jpg)]
任务三:Gatsby
- 什么是Gatsby以及静态应用的优势
- 静态站点生成器 基于React,能把React开发的项目转换为静态站点
- https://www.gatsbyjs.org 官网
- 解决单页应用存在的两大问题
- 首屏加载时间长
- 对搜索引擎不友好
- 将React应用转换为静态应用,这两个问题就不存在了
- 优势
- 访问速度快
- 更利于SEO搜索引擎的内容抓取
- 部署简单
- Gatsby工作流程与框架特性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtVl80Qd-1630307463487)(./img/m4/1630120098200.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4eMfZ1jv-1630307463489)(./img/m4/1630120208512.jpg)]
- 创建Gatsby项目
npm install gatsby-cli -g
- 创建项目
- 创建: gatsby new project-name https://github.com/gatsbyjs/gatsby-starter-hello-world
- 启动: gatsby develop 或 npm start
- 访问: localhost:8000
- 基于文件的路由系统
- Gatsby 框架内置基于文件的路由系统,页面组件被放置在src/pages文件夹中
- 以编程的方式创建页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFIysm3q-1630307463491)(./img/m4/1630121941987.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZhgNm3yN-1630307463493)(./img/m4/1630122720141.jpg)]
- Link组件的使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xd334j5q-1630307463495)(./img/m4/1630122994798.jpg)]
- GraphQL数据层介绍
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUW51dUi-1630307463496)(./img/m4/1630130106038.jpg)]
- 在组件中从数据层中查询数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-121vUMzE-1630307463498)(./img/m4/1630130728726.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PpQN2cDz-1630307463500)(./img/m4/1630130794152.jpg)]
- Gatsby框架中和插件相关的一些概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0rZW2u7B-1630307463502)(./img/m4/1630131050432.jpg)]
- 将本地JSON文件数据添加到数据层中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c3qvdP7G-1630307463503)(./img/m4/1630131355967.jpg)]
- gatsby-config.js
- 图像优化
- 图像文件和数据文件不在源代码中的同一位置
- 图像路径基于构建站点的绝对路径,而不是相对于数据的路径,难以分析出图片的真实位置
- 图像没有经过如何优化操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6nJRWHdQ-1630307463504)(./img/m4/1630131816788.jpg)]
- 将本地markdown文件作为数据源构建文章列表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HrQ3Htjj-1630307463506)(./img/m4/1630132258320.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uycfgDca-1630307463507)(./img/m4/1630132305048.jpg)]
- 以编程方式为所有md数据节点添加slug属性
- 构建文章详情
- 重新构建查询数据,添加slug作为请求标识,slug值为文件名称
- gatsby.md => /posts/gatsby
- react.md => /posts/react
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PG0r5Jkb-1630307463508)(./img/m4/1630132852182.jpg)]
- gatsby-node.js
- 根据slug构建文章详情页
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPgrGGqH-1630307463510)(./img/m4/1630133239158.jpg)]
- 解决markdown文件中的图片显示优化问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3RguqN6-1630307463511)(./img/m4/1630133720457.jpg)]
- 将CMS作为Gatsby应用程序的外部数据源
- 从 Strapi中获取数据
- 创建项目: npx create-strapi-app 项目名称
- https://github.com/strapi/strapi
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iPlZgwB8-1630307463513)(./img/m4/1630134148648.jpg)]
- 开发数据源插件-获取外部数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-myDqcEvZ-1630307463514)(./img/m4/1630136431787.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MhX06RfO-1630307463515)(./img/m4/1630136561813.jpg)]
- plugins/gatsby-source-mystrapi/gatsby-node.js
- npm init -y
- npm install axios
- npm i pluralize
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kWb12KTt-1630307463516)(./img/m4/1630136829289.jpg)]
- 开发数据源插件-添加数据至数据层
- npm install gatsby-node-helpers
const axios = require("axios")
const pluralize = require("pluralize")
const createNodeHelper = require("gatsby-node-helpers").default
async function sourceNodes({ actions }, configOptions) {
const { createNode } = actions
const { apiUrl, contentTypes } = configOptions
// Post -> posts Product -> products
const types = contentTypes
.map(type => type.toLowerCase())
.map(type => pluralize(type))
// 从外部数据源中获取数据
let final = await getContents(types, apiUrl)
for (let [key, value] of Object.entries(final)) {
// 1. 构建数据节点对象 allPostsContent allProductsContent
const { createNodeFactory } = createNodeHelper({
typePrefix: key,
})
const createNodeObject = createNodeFactory("content")
// 2. 根据数据节点对象创建节点
value.forEach(item => {
createNode(createNodeObject(item))
})
}
}
async function getContents(types, apiUrl) {
const size = types.length
let index = 0
// {posts: [], prodcuts: []}
const final = {}
// 初始调用
await loadContents()
async function loadContents() {
if (index === size) return
console.log(`${apiUrl}/${types[index]}`)
let { data } = await axios.get(`${apiUrl}/${types[index]}`)
final[types[index++]] = data
await loadContents()
}
return final
}
module.exports = {
sourceNodes,
}
- 开发数据转换插件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rjLV0p7v-1630307463518)(./img/m4/1630137713185.jpg)]
- npm i xml2js
- npm install gatsby-node-helpers
- plugins/gatsby-transformer-xml
const { parseString } = require("xml2js")
const { promisify } = require("util")
const parse = promisify(parseString)
const createNodeHelpers = require("gatsby-node-helpers").default
async function onCreateNode({ node, loadNodeContent, actions }) {
const { createNode } = actions
// 判断node是否是我们需要转换的节点
if (node.internal.mediaType === "application/xml") {
let content = await loadNodeContent(node)
let obj = await parse(content, {
explicitArray: false,
explicitRoot: false,
})
const { createNodeFactory } = createNodeHelpers({
typePrefix: "XML",
})
const createNodeObject = createNodeFactory("parsedContent")
createNode(createNodeObject(obj))
}
}
module.exports = {
onCreateNode,
}
- SEO优化
- react-helmet 是一个组件,用于控制页面元数据,这对于SEO非常重要
- 此插件用于页面元数据添加到Gatsby构建的静态HTML页面中
npm install gatsby-plugin-react-helmet react-helmet
- 配置 gatsby-config.js
- “gatsby-plugin-react-helmet”,
- components/SEO.js
import React from "react"
import { graphql, useStaticQuery } from "gatsby"
import { Helmet } from "react-helmet"
export default function SEO({ title, description, meta, lang }) {
const { site } = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
description
}
}
}
`)
const metaDescription = description || site.siteMetadata.description
return (
<Helmet
htmlAttributes={{ lang }}
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: "description",
content: metaDescription,
},
].concat(meta)}
/>
)
}
SEO.defaultProps = {
description: "",
meta: [],
lang: "en",
}
- 让Gatsby应用支持less
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZHpAt41-1630307463519)(./img/m4/1630139171544.jpg)]
-
案例实现方式介绍
-
创建realworld项目
- gatsby new realworld https://github.com/gatsbyjs/gatsby-starter-hello-world
- npm start 如果报错
- rm package-lock.json
- rm -rf node-modules
- npm install
- code .
- 构建案例所需组件
- https://github.com/gothinkster/realworld-starter-kit/blob/master/FRONTEND_INSTRUCTIONS.md
- html to jsx 安装这个vscode插件
- 把.cache 文件夹下 default-html.js 文件复制到src下改成html.js
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4mWE5wF-1630307463521)(./img/m4/1630140997307.jpg)]
- 动态的给每一个页面组件添加布局组件
- 在根目录下创建文件.eslintrc 解决警告
- 在案例中配置Redux
npm install redux react-redux
- src/store/createStore.js
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4U0Rypqa-1630307463522)(./img/m4/1630141505873.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QQllEWub-1630307463523)(./img/m4/1630141584305.jpg)]
-
实现登录(一)
-
实现登录(二)
-
同步用户状态
-
实现客户端路由
npm install gatsby-plugin-create-client-paths
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGAFZHZd-1630307463525)(./img/m4/1630143022360.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SIb8XSkW-1630307463526)(./img/m4/1630143186747.jpg)]
- 受保护的客户端路由
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UutZ1BDo-1630307463527)(./img/m4/1630143530559.jpg)]
-
文章列表实现思路分析
-
通过数据源插件获取外部文章列表数据
-
将文章列表数据添加至数据层
-
根据文章列表数据创建带分页的文章列表页面
-
组件查询数据显示数据-1
-
动态获取文章列表数据
-
创建文章详情页面
-
创建动态文章详情页面