Next.js实战(上)
这是我参与第五届青训营 伴学笔记创作活动的第7天。
课程重点
- CSR,SSR,SSG
- 什么是Next.js
- Next.js客户端开发
详细知识点
CSR,SSR,SSG
先科普一下B端、C端的概念:
什么是B端,C端? B的全称是Business即商家,多为企业的产品。通常是企业或商家,为工作或商业目的而使用的系统型软件、工具或平台。例如:腾讯云,阿里云,企业内部的ERP系统等等。 C的全称是Customer即消费者,多为用户的产品,个人用户或终端用户,使用的是客户端。例如:微信,抖音,拼多多等等。
- CSR:客户端渲染(Client-Side Rendering)。是常见的B端Web应用开发模式,前后端分离,服务器压力相对更轻,渲染工作在客户端进行,服务器直接返回不加工的HTML,用户在后续进行访问操作。首屏时间更长。
- SSR:服务端渲染(Server-Side Rendering)。是面对C端用户,需要支持SEO,就需使用SSR,因为可以有HTML的结构节点,对于浏览器爬虫友好。传统的服务端渲染如JSP、PHP,是由java,php负责渲染逻辑,前端只负责UI和交互。缺点是代码耦合度高,模板语言中混杂编程语言,维护困难。
- 同构SSR:BFF(Backend For Frontend)即服务于前端应用的后端。如:Nuxt.js(Vue)、Next.js(React).前后端一体化,一套Vue/React代码在服务器上运行一遍,到达浏览器又运行一遍。前端后端都要参与渲染,而且首次渲染出的HTML要一样。
- SSG:静态站点生成(Static Site Generation),在构建的时候直接把结果页面输出html到磁盘,每次访问直接把html返回给客户端,相当于一个静态资源。相比于SSR,由于不需要每次请求都由服务器端处理,所以可以大幅度减轻服务端的压力。缺陷在于只能用于偏静态的页面,无法生成与用户相关的内容,也就是所有用户访问的页面都是相同的。
SSR,SSG的优势:利于SEO,浏览器的推广程度,取决于搜索引擎对站点检索的排名,搜索引擎可以理解是一种爬虫,它会爬取指定页面的html,并根据用户输入的关键词对页面内容精选排序检索,最后形成我们看到的结果;更短的首屏时间,只需要请求到一个html文件就能展示出页面,虽然在服务器上会调取接口,但服务器之间的通信要远比客户端快,甚至是同一台服务器上的本地接口调取。因为不再需要请求大量js文件,这就使SSR/SSG可以拥有更短的首屏时间。
什么是Next.js
基于React提供的相关服务器端渲染API实现,整个过程实现比较繁琐重复,从零实现对新手不友好。迫切需要一个封装好的集合来快速上手服务器端渲染。
Next.js是一个构建于Node.js之上的开源Web开发框架,支持基于React的Web应用程序功能,例如服务端渲染和生成静态网站。
Next.js客户端开发
初始化项目
npx create-next-app@latest --typescript
# or
yarn create next-app --typescript
项目结构
Layout:在入口文件_app.tsx中导入layout布局组件,可以实现每个页面公共的页头和页尾。
import '@/styles/globals.css'
import type { AppProps } from 'next/app'
import Layout from '@/components/layout'
export default function App({ Component, pageProps }: AppProps) {
return <Layout>
<Component {...pageProps}/>
</Layout>
}
文件式路由
Next.js有一个基于页面概念的基于文件系统的路由器。当一个文件被添加到pages目录中时,它会自动作为一个路径可用。
预定义路由优先级更高,预定义路由能直接匹配的路由就不会分发给下面的动态路由。
BFF层的文件式路由:
BFF,作为服务器构建包,不影响客户端构建bundle的体积。相同的router生成方式,不过是作为API层访问,而不是page.
路由跳转:采用next/link跳转或者useRouter跳转
import type { NextPage } from "next";
import Link from "next/link";
import style from './index.module.scss'
const Navbar:NextPage = () => {
return <div className={style.navbar}>
<ul>
<li><Link href="/">首页</Link></li>
<li><Link href="/tag">标签</Link></li>
<li><Link href="/my">我的</Link></li>
</ul>
</div>
}
export default Navbar
数据注入:
getServerSideProps、getStaticProps、getInitialProps、客户端注入。
getInitialProps:在服务端执行,只能在页面层面进行绑定,采用同构,首次渲染服务器端渲染,路由跳转使用客户端路由。
import type { NextPage } from "next";
import style from './index.module.scss'
type Data = {
address: string
}
const Home: NextPage = ({props}) => {
const list:Data[] = props.list
return <div className={style.home}>
我是首页
<ul>
{
list.map((item,index) => {
return <li key={index}>{item.address}</li>
})
}
</ul>
</div>;
}
Home.getInitialProps =async (context) => {
console.log("query",context.query)
const res = await fetch('http:127.0.0.1:3000/api/hello')
const data: {list:Data[]} = await res.json()
console.log(data);//服务端执行
return {props:data};
}
export default Home;
意味着如果使用router跳转当前页,会在客户端执行Home.getInitialProps这部分逻辑
getServeSideProps: SSR,与getInitialProps不同的是即使使用router跳转当前页,也只会在服务端执行这部分逻辑。
export const getServerSideProps: GetServerSideProps = async context => {
const { articleId } = context.query;
const { data } = await axios.get(`${LOCALDOMAIN}/api/articleInfo`, {
params: {
articleId,
},
});
return {
props: data, // 需要拿props包裹
};
};
getStaticProps: SSG,在服务端构建时执行,如果涉及动态路由(带参数),需要使用getStaticPaths配置的所有可能的参数情况。
export const getStaticPaths: GetStaticPaths = async () => ({
paths: [{ params: { articleId: '1' } }],
fallback: false,
});
export const getStaticProps: GetStaticProps = async context => {
const { articleId } = context.params as any;
const { data } = await axios.get(`${LOCALDOMAIN}/api/articleInfo`, {
params: {
articleId,
},
});
return {
props: data,
};
};
总结:
以上内容主要科普了B端,C端,以及CSR,SSR,SSG这些概念,然后介绍了next.js以及next.js客户端的文件式路由,路由跳转方式,数据注入等。next.js服务端开发将在下节介绍。