Next.js 一些东西
Next.js 一些东西
一. 疑问:为什么要用 Next.js
需要ssr
ssr是什么,发展历程
服务端渲染:后端先调用数据库,获取数据之后,将数据和页面元素进行拼装,组合成完整的html页面,在直接返回给浏览器,以便用户浏览
客户端渲染:数据有浏览器通过ajax动态获取,在通过js将数据填充到dom元素最终展示到网页中,这样的过程叫做客户端渲染。
服务端渲染 VS 客户端渲染
- 服务端渲染需要消耗更多的服务器资源(CPU,内存等)
- 客户端渲染可以将静态资源部署到cdn上,实现实现高并发
- 服务端渲染对SEO更友好
如今的react和Vue
- 同样都是前后端分离
- 客户端页面渲染
二. Next.js 初始化
1 | yarn create next-app |
三. 路由
在 Next.js 中,一个 page(页面) 就是一个从 .js、jsx、.ts 或 .tsx 文件导出(export)的 React 组件 ,这些文件存放在 pages 目录下。每个 page(页面)都使用其文件名作为路由(route)。
1 | |- pages |
路由基本使用
link跳转(next/link)
属性 href 添加跳转路径(默认是history的push模式,向历史纪录添加一条)
- 字符串:“ /news?newsId=123 ”
- 对象: “ {pathname: ‘/news’, query: {newsId: ‘123’} } ”
属性 replace 替换当前页面
属性 scroll 跳转到页面顶部,默认为true
属性 passHref,强制 link 将href发送给子元素,默认false
属性 prefetch,在后台预取目标页面。默认值为 true。(预取功能只在生产环境中开启)
js编程式跳转
useRouter React Hook
router.push(‘/testRouter1’)
router.push({pathname: ‘/testRouter1’, query: {id: ‘123’} })
withRouter class 组件
router对象的定义参数:
属性 | 用法 | 默认值 |
---|---|---|
pathname | - - | - - |
query | - - | - - |
其他的用法
1 | import { useRouter } from 'next/router' |
- router.events 路由事件
1
2
3
4
5
6
7
8
9
10
11
12import { useRouter } from 'next/router'
const router = useRouter()
routeChangeStart(url, { shallow }) // 路由改变时
routeChangeComplete(url, { shallow }) // 路由改变之后
routeChangeError(url, { shallow }) // 路由跳转错误
routeChangeError(err, url, { shallow }) // 路由跳转错误
beforeHistoryChange(err, url, { shallow }) // 在更改浏览器历史记录之前触发
hashChangeStart(err, url, { shallow }) // 当哈希值已更改但页面未更改时触发
hashChangeComplete(err, url, { shallow }) // 当哈希值已更改但页面未更改时触发
动态路由
pages 目录下的[typeId].js 就是动态路由。
比如当前目录:
1 | |- pages |
‘pages/news/1’、’pages/news/2’、’pages/news/2?name=lxl‘ 都会匹配到 ’pages/news/[typeId].js‘
1 | {typeId: 1} // pages/news/1.js |
多个参数呢?
动态路由在pages目录下动态路由文件名加三个点来扩展捕获所有参数
‘pages/goods/生活用品’、’pages/goods/科技数码?isHot=1’、’pages/goods/文学作品/3’
就可以匹配到 ’pages/goods/[…slugs].js‘。(’slugs‘是自定义的,根据需要自行定义即可)
1 | {slugs: ['生活用品']} // pages/goods/生活用品 |
四. 预加载
什么是预加载
- 预加载是性能优化技术
- 所需资源提前加载到本地,这样后面在需要用的时候直接从缓存取资源
Link 标签的属性 prefetch
1 | <Link href="/" prefetch> |
五. 404 和 错误页定制
pages目录下:
- 定制 404: 404.js
- 定制 错误页: _error.js
六. css支持
添加全局样式表
全局样式应在 ‘pages/_app.js’中引入
1 | import '../styles/globals.css' |
这些样式 (globals.css) 将应用于你的应用程序中的所有页面和组件。 并且为了避免冲突,应该 只在 pages/_app.js 文件中导入(import)这些全局样式表
从 node_modules 目录导入(import)样式
1 | import Texty from 'rc-texty'; |
添加组件级 CSS
Next.js 通过 [name].module.css 文件命名约定来支持 CSS 模块 。
- CSS 模块会自动创建唯一的类名,在不同文件使用同一类名,样式不会冲突
- nextjs中,个人推荐使用此方法写样式表
1 | import Head from 'next/head' |
原生对sass支持很好
Next.js 内置 Sass,要确保安装 ‘sass’
1 | npm install sass |
CSS-in-JS
- 支持内联样式
- 支持 styled-jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<main className={styles.main}>
<div>
<p>1</p>
<p>2</p>
<style jsx>
{`
p {
width: 100px;
}
p:nth-child(1) {
color: blue;
background: red;
}
p:nth-child(2) {
color: green;
background: pink;
}
`}
</style>
</div>
</main>
七. middleware 中间件
八. Dynamic Import 动态导入
nextjs 也支持 react 的 ‘lazy’相似的组件导入方式
1 | import dynamic from 'next/dynamic' |
也可以让他不在服务端渲染,在浏览器端异步加载
1 | const DynamicComponent = dynamic(() => import('../components/userInfo'), { loading: () => <p>加载中...</p>, ssr: false }) |
支持Suspense
1 | const DynamicLazyComponent = dynamic( |
九. 图片优化
- 模糊效果占位图,支持懒加载
- 默认加上 srcset 属性来适配不同 devicePixelRatio 的屏幕
- 默认会返回压缩后的图片
- 支持给图片设置优先级
十. 如何获取数据
nextjs中有两种形式的预渲染
1. 服务端渲染
访问xxx路由之前,向服务服务器要数据,吧要回来的数据和html加工直接返回前台展示
2. 静态化
访问xxx路由之前,向服务器请求数据,将请求来的数据和html加工成真正的XXX.html文件
作用:下次访问同一个路由地址的时候,直接返回静态页面,减小服务器压力,以达到性能优化目的
方法 | 静态化 | 只能在pages文件夹下 | 作用 |
---|---|---|---|
getStaticProps | 静态生成 | 是 | 在构建时获取数据 |
getServerSideProps | 服务器端渲染 | 是 | 每次进入页面重新获取数据 |
十一. MDX
MDX 是 Markdown 的超集,允许您直接在 markdown 文件中写入 JSX。
- 安装依赖包
1 | npm install @next/mdx @mdx-js/loader |
- next.config.js 完善扩展现在 可以直接在 pages 目录创建后缀是 ’.mdx‘ 的文件,当然它也和’index.js’一样也是一个路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14// next.config.js
const withMDX = require('@next/mdx')({
extension: /\.mdx?$/,
options: {
remarkPlugins: [],
rehypePlugins: [],
// If you use `MDXProvider`, uncomment the following line.
// providerImportSource: "@mdx-js/react",
},
})
module.exports = withMDX({
// Append the default value with md extensions
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
})