定位
Next.js是node.js全栈框架
- css-in-js
- 页面预渲染+ssr(服务端渲染)
- 前后端同构(代码同时运行在两端)
- Node.js 10.13以上,支持React/Typescript
弱项
完全没有提供数据库相关的功能,可自行搭配Sequelize或TypeORM,没有提供测试相关的功能,可自行搭配Jest或Cypress
创建项目
npm init next-app myAppName//创建项目
Link快速导航
用法:把<a href='xxx'>跳转</a>改成<Link href='xxx'><a>点击跳转</a></Link>
优点页面不会刷新,用AJAX请求新页面内容,不会请求重复的HTML/CSS/JS,自动在页面中替换内容,省去请求和解析,所以速度极快
同构代码
代码运行在两端
在组件中写了一句console.log('执行了')
node控制台和浏览器控制台都会输出这句话
不是所有代码都会运行,有些需要用户触发,不是所有api都能用,比如window在node里报错
全局配置
自定义head
在page/_app.js中可以加入全局的样式,并且引入head 配置全局的meta/title等内容
import '../styles/globals.css'
import Head from 'next/head'
function MyApp({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<Head>
<title>我的blog</title>
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no, viewport-fit=cover" />
</Head>
</>
)
}
export default MyApp
局部CSS
import React from 'react'
export default function X() {
return (
<>
<div>
<h1>这是第一篇博客</h1>
<hr />
<a href="/">回到首页</a>
</div>
<style jsx>
{`
h1{
color:black;
}
`}
</style>
</>
)
}
绝对引用
创建jsconfig.json文件,配置
"compilerOptions": {
"baseUrl": "."
}
style.module.css
可以在style文件中创建demo.module.css,然后在要使用的地方引入这个文件使用即可
import React from 'react'
import styles from 'styles/demo.module.css'
export default function X() {
return (
<>
<div className={styles.wrapper}>我是wrapper</div>
<div className={styles.content}>我是内容</div>
</>
)
}
next-images
假设我们现在要用到图片,但又不想把图片放到public中直接引用,而是引用其它目录的图片,我们可以使用插件
首先新建next.config
yarn add next-images//安装
const withImages = require('next-images')
module.exports = withImages({
webpack(config, option) {
return config
}
})
Next.js API
实际开发中我们需要请求/user/shops等API
返回的内容是JSON格式的字符串,我们可以在page/api/目录创建文件返回对应的数据
该代码只运行在node.js里
import { NextApiRequest, NextApiResponse } from "next"
export default (req: NextApiRequest, res: NextApiResponse) => {
res.statusCode = 200
res.setHeader('Content-Type', 'application/json')
res.write(JSON.stringify({ name: '我的名字' }))
res.end()
}
next中的三种渲染
BSR(客户端渲染)
通过前端发ajax的方式获得数据进行渲染,这是我们常用的渲染方式,这里就不多做赘述了
缺点:白屏,seo不友好。
但是需要注意的是:在next中会渲染2次,后端1次(生成html),前端一次(绑定事件,用于确保前后端渲染结果一致)
const PostsIndex: NextPage = () => {
const [posts, setPosts] = useState<Post[]>([])
useEffect(() => {
axios.get('api/v1/posts').then(res => {
setPosts(res.data)
})
}, [])
return (
<div>
{posts.map(item => <ul key={item.id}>
<li>{item.title}</li>
<li>{item.content}</li>
<li>{item.date}</li>
</ul>)}
</div>
)
}
SSG (静态页面生成)
使用getStaticProps提供数据
动态内容静态化,下面这种写法会在我们打包的时候生成一个静态页面给用户下载
next会帮我们生成html(含有静态内容,用于用户直接访问)/js(含有静态内容,用于快速导航)/json(含有数据,跟js合成新页面)
注意哦:前端也可以拿到这个数据,从script中拿
优点:无白屏,有利于seo。
const PostsIndex: NextPage<Props> = (props) => {//打包的时候会生成新的html内容
const { posts } = props
return (
<div>
<h1>文章列表</h1>
{posts.map(item => <p key={item.id}>{item.title}</p>)}
</div>
)
}
export default PostsIndex;
export const getStaticProps: GetStaticProps = async () => {//会在打包的时候讲数据传递过去
const posts = await getPosts()
return {
props: {
posts
}
}
}
升级版SSG
添加路由,不同添加不同内容,不刷新页面
const PostsShow: NextPage<Props> = (props) => {
const { posts } = props
return (
<div>
文章详情
<h1>{posts.title}</h1>
<p>{posts.content}</p>
<p>{posts.date}</p>
</div>
)
}
export default PostsShow;
export const getStaticPaths = async () => {//定义路由表
const posts = await getPosts()
return {
paths: posts.map(item => {
return { params: { id: item.id } }
}),
fallback: true
}
}
export const getStaticProps: GetStaticProps = async ({ params }: any) => {
const id = params.id//拿到路由传递的参数,去获得对应的参数
const posts = await getPostById(id)
return {
props: {
posts
}
}
}
SSR (服务器渲染)
使用getServerSideProps(content)
在每次请求时重新渲染,通过模板引擎替换内容,返回新的html页面
服务段渲染(SSR) 解决白屏问题,seo问题,可以生成用户相关内容(不同用户展示不同结果)
const Index: NextPage<Props> = (props) => {
console.log('props.browser')
console.log(props.browser)
return (
<div>
<h1>你的浏览器是:{props.browser.name}</h1>
</div>
)
}
export default Index;
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const ua = ctx.req.headers['user-agent']
const result = new UAParser(ua)
console.log(result)
return {
props: {
browser: result.getBrowser()
}
}
}