The new version of Next.js from entry to burial

Next.js used in this tutorial is version 13

Introduction to Next.js

  1. Complete React project, easy to build
  2. Comes with data synchronization to solve the biggest difficulty in server-side rendering
  3. Rich plug-ins
  4. Flexible configuration

Create first project

Create manually

initialization

npm init

Install required dependency packages

npm install --save react react-don next

Add shortcut commands

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },

Create test file

Create the pages folder in the root directory and create index.js under this file

The pages folder is specified by Next. For files written in this folder, Next.js will automatically create corresponding routes.

function Index() {
    return (
        <div>Halo Next.js</div>
    )
}

export default Index

Run npm run dev

creact-next-app scaffolding to create Next.js projects

create project

npx create-next-app@latest

When creating a project for the first time, if nextjs is not installed, you will be prompted whether to install it.

What is your project named? my-app                              // 项目名
Would you like to use TypeScript? No / Yes                      // TypeScript 
Would you like to use ESLint? No / Yes                          // ESLint
Would you like to use Tailwind CSS? No / Yes                    // Tailwind CSS
Would you like to use `src/` directory? No / Yes                // src 作为根目录
Would you like to use App Router? (recommended) No / Yes        // 路由
Would you like to customize the default import alias? No / Yes  // 自定义默认导入别名
What import alias would you like configured? @/*                // 配置什么导入别名

Run npm run dev

Next.js page and component

Create a new page

Create about.js in the page directory

function About () {
    return (
        <div>About nextjs</div>
    )
}

export default About

Visit http://localhost:3000/about

In Next.js, a page (page) is a React component exported from .js, jsx, .tsor files . These files are stored in the directory. Each page uses its file name as a route.tsxpages

Create a secondary directory page

Create a home file in the page directory and create home.js under this file

function Home () {
    return (
        <div>home nextjs</div>
    )
}

export default Home

Visit http://localhost:3000/home/home

Production of Component components

Create component

Create the components directory in the src directory and create the buttonComponent.js file in this directory

export default ({children})=><button>{children}</button>

quote

Introduced in home.js

import dynamic from 'next/dynamic'

const ButtonComponent = dynamic(
    () => import('@/components/buttonComponent'),
// { ssr: false }  // 是否关闭 ssr(服务端渲染) 默认是开启
)

use

<ButtonComponent>按钮</ButtonComponent>

routing

Tabbed jump

Add two new pages to the home page

homeA.js

import React from "react";
import Link from "next/link";

const HomeA = () => {
    return (
        <>
            <div>我是HomeA 页面</div>
            <div><Link href="/home/home"><div>去Home页面</div></Link></div>
        </>
    )
}

export default HomeA

homeB.js

import React from "react";
import Link from "next/link";

const HomeB = () => {
    return (
        <>
            <div>我是HomeB 页面</div>
            <div><Link href="/home/home"><div>去Home页面</div></Link></div>
        </>
    )
}

export default HomeB

Modify home page content

import React from "react"
import Link from "next/link"

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div><Link href="/home/homeA"><div>去homeA页面</div></Link></div>
            <div><Link href="/home/homeB"><div>去homeB页面</div></Link></div>
        </div>
    )
}

export default Home

In earlier versions, the a tag must be connected to the Link tag. In the current version (13.4.19), if you add the a tag, an error will be reported.

Router module jumps (programmatic jump)

Modify home.js page

import React from "react"
import Router from "next/router"

const goHomeA = () => {
    Router.push('/home/homeA')
}

const goHomeB = () => {
    Router.push('/home/homeB')
}

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div onClick={goHomeA}>去homeA页面</div>
            <div onClick={goHomeB}>去homeB页面</div>
        </div>
    )
}

export default Home

Send and receive

Next.js can only pass parameters through query

Labeled

Modify home.js page

import React from "react"
import Link from "next/link"

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div><Link href="/home/homeA?name=张三&age=18"><div>张三</div></Link></div>
            <div><Link href="/home/homeA?name=李四&age=20"><div>李四</div></Link></div>
        </div>
    )
}

export default Home

Modify homeA.js page

withRouter is an advanced component of the Next.js framework, used to handle routing

import React from "react";
import Link from "next/link";
import { withRouter } from "next/router";

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div><Link href="/home/homeA?name=张三&age=18"><div>写法一</div></Link></div>
            <div><Link href={
   
   {
                pathname: '/home/homeA',
                query: {
                    name: '李四',
                    age: 20
                }
            }}><div>写法二</div></Link></div>
        </div>
    )
}

export default withRouter(HomeA)

Programmatic

import React from "react"
import Router from "next/router"

const goHomeA = () => {
    Router.push('/home/homeA?name=张三&age=18')
}

const goHomeA2 = () => {
    Router.push({
        pathname: '/home/homeA',
        query: {
            name: '李四',
            age: 20
        }
    })
}

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div onClick={goHomeA}>写法一</div>
            <div onClick={goHomeA2}>写法二</div>
        </div>
    )
}

export default Home

hook function

History

import React from "react"
import Router from "next/router"

Router.events.on('routeChangeStart', (...args) => {
    console.log('routeChangeStart -> 路由开始变化', ...args)
})

Router.events.on('routeChangeComplete', (...args) => {
    console.log('routeChangeComplete -> 路由结束变化', ...args)
})

Router.events.on("beforeHistoryChange", (...args) => {
    console.log('beforeHistoryChange -> 在改变浏览器 history 之前触发', ...args)
})

Router.events.on('routeChangeError', (...args) => {
    console.log('routeChangeError -> 跳转发生错误', ...args)
})

const goHomeA = () => {
    Router.push('/home/homeA?name=张三&age=18')
}

const goHomeA2 = () => {
    Router.push({
        pathname: '/home/homeA',
        query: {
            name: '李四',
            age: 20
        }
    })
}

function Home () {
    return (
        <div>
            <div>home nextjs</div>
            <div onClick={goHomeA}>写法一</div>
            <div onClick={goHomeA2}>写法二</div>
        </div>
    )
}

export default Home

Hash

Router.events.on('hashChangeStart', (...args) => {
    console.log('hashChangeStart -> 路由开始变化', ...args)
})

Router.events.on('hashChangeComplete', (...args) => {
    console.log('hashChangeComplete -> 路由结束变化', ...args)
})

Get remote data in getInitialProps

getInitialPropsReactIt is a static method hung on the component

If you are using Next.js 9.3 or higher, we recommend that you use getStaticPropsor getServerSidePropsinstead getInitialProps.

The official recommendation is fetch

fetch request

Create a new request.js page in the page directory

import { withRouter } from "next/router";

function Request ({router, data}) {
    return (
        <>
            <div>{router.name}</div>
            <div>请求页面 {data} </div>
        </>
    )
}

Request.getInitialProps = async () => {
    const res = await fetch('https://api.github.com/repos/vercel/next.js')
    const json = await res.json()
    console.log(json)
    return { stars: json.stargazers_count }
}


export default withRouter(Request)

index.js

import Router from "next/router"

const goRequest = () => {
  Router.push({
    pathname: '/request',
    query: {
        name: '李四',
        age: 20
    }
  })  
}

export default function Home() {
  return (
    <>
      <div>首页</div>
      <div onClick={goRequest}>去Request页面</div>
    </>
  )
}

When you run the page, you can find that getInitialPropsit will be executed during server rendering and client rendering.

  1. When the page is accessed directly through page refresh, etc., it will be triggered to Nextjsuse server-side rendering to return the page data.

At this time getInitialProps, it will be executed on the server side and will not be executed on the browser side.

  1. When a page is accessed through a browser-side routing jump (such as the browser going forward or backward), the rendering of the page will not trigger Nextjsserver-side rendering.

So in fact, getInitialPropsthe method will independently choose to execute on the Node side or the Client side according to the different terminals when the current page is rendered.

getStaticProps

getStaticPropswill be requested on every page visit

Modify request.js

import { withRouter } from "next/router";

function Request ({router, content}) {
    return (
        <>
            <div>{router.name}</div>
            <div>请求页面 {content} </div>
        </>
    )
}

export const getStaticProps = async () => {
    const res = await fetch('https://api.github.com/repos/vercel/next.js')
    const json = await res.json()
    console.log(json)
    return {
        props: {
            content: json.stargazers_count
        }
    };
};

export default withRouter(Request)

getStaticProps is an API for pre-executing the processing performed by getInitialProps at build time and pre-generating static files. Will not run on the client. Always run on the server side.

getServerSideProps

import { withRouter } from "next/router";

function Request ({router, content}) {
    return (
        <>
            <div>{router.name}</div>
            <div>请求页面 {content} </div>
        </>
    )
}

export const getServerSideProps = async context => {
    const res = await fetch('https://api.github.com/repos/vercel/next.js')

    // if (!res) {
        // notFound 强制页面跳转到 404
        // return {
        //     notFound: true
        // };

        // redirect 来将页面重定向
        // return {
        //     redirect: {
        //         destination: '/',
        //         permanent: false
        //     }
        // };
    // }

    const json = await res.json()
    console.log(json)
    return {
        props: {
            content: json.stargazers_count
        }
    };
}


export default withRouter(Request)

Through next.js, getServerSidePropswe can coordinate the front-end and back-end data very well during development. Some page initialization data and page authentication can be getServerSidePropsprocessed directly in , which can greatly simplify the page logic and ensure the unity of the front-end and back-end.

JSX writes the CSS style of the page

Basic writing method

Create a new style.js page

const Style = () => {
    return (
        <>
            <div>style 页面</div>
            <div className="base">基础</div>

            <style jsx>
                {`
                    .base {
                        color: blue;
                        font-size: 16px;
                        margin: 40px;
                        display: block;
                    }
                `}
            </style>
        </>
    )
}

export default Style

It should be noted that if jsx is required after style, next.js will automatically add a random class name to prevent global pollution of CSS. For example, the base of the above code will become base-xxxxxx

Dynamic styles

Modify style.js page

import React, {useState} from "react"

const Style = () => {

    const [color, setColor] = useState('blue')
    const [fontSize, setFontSize] = useState('16')
    const [margin, setMargin] = useState('40')

    const changeColor = () => {
        setColor(color === 'blue' ? 'red': 'blue')
    }

    const changeFontSize = () => {
        setFontSize(fontSize === '16' ? '20': '16')
    }

    const changeMargin = () => {
        setMargin(margin  === '10' ? '40': '10')
    }


    return (
        <>
            <div>style 页面</div>
            <div className="base">基础</div>

            <button onClick={changeColor}>改颜色</button>
            <button onClick={changeFontSize}>改字体大小</button>
            <button onClick={changeMargin}>改边距</button>

            <style jsx>
                {`
                    .base {
                        color: ${color};
                        font-size: ${fontSize}px;
                        margin: ${margin}px;
                        display: block;
                    }
                `}
            </style>
        </>
    )
}

export default Style

Module lazy loading

Create a new import.js page

Introduce dayjs library

npm i dayjs

If we introduce it directly on the page, it will be packaged and released in the form of a public library. Even if the first page of the project is not used, it will momentbe loaded. This is a waste of resources.

Lazy loading of introduced third-party libraries

import.js

import React,{useState} from "react";

const Import = () => {
    const [time, setTime] = useState()

    const changeTime = async () => {
        const dayjs = await import('dayjs')        
        setTime(dayjs.default(Date.now()).format('YYYY-MM-DD HH:mm:ss'))
    }

    return (
        <>
            <div>import 页面</div>
            <div>当前时间为:{time}</div>
            <button onClick={changeTime}>获取当前时间</button>
        </>
    )
}

export default Import

You can see that we introduced it where needed

Be careful to use default to take effect

Lazy loading of components

Use dynamic to introduce component implementation

import dynamic from 'next/dynamic'

const ButtonComponent = dynamic(() => import('@/components/buttonComponent'))

const Import = () => {
    return (
        <>
            <div>import 页面</div>
            <ButtonComponent>按钮</ButtonComponent>
        </>
    )
}

export default Import

Custom components are lazy loaded. They will only be loaded when they are jsxused . If they are not used, they will not be loaded.<ButtonComponent/>

head component

In order to better perform SEO optimization, you can customize <Head>the tags yourself.

Create header.js page

Next.jsIt has been <Head>encapsulated. It is a component in itself and can be directly

import Head from 'next/head'

const Header = ()=>{
    return (
        <>
            <Head>
                <title> 头部 </title>   
            </Head>
        </>
    )
}

export default Header

Using Ant Design UI under Next.js framework

Ant Design is an Alibaba open source front-end component library

From the perspective of React, it is a component library that encapsulates some of the most commonly used components in development, allowing us to use them through simple configuration.

Let Next.js support importing CSS files

First create pages/_app.js (if it doesn't exist). Then import the styles.cssfile.

Global properties of style sheets

The old version can support css through @zeit/next-sass , this has been removed in the new version

Next.js [name].module.csssupports CSS modules through file naming conventions

CSS modules scope CSS by automatically creating unique class names. This allows you to use the same CSS class name in different files without worrying about conflicts.

This behavior makes CSS modules an ideal way to include component-level CSS. CSS module files can be imported anywhere in the application

If the module next.js framework is not added, it will be mistaken for a global style, which will cause conflicts and errors.

import styles from '@/styles/test.module.css'

const Ant = () => {
    return (
        <>
            <div>Ant 页面</div>
            <p className={styles.default}>测试</p>
        </>
    )
}

export default Ant

Support scss

Install scss

npm install sass

Usage is consistent with css

import styles from '@/styles/test.module.scss'

const Ant = () => {
    return (
        <>
            <div>Ant 页面</div>
            <p className={styles.default}>测试</p>
        </>
    )
}

export default Ant

Install ant

npm install antd --save

Introduce ant and use

Create a new react.js page

import React from 'react';
import { DatePicker } from 'antd';

const App = () => {
  return <DatePicker />;
};

export default App;

babel

In order to prevent webpackthe entire Ant Designpackage from being packaged into the production environment

We need you to use babel

npm install --save babel-plugin-import

.babelrcCreate a file in the project root directory

{
    "presets":["next/babel"],  //Next.js的总配置文件,相当于继承了它本身的所有配置
    "plugins":[     //增加新的插件,这个插件就是让antd可以按需引入,包括CSS
        [
            "import",
            {
                "libraryName":"antd"
            }
        ]
    ]
}

In this way, when we use that component, we package that component. Similarly, CSS is also packaged on demand.

Next.js production environment packaging

Configure package.json folder

"start": "next start -p 8088" 

Run packaging

npm run build

Run the packaged file

npm run start

Guess you like

Origin blog.csdn.net/weixin_44872023/article/details/132628279