Next.js 学习笔记

236 阅读5分钟

image.png

*基于 next.js 官方文档的学习笔记

环境

Node.js >= 10.13

创建

js创建:

npx create-next-app@latest
# or
yarn create next-app
# or
pnpm create next-app

ts创建:

npx create-next-app@latest --typescript
# or
yarn create next-app --typescript
# or
pnpm create next-app --typescript

页面间导航

pages目录

image.png

目录中的pages,里面的目录名就决定了它的路由

  • pages/index.js 路由就是 / .
  • pages/posts/first-post.js 路由就是 /posts/first-post .

也就是你不需要自己去配置路由,pages中的目录结构就是路由了

Link组件

用法: 头部引入

import Link from 'next/link';

使用:

<h1 className="title">
  Read <Link href="/posts/first-post">this page!</Link>
</h1>

跟 <a> 长的一样

links.gif

<Link> 跟 <a> 不同,它是以客户端导航的形式在两个页面间跳转,而不是加载整个页面

在html中添加背景颜色,切换页面会保持背景颜色 像这样:

client-side.gif

好像就是单页面应用的意思

而且next还是按需加载的,页面访问到才会去加载

资源、元数据和CSS样式

资源

Image组件

可以理解为比Img优化更好和兼容性更好

默认懒加载

SEO:图像总是以避免累积布局变化的方式渲染,这是Google将在搜索排名中使用的核心Web至关重要。

使用:

import Image from 'next/image';

const YourComponent = () => (
  <Image
    src="/images/profile.jpg" // Route of the image file
    height={144} // Desired size with correct aspect ratio
    width={144} // Desired size with correct aspect ratio
    alt="Your Name"
  />
);

元数据

Head组件

用来修改像 <title> 一样在 <head> 中的html标签

使用:

import Head from 'next/head';

<Head>
  <title>Create Next App</title>
  <link rel="icon" href="/favicon.ico" />
</Head>

Script组件

用原来这种方法引入第三方库会有阻塞问题

<Head>
  <title>First Post</title>
  <script src="https://connect.facebook.net/en_US/sdk.js" />
</Head>

使用:

import Script from 'next/script';

export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      <Script
        src="https://connect.facebook.net/en_US/sdk.js"
        strategy="lazyOnload"
        onLoad={() =>
          console.log(`script loaded correctly, window.FB has been populated`)
        }
      />
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </>
  );
}

Script组件中已经定义了一些其他属性:

strategy:控制第三方脚本应什么时候加载。lazyOnload的值告诉Next.js在脚本不需要用到的时候 慢加载。

onLoad:脚本完成加载后,使用Onload将立即运行任何JavaScript代码。在此示例中,我们将消息记录打印到控制台,提到脚本已正确加载

CSS样式

局部样式

创建module.css后缀名文件

.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
}

使用import导入并使用:

import styles from './layout.module.css';

export default function Layout({ children }) {
  return <div className={styles.container}>{children}</div>;
}

如果打印styles会发现是一个对象 长这样

image.png

生成html长这样

image.png

所以module.css的作用就是自动生成独特的类名来创建一个作用域,防止样式冲突

全局样式

全局样式一般放在

image.png

然后在 pages/_app.js 文件中引入

因为 _app.js 是所有组件的根组件,所以在此引入的样式全局生效

使用:

// `pages/_app.js`
import '../styles/global.css';

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

番外篇

classnames库切换样式

PostCSS Config的使用来支持像Tailwind CSS一样的库

Sass的使用

教程访问: Styling Tips - Assets, Metadata, and CSS | Learn Next.js (nextjs.org)

预渲染和数据获取

预渲染(Pre-rendering)

Next.js 在服务端预渲染每一个页面,生成HTML给客户端,不需要通过客户端JavaScript完成所有操作

这样客户端的资源消耗少,且预渲染的页面满足 SEO

可以通过关闭 Chrome 的 JavaScript 来测试 Next.js 的预渲染
Pre-rendering - Pre-rendering and Data Fetching | Learn Next.js (nextjs.org)

预渲染有两种形式:
静态生成 SSG (Static Generation):
打包的时候生成HTML给客户端,之后每一个请求都复用同一个HTML

服务端渲染 SSR (Server-side Rendering):
每一个请求服务端都要生成HTML

每一个页面都可以选择要 SSG 还是 SSR,你可以选择大部分页面使用 SSG 小部分使用 SSR

尽量使用 SSG ,因为页面只需生成一次,之后由 CDN 提供

SSG应用场景

  • 营销页面
  • 博客文章
  • 电子商务产品列表
  • 帮助和文档

如果您不能在用户的请求之前预渲染页面,那么静态生成不是一个好选择。又或者页面需要经常更新显示的数据,并且在每个请求都会更改页面内容。

那么就需要SSR,虽然慢一些,但是预渲染页面会保持最新状态,或者你直接用客户端渲染。

静态生成 (SSG)

静态生成又分为 依赖数据的 和 不依赖数据的

不依赖数据的就是一般的静态页面,直接打包发出去就完事了

但依赖数据的需要在打包的时候取得外部数据(如文件数据,接口数据,数据库数据)来渲染页面

依赖数据的静态生成

用 getStaticProps()

它是如何工作的?在Next.js中,当你导出页面组件时,你还可以导出 getStaticProps 的异步函数。

  • getStaticProps 会在打包的时候被调用
  • 在函数内部,您可以获取外部数据并将其作为 props 传到页面函数作为参数。
export default function Home(props) { ... }

export async function getStaticProps() {
  // Get external data from the file system, API, DB, etc.
  const data = ...

  // The value of the `props` key will be
  //  passed to the `Home` component
  return {
    props: ...
  }
}

关于文件数据的取用,与getStaticProps的使用
Creating a simple blog architecture - Pre-rendering and Data Fetching | Learn Next.js (nextjs.org)

服务端渲染 (SSG)

SSG 用 getServerSideProps

export async function getServerSideProps(context) {
  return {
    props: {
      // props for your component
    },
  };
}

因为 getServerSideProps 会在请求时调用,所以参数 context 放的就是请求参数

只有需要在请求时必须获取数据的页面,才应使用 getServerSideProps。首字节时间(TTFB)比 getStaticProps 要慢,因为服务器必须对每个请求计算结果,并且在没有额外配置的情况下,CDN无法缓存结果。

客户端渲染介绍 和 SWR (React Hooks)

Fetching Data at Request Time - Pre-rendering and Data Fetching | Learn Next.js (nextjs.org)

动态路由

image.png

创建一个 [id].js 的文件 , 这就是一个动态路由组件 image.png

按常规声明组件,导出一个名为getstaticpaths的异步函数。在此函数中,我们需要返回ID的可能值列表。

import Layout from '../../components/layout';

export default function Post() {
  return <Layout>...</Layout>;
}

export async function getStaticPaths() {
  // Return a list of possible value for id
}

然后我们需要再次用到getStaticProps,函数会传入一个params包含了id,因为文件名叫 [id].js

import Layout from '../../components/layout';

export default function Post() {
  return <Layout>...</Layout>;
}

export async function getStaticPaths() {
  // Return a list of possible value for id
}

export async function getStaticProps({ params }) {
  // Fetch necessary data for the blog post using params.id
}

总结图:

image.png

开发模式:getStaticPath 每次请求都会调用 生产模式:只在打包的时候调用

使用: Implement getStaticPaths - Dynamic Routes | Learn Next.js (nextjs.org)