React的SSR框架- 渲染有三种方式: BSR(客户端渲染,Browser Side Render),SSG(静态页面生成,Static Site Generation),SSR(服务端渲染,Server Side Render)
- 需要注意的是如果页面中有用js控制的部分(例如条件渲染),在SSR的时候不会直接渲染成DOM元素,虽然也能导出成静态HTML,但是仍然是前端js来控制的
基础配置
1 | npx create-next-app@latest # 初始化项目 |
next.config.js
- 每次修改必须重启应用
- 在
.env中设置的环境变量默认不会在后端渲染中被前端看到,但是如果以NEXT_PUBLIC_开头的环境变量,是能看到也能被前端直接使用的
1 | module.exports = { |
路由
路由定义
- 路由定义默认是根据pages文件夹下的文件名来的
1 | pages/blog/first-post.js → /blog/first-post |
路由常用方法
1 | import { useRouter } from 'next/router'; |
路由事件
包括:routeChangeStart、routeChangeComplete、routeChangeError、beforeHistoryChange、hashChangeStart、hashChangeComplete
页面组件
- 通过变量渲染html,需要用
<div dangerouslySetInnerHTML={{__html = ''}}
Layouts
全局定义页面的layout
所有页面都相同的layout可以这样做
1
2
3
4
5
6
7
8
9
10// pages/_app.js
import Layout from '../components/layout'
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}如果不是所有页面的layout都相同,可以参考官方文档
Head
可以在
Head里面插入全局的js,例如google analytics代码:1
2
3
4
5
6
7
8
9
10
11<Head>
<script
dangerouslySetInnerHTML={{
__html: `[google analytics tracking code here]`
}}
/>
// 字体优化,能够在编译阶段就优化字体,这样在打开页面不会因为要获取字体文件而闪一下
</Head>
Image
- 需要在
next.config.js中配置图片域名images.domains - 可以设置width、height、quality、priority、responsive自动修改图片显示大小
- 但是毕竟是后端js程序在进行转换,不如直接使用
cloudinary这样的服务速度快功能多 - 如果图片存储在第三方需要添加配置
images: loader: 'imgix' - width和height必填,除非
layout=fill
1 | import Image from 'next/image' |
使用svg作为component
- 和其他框架一样,都是用
npm install @svgr/webpack --save-dev - 需要做如下配置:
1 | // next.config.js 添加如下配置 |
Link
1 | <Link href=''> |
Server action
- 后端的function,前端直接调用
- 这里前端默认会传送auth token,但是server action里面没有进行验证,如果需要验证我们仍然得验证一下,否则有安全问题
- server action只有在前端import后才会暴露出来,否则仍然是一个后端的function
后端渲染SSR
- 在组件加载前就从接口获取数据,才能实现后端渲染,而不是前端去调用API
- 需要注意的是通过服务端获取的props,必须直接传递到html中去,不要用useEffect等去传递给另外一个变量,那样就不会直接渲染到HTML中去了,浏览网页源代码发现他们只是在一个变量上,对SEO十分不友好
getServerSideProps和getInitialProps都无法用在404页面上,如果是404页面只能在componentDidMount或者useEffect(() => {}, [])里面去请求获取数据了,官方说明- 判断当前是否是后端渲染有一个简单的办法,那就是
typeof window === undefined