认识SSR
1.为什么需要SSR呢?
单页面富应用的局限:
- 之前我们开发的应用程序,如果右键直接查看源代码,可以看到上面几乎没有什么内容
- 但是我们为什么可以看到大量的内容呢?
- 因为当我们请求下来静态资源之会执行
JS
,JS
会去请求数据,并且渲染我们想看到的
但是这个过程存在两个问题:
- 问题一:首屏显示速度较慢
- 问题二:不利于
SEO
优化
如何解决这个问题呢?
- 使用服务端渲染
2.认识SSR
- SSR(Server Side Rendering,服务端渲染),指的是页面在服务器端已经生成了完成的HTML页面结构,不需要浏览器解析
- 对应的是CSR(Client Side Rendering,客户端渲染),我们开发SPA页面通常依赖的就是客户端渲染
- 早期的服务端渲染包裹PHP、JSP、ASP等方式,但是在目前 "前后端分离" 的开发模式下,前端开发人员不太可能再去学习PHP、 JSP等技术来开发网页
- 不过我们可以借助于
Node
来帮助我们执行JavaScript
代码,提前完成页面的渲染
3.同构
- 什么是同构?
- 一套代码既可以在服务端又可以在客户端运行,这就是同构应用;
- 同构是一种SSR的形态,是现带SSR的一种表型形式;
- 当用户发出请求时,先在服务器通过SSR渲染出首页的内容;
- 但是对应的代码同样在可以在客户端执行;
- 执行的目的包括事件绑定等以及其它页面切换时也可以在客户端被渲染;
- 期望在服务器上拿到
html
页面并发送请求,之后的的结果直接响应给客户端
之前是由浏览器执行的-》现在由node.js来完成
index.html
1.请求js文件
2.执行js文件
3.ajax 请求
4.继续执行js遍历数据,生成html结构
Next.js
1.使用React SSR
使用React SSR主要有两种方式:
- 方式一: 手动搭建一个
SSR
框架; - 方式二: 使用已经成熟的
SSR
框架:Next.js
- 方式一: 手动搭建一个
安装
Next.js
框架的脚手架:npm install -g create-next-app
创建
Next.js
项目create-next-app next-demo
package.json
文件↓
2.首页的展示
Next.js
默认已经给我们配置好了路由映射关系:- 路径和组件的映射关系;
- 这个映射关系就是在
pages
中配置相关的组件都会自动生成对应的路径; - 默认
page/index.js
是页面的默认路径:
3.关于页面和页面跳转
- 定义About页面
- 从Home页面跳转到About页面
4.Layout组件
我们发现home和about是两个相互独立的组件:
- 如果他们有一些公共的内容: 比如头部、尾部都是一样的,是否每个地方都需要写一遍呢?
有两种解决方案:
- 方案一: 自定义一个Layout的组件,将公共的内容放到Layout中;
- 方案二: 在 _app 中编写公共部分的内容;
5.Next.js支持各种样式
- 方式一: 全局样式引入
- 方式二:
module.css
- 方式三: 默认集成
styled-jsx
<style>{`
p {
color: #f879c6;
}
`}</style>
方式四: 其他
css in js
方案,比如styled-components
styled-components在Next服务器上渲染的的问题:
- 组件使用了
styled-components
显示是没有问题的,这是在客户端进行渲染的,但是只要我们手动刷新,className
就不进行匹配,这是因为在服务端渲染和在客户端渲染的className
不匹配
- 组件使用了
- 如何解决:引入相关依赖,创建和编辑
.babelrc
文件 yarn add styled-components
yarn add -D babel-plugin-styled-components
- 编辑
.babelrc
文件
{
"presets": [
"next/babel"
],
"plugins": [
["styled-components"]
]
}
6.路由的补充
路由的嵌套(子路由):
- 文件夹的嵌套,最后就可以形成子路由;
路由的传参:
- Next.js中无法通过 /user/:id 方式传递参数;
- 只能通过 /user?id=123 的方式来传递参数
传递参数由两种方法:
- Link中的路径
- Router.push( pathname,query )
<Link href={`/recommend?id=${item}`} key={item}>
<a>推荐数据{item}</a>
</Link>
import Router from 'next/router'
const itemClick = (item) => {
Router.push({
pathname: 'recommend',
query: {
id: item
}
})
}
7.数据请求
- getInitialProps
// 返回一个promise对象或者返回对象
Home.getInitialProps = async (props) => {
const res = await axios({ url: 'http://39.102.36.212:3000/banner' })
return {
name: 'why',
banners: res.data.banner,
recommends: res.data.recommend.list,
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。