• 客户端渲染
    • 只在浏览器上执行的渲染
    • 用JS,Vue,React创建HTML
  • 静态页面生成(SSG)
    • Static Site Generation,解决白屏问题,SEO问题
    • 无法生成用户相关内容(所有用户请求的结果都一样)
    • 页面静态化,把PHP提前渲染成HTML
  • 服务端渲染(SSR)
    • 解决白屏问题,SEO问题
    • 可以生成用户相关内容(不同用户结果不同)
    • PHP,Python,Ruby,Java后台的基本功能
    • 不同的是,Next.js的预渲染可以与前端React无缝对接
  • 注意:SSR和SSG都属于预渲染Pre-rendering

BSR 客户端渲染

客户端渲染: 数据一开始不在页面上,是在AJAX请求之后,才在页面上的。

安装axios

yarn add axios

yarn add @types/axios

创建/pages/posts/index.tsx

发送请求给之前写好的拿博客文章的api

写一个loading和文章列表为空的处理:

  1. import {NextPage} from 'next';
  2. import axios from 'axios';
  3. import {useEffect, useState} from 'react';
  4. type Post = {
  5. id: string,
  6. date: string,
  7. title: string
  8. }
  9. const PostsIndex: NextPage = () => {
  10. const [posts, setPosts] = useState<Post[]>([]);
  11. const [isLoading, setIsLoading] = useState(false);
  12. const [isEmpty, setIsEmpty] = useState(false);
  13. useEffect(() => {
  14. setIsLoading(true);
  15. axios.get('/api/v1/posts').then(res => {
  16. setPosts(res.data);
  17. setIsLoading(false);
  18. if (res.data.length === 0) {
  19. setIsEmpty(true);
  20. }
  21. }, () => {
  22. setIsLoading(false);
  23. });
  24. }, []); //空数组是为了只在第一次渲染的时候触发
  25. return (
  26. <div>
  27. <h1>文章列表</h1>
  28. {isLoading ? <div>加载中</div> :
  29. isEmpty ? <div>文章列表为空</div> :
  30. posts.map(p => <div key={p.id}>
  31. {p.id}
  32. </div>)
  33. }
  34. </div>
  35. );
  36. };
  37. ;
  38. export default PostsIndex;

效果

Next.js的三种渲染方式 - 图1

封装代码:自定义Hooks

新建一个文件/hooks/usePosts.tsx

把上面/posts/index.tsx里面的用到hooks的东西剪切过来

然后把需要的东西isLoading之类的 return出去

  1. import {useEffect, useState} from 'react';
  2. import axios from 'axios';
  3. type Post = {
  4. id: string,
  5. date: string,
  6. title: string
  7. }
  8. export const usePost = () => {
  9. const [posts, setPosts] = useState<Post[]>([]);
  10. const [isLoading, setIsLoading] = useState(false);
  11. const [isEmpty, setIsEmpty] = useState(false);
  12. useEffect(() => {
  13. setIsLoading(true);
  14. axios.get('/api/v1/posts').then(res => {
  15. setPosts(res.data);
  16. setIsLoading(false);
  17. if (res.data.length === 0) {
  18. setIsEmpty(true);
  19. }
  20. }, () => {
  21. setIsLoading(false);
  22. });
  23. }, []); //空数组是为了只在第一次渲染的时候触发
  24. return {posts,setPosts,isLoading,setIsLoading,isEmpty,setIsEmpty}
  25. };

/posts/index.tsx 就引入上面的usePosts,并解构出想要的数据

  1. import {NextPage} from 'next';
  2. import {usePost} from '../../hooks/usePosts';
  3. const PostsIndex: NextPage = () => {
  4. const {isLoading , isEmpty, posts} = usePost()
  5. return (
  6. <div>
  7. <h1>文章列表</h1>
  8. {isLoading ? <div>加载中</div> :
  9. isEmpty ? <div>文章列表为空</div> :
  10. posts.map(p => <div key={p.id}>
  11. {p.id}
  12. </div>)
  13. }
  14. </div>
  15. );
  16. };
  17. ;
  18. export default PostsIndex;

完成。

commit:https://github.com/E1FANG/next-blog-1/commit/049c472e5bf1df08816e0318d42e2a62bbba7f31

文章列表完全由前端渲染的,我们称之为客户端渲染。

客户端渲染的缺点

  1. 白屏
    1. 在AJAX得到响应之前,页面中之后loading
  1. SEO不友好
    1. 搜索引擎访问页面,看不到post数据
    2. 因为搜索引擎默认不执行JS,只能看到HTML

静态内容与动态内容

Next.js的三种渲染方式 - 图2

静态内容:红色部分,直接展示在源代码里面的。是写在代码里面的

动态内容:绿色部分,需要用JS去请求资源,再判断去展示的。是从数据库等地方拉过来的