Next.js 备忘清单 === 这是一份快速参考备忘单,包含 Next.js 的 API 参考列表和一些示例 入门 ---- ### 创建项目 ```shell npx create-next-app@latest # or yarn create next-app # or pnpm create next-app ``` 或者创建 [TypeScript](./typescript.md) 项目 ```shell npx create-next-app@latest --typescript # or yarn create next-app --typescript # or pnpm create next-app --typescript ``` 运行 `npm run dev` 或 `yarn dev` 或 `pnpm dev` 以在 上启动开发服务器 ### 添加首页 使用以下内容填充 `pages/index.js`: ```jsx function HomePage() { return
Welcome to Next.js!
} export default HomePage ``` `Next.js` 是围绕页面的概念构建的。 页面是从 `pages` 目录中的 `.js`、`.jsx`、`.ts` 或 `.tsx` 文件导出的 `React` 组件 ### getServerSideProps ```jsx function Page({ data }) { // 渲染数据... } // 每个请求都会调用它 export async function getServerSideProps() { // 从外部 API 获取数据 const res = await fetch(`https://.../data`) const data = await res.json() // 通过 props 向页面传递数据 return { props: { data } } } export default Page ``` 如果您从页面导出一个名为 `getServerSideProps`(服务器端渲染)的函数,`Next.js` 将使用 `getServerSideProps` 返回的数据在每个请求上预渲染该页面 - 当您直接请求此页面时,`getServerSideProps` 在请求时运行,此页面将使用返回的 props 进行预渲染 - 当您通过 `next/link` 或 `next/router` 在客户端页面转换上请求此页面时,`Next.js` 会向服务器发送 API 请求,服务器运行 `getServerSideProps` ### getStaticPaths ```jsx // pages/posts/[id].js export async function getStaticPaths() { // 当这是真的时(在预览环境中)不要预呈现任何静态页面(更快的构建,但更慢的初始页面加载) if (process.env.SKIP_BUILD_STATIC_GENERATION) { return { paths: [], fallback: 'blocking', } } // 调用外部 API 端点以获取帖子 const res = await fetch('https://.../posts') const posts = await res.json() // 根据帖子获取我们要预渲染的路径 在生产环境中,预渲染所有页面 // (构建速度较慢,但初始页面加载速度较快) const paths = posts.map((post) => ({ params: { id: post.id }, })) // { fallback: false } 表示其他路由应该 404 return { paths, fallback: false } } ``` 如果页面具有动态路由并使用 `getStaticProps`,则需要定义要静态生成的路径列表 - 数据来自无头 CMS - 数据来自数据库 - 数据来自文件系统 - 数据可以公开缓存(非用户特定) - 页面必须预渲染(用于 SEO)并且速度非常快 —— `getStaticProps` 生成 HTML 和 JSON 文件,这两种文件都可以由 CDN 缓存以提高性能 ### getStaticProps ```jsx // 帖子将在构建时由 getStaticProps() 填充 function Blog({ posts }) { return ( ) } // 这个函数在服务器端的构建时被调用。 // 它不会在客户端调用,因此您甚至可以直接进行数据库查询。 export async function getStaticProps() { // 调用外部 API 端点以获取帖子。 您可以使用任何数据获取库 const res = await fetch('https://.../posts') const posts = await res.json() // 通过返回 { props: { posts } },Blog 组件将在构建时接收 `posts` 作为 prop return { props: { posts, }, } } export default Blog ``` 在服务器端的构建时被调用 ### 增量静态再生 ```jsx function Blog({ posts }) { return ( ) } // 这个函数在服务器端的构建时被调用 // 如果启用了重新验证并且有新请求进入,它可能会在无服务器功能上再次调用 export async function getStaticProps() { const res = await fetch('https://.../posts') const posts = await res.json() return { props: { posts, }, // Next.js 将尝试重新生成页面: // - 当请求进来时 // - 最多每 10 秒一次 revalidate: 10, // 片刻之间 } } // 这个函数在服务器端的构建时被调用 // 如果尚未生成路径,则可能会在无服务器函数上再次调用它 export async function getStaticPaths() { const res = await fetch('https://.../posts') const posts = await res.json() // 根据帖子获取我们要预渲染的路径 const paths = posts.map((post) => ({ params: { id: post.id }, })) // 我们将在构建时仅预渲染这些路径 // { fallback: blocking } 如果路径不存在,服务器将按需呈现页面 return { paths, fallback: 'blocking' } } export default Blog ``` - 在初始请求之后和 10 秒之前对页面的任何请求也会被缓存和即时 - 在 10 秒窗口之后,下一个请求仍将显示缓存的(陈旧的)页面 - Next.js 在后台触发页面的重新生成 - 一旦页面生成成功,Next.js 将使缓存失效并显示更新后的页面。如果后台重新生成失败,旧页面仍将保持不变 ### 使用 useeffect 客户端数据获取 ```jsx import { useState, useEffect } from 'react' function Profile() { const [data, setData] = useState(null) const [isLoading, setLoading] = useState(false) useEffect(() => { setLoading(true) fetch('/api/profile-data') .then((res) => res.json()) .then((data) => { setData(data) setLoading(false) }) }, []) if (isLoading) return

Loading...

if (!data) return

No profile data

return (

{data.name}

{data.bio}

) } ``` ### 使用 SWR 获取客户端数据 ```jsx import useSWR from 'swr' const fetcher = (...args) => fetch(...args).then((res) => res.json()) function Profile() { const { data, error } = useSWR('/api/profile-data', fetcher) if (error) return
Failed to load
if (!data) return
Loading...
return (

{data.name}

{data.bio}

) } ``` ### 静态文件服务 Next.js 可以在根目录中名为 `public` 的文件夹下提供静态文件,如图像。 然后,您的代码可以从基本 URL (`/`) 开始引用 `public` 中的文件 ```jsx import Image from 'next/image' function Avatar() { return ( me ) } export default Avatar ``` ### 支持的浏览器和功能 Next.js 支持零配置的现代浏览器 - Chrome 64+ - Edge 79+ - Firefox 67+ - Opera 51+ - Safari 12+ Next.js 支持在 `package.json` 文件中配置 `Browserslist` ```js { "browserslist": [ "chrome 64", "edge 79", "firefox 67", "opera 51", "safari 12" ] } ``` 内置 CSS 支持 --- ### 添加全局样式表 如果不存在,请创建一个 `pages/_app.js` 文件。 然后,导入 `styles.css` 文件 ```jsx import '../styles.css'; // 在新的“pages/_app.js”文件中需要此默认导出 export default function MyApp({ Component, pageProps }) { return } ``` 例如,考虑以下名为 `styles.css` 的样式表 ```css body { font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; margin: 0 auto; } ``` ### 从 node_modules 导入样式 对于全局样式表,如 `bootstrap` 或 `nprogress`,您应该在 `pages/_app.js` 中导入文件 ```jsx // pages/_app.js import 'bootstrap/dist/css/bootstrap.css' export default function MyApp({ Component, pageProps }) { return } ``` 从 Next.js 9.5.4 开始,您的应用程序中的任何地方都允许从 `node_modules` 导入 CSS 文件 ### 添加组件级 CSS (CSS Modules) 您无需担心 .error {} 与任何其他 `.css` 或 `.module.css` 文件!他将被生成 `hash` 名称 ```css .error { color: white; background-color: red; } ``` 然后,创建 `components/Button.js`,导入并使用上面的 CSS 文件: ```jsx import styles from './Button.module.css' export function Button() { return ( ) } ``` ### Sass 支持 Next.js 允许您使用 `.scss` 和 `.sass` 扩展名导入 Sass,可以通过 CSS 模块和 `.module.scss` 或 `.module.sass` 扩展名使用组件级 `Sass` ```shell $ npm install --save-dev sass ``` 在使用 Next.js 的内置 `Sass` 支持之前,请务必安装 `sass` ### 自定义 Sass 选项 通过在 `next.config.js` 中使用 `sassOptions` 来实现配置 `Sass` 编译器。例如添加 `includePaths`: ```js const path = require('path') module.exports = { sassOptions: { includePaths: [path.join(__dirname, 'styles')], }, } ``` #### Sass 变量 ```sass /* variables.module.scss */ $primary-color: #64ff00; :export { primaryColor: $primary-color; } ``` 在 `pages/_app.js` 中导入 `variables.module.scss` ```jsx import variables from '../styles/variables.module.scss' export default function MyApp({ Component, pageProps }) { return ( ) } ``` ### CSS-in-JS 最简单的一种是内联样式: ```jsx function HiThere() { return (

hi 这里

) } export default HiThere ``` 使用 [styled-jsx](https://github.com/vercel/styled-jsx) 的组件如下所示: ```jsx function HelloWorld() { return (
Hello world

scoped!

) } export default HelloWorld ``` 当然,你也可以使用 [styled-components](./styled-components.md) Layouts --- ### 基础示例 ```jsx // components/layout.js import Navbar from './navbar' import Footer from './footer' export default function Layout({ children }) { return ( <>
{children}