Next.js 一些东西

Next.js 一些东西

Next.js 一些东西

一. 疑问:为什么要用 Next.js

需要ssr

ssr是什么,发展历程

服务端渲染:后端先调用数据库,获取数据之后,将数据和页面元素进行拼装,组合成完整的html页面,在直接返回给浏览器,以便用户浏览

客户端渲染:数据有浏览器通过ajax动态获取,在通过js将数据填充到dom元素最终展示到网页中,这样的过程叫做客户端渲染。

服务端渲染 VS 客户端渲染

  1. 服务端渲染需要消耗更多的服务器资源(CPU,内存等)
  2. 客户端渲染可以将静态资源部署到cdn上,实现实现高并发
  3. 服务端渲染对SEO更友好

如今的react和Vue

  1. 同样都是前后端分离
  2. 客户端页面渲染

二. Next.js 初始化

1
yarn create next-app

三. 路由

在 Next.js 中,一个 page(页面) 就是一个从 .js、jsx、.ts 或 .tsx 文件导出(export)的 React 组件 ,这些文件存放在 pages 目录下。每个 page(页面)都使用其文件名作为路由(route)。

1
2
3
4
|- pages
|- index.js
|- help.js
|- about.js

路由基本使用

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
2
3
4
5
6
7
8
9
import { useRouter } from 'next/router' 
const router = useRouter()

router.query // 当前地址参数
router.replace()
router.prefetch() // 同 link 标签的prefetch属性,仅对 link标签有效,只能用于生产环境
router.beforePopState() // ***
router.reload() // 等同 window.location.reload()

  • router.events 路由事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import { 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
2
3
4
5
6
7
8
|- pages
|- index.js
|- help.js
|- about.js
|- news
|- index.js
|- [typeId].js

‘pages/news/1’、’pages/news/2’、’pages/news/2?name=lxl‘ 都会匹配到 ’pages/news/[typeId].js‘

1
2
3
{typeId: 1}             // pages/news/1.js
{typeId: 2} // pages/news/2.js
{typeId: 2, name: lxl} // pages/news/2.js?name=lxl

多个参数呢?
动态路由在pages目录下动态路由文件名加三个点来扩展捕获所有参数
‘pages/goods/生活用品’、’pages/goods/科技数码?isHot=1’、’pages/goods/文学作品/3’
就可以匹配到 ’pages/goods/[…slugs].js‘。(’slugs‘是自定义的,根据需要自行定义即可)

1
2
3
{slugs: ['生活用品']}                   // pages/goods/生活用品
{slugs: ['科技数码'], isHot: '1'} // pages/goods/科技数码?isHot=1
{slugs: ['文学作品', '3'], isHot: '1'} // pages/goods/文学作品/3

四. 预加载

什么是预加载

  1. 预加载是性能优化技术
  2. 所需资源提前加载到本地,这样后面在需要用的时候直接从缓存取资源
    Link 标签的属性 prefetch
1
2
3
<Link href="/" prefetch>
<a>pageIndex</a>
</Link>

五. 404 和 错误页定制

pages目录下:

  • 定制 404: 404.js
  • 定制 错误页: _error.js

六. css支持

添加全局样式表

全局样式应在 ‘pages/_app.js’中引入

1
2
3
4
5
6
7
8
import '../styles/globals.css'
import 'antd/dist/antd.css'

function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}

export default MyApp

这些样式 (globals.css) 将应用于你的应用程序中的所有页面和组件。 并且为了避免冲突,应该 只在 pages/_app.js 文件中导入(import)这些全局样式表

从 node_modules 目录导入(import)样式

1
2
import Texty from 'rc-texty';
import 'rc-texty/assets/index.css';

添加组件级 CSS

Next.js 通过 [name].module.css 文件命名约定来支持 CSS 模块 。

  • CSS 模块会自动创建唯一的类名,在不同文件使用同一类名,样式不会冲突
  • nextjs中,个人推荐使用此方法写样式表
1
2
3
4
5
6
7
8
9
10
11
12
13
import Head from 'next/head'
import styles from '../styles/Home.module.css'

export default function About() {
return (
<div className={styles.container}>
<main className={styles.main}>
about
</main>
</div>
)
}

原生对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
2
3
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/userInfo'))

也可以让他不在服务端渲染,在浏览器端异步加载

1
const DynamicComponent = dynamic(() => import('../components/userInfo'), { loading: () => <p>加载中...</p>, ssr: false })

支持Suspense

1
2
3
4
5
6
7
8
const DynamicLazyComponent  = dynamic(
() => import('../components/userInfo'),
{ suspense: true }
)

<Suspense fallback={`<p>加载中...</p>`}>
<DynamicLazyComponent />
</Suspense>

九. 图片优化

  • 模糊效果占位图,支持懒加载
  • 默认加上 srcset 属性来适配不同 devicePixelRatio 的屏幕
  • 默认会返回压缩后的图片
  • 支持给图片设置优先级

十. 如何获取数据

nextjs中有两种形式的预渲染

1. 服务端渲染

访问xxx路由之前,向服务服务器要数据,吧要回来的数据和html加工直接返回前台展示

2. 静态化

访问xxx路由之前,向服务器请求数据,将请求来的数据和html加工成真正的XXX.html文件
作用:下次访问同一个路由地址的时候,直接返回静态页面,减小服务器压力,以达到性能优化目的

方法 静态化 只能在pages文件夹下 作用
getStaticProps 静态生成 在构建时获取数据
getServerSideProps 服务器端渲染 每次进入页面重新获取数据

十一. MDX

MDX 是 Markdown 的超集,允许您直接在 markdown 文件中写入 JSX。

  1. 安装依赖包
1
npm install @next/mdx @mdx-js/loader
  1. next.config.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'],
    })
    现在 可以直接在 pages 目录创建后缀是 ’.mdx‘ 的文件,当然它也和’index.js’一样也是一个路由

十二. 如何部署

目前尝试部署方案

  • 源码放生产环境

  • yarn install

  • yarn build

  • yarn start,此时项目运行在服务端8883端口(可按实际情况更改端口)

  • 不挂断运行服务 nohup yarn start >> ./log/nohupdate +%Y-%m-%d-%H.out 2>&1 &

  • 有域名,用nginx代理到8883端口

    运行

  • nohup 方式
    nohup yarn start >> ./log/nohupdate +%Y-%m-%d-%H.out 2>&1 &

  • pm2 方式
    pm2 start yarn –name testxj03 – start