Posted on:
Last modified:
当我们要写一个稍微复杂的 React 应用的时候,就需要路由功能了,比较流行的是 react-router, 这是一个很好的库。但是当我们已经用到路由的时候,下一步就该考虑如何做服务端渲染了,所以 直接上 next.js 吧。
创建第一个 next 项目:
pnpm create next-app MY-APP --ts
// 添加一些常用的库
cd MY-APP
pnpm add tailwindcss postcss autoprefixer axios react-hook-form dayjs nprogress
Next 的核心概念是页面。按照约定,放在 /pages 文件夹中的每一个组件都是一个页面,每个组件
需要使用 export default
导出。
/pages/index.tsx
对应的自然是首页了。/pages/xxx/index.js
对应的是 /xxx
路径。
import type {NextPage} from 'next'
const HomePage: NextPage = () => {
return <div>Welcome to Next.js!</div>
}
export default HomePage
pnpm next
就可以看到首页啦!
作为一个服务端渲染框架,Next.js 既可以预先编译生成静态文件,也可以每个请求实时编译。不过, 推荐的方式是预先编译。
Next.js 完全按照文件的物理路径来确定路由,参数就体现在文件路径中。要实现 post/1
,直接
定义 pages/post/[id].js
文件即可。
在一个页面中,export 一个 async 函数 getStaticProps/getServerSideProps
就可以实现获取
服务端的数据。
getStaticProps
还需要使用 getStaticPaths
函数配合生成所需路径,比如所有的文章的 id.
// pages/post/[id].js
export async function getStaticProps({params}) {
const res = await axios.get(`http://example.com/api/post/${params.id}`)
return {
props: res.json // 传递给页面组件的 props
}
}
// 导出所有需要静态生成的页面的参数
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } }
],
fallback: true // 是否允许未生成的页面实时渲染
// fallback 的选项有三个:
// 1. false, 未生成的页面直接 404
// 2. true, 客户端请求数据渲染
// 3. 'blocking', 服务端渲染
};
}
getStaticProps 获得的参数是:context, 其中比较重要的几个属性:
getStaticPaths 和 getStaticProps 会在 build 的时候运行,不过在开发阶段(next dev
),每个
请求都会触发 getStaticPaths.
当使用服务端渲染的时候,每次从客户端路由到一个页面,会调用 getServerSideProps 来获取数据。
export async function getServerSideProps({params}) { // 同样的 context 参数
return {
props: {}, // 传递给页面组件的 props
}
}
在这个函数中,应该直接读取数据库或者外部 API. 除此之外,传统方式是在客户端获取数据,可以 使用 useSWR 库。
Next.js 中必须在 pages/_app.js
中导入全局的 css,这个文件会应用到所有页面。除此之外,
不能再导入别的自定义全局 css 文件。
// 自定义样式
import '../styles.css'
// 第三方库的样式
import 'antd/dist/style.css'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
首先,安装 tailwindcss
pnpm add tailwindcss postcss autoprefixer
pnpm tailwindcss init -p
编辑 tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
确保 _app.js
中已经引入了 global.css,然后编辑 global.css
@tailwind base;
@tailwind components;
@tailwind utilities;
URL 参数需要使用 router 来手动读取,还可以使用 router.push 在 JS 中跳转。
import {useRouter} from 'next/router'
function MyPage() {
const router = useRouter()
const path = router.pathname
const {keyword} = router.query
const query = {foo: "bar"}
const onSubmit = () => {
router.push("/ok")
// or
router.push({pathname: "/ok", query: {foo: "bar"}})
}
}
默认情况下,跳转后还会回滚到页面顶部。如果要跳转到外部链接,直接使用 window.location
就好了。
router
的其他常用方法还有:
Next.js 中的链接是这样的:
import Link from 'next/link'
// about
<Link href="/about"><a>About</a></Link>
// blog/hello
<Link href={{pathname: "/blog/[slug]", query: {slug: "hello"}}}>
<a>{post.title}</a>
</Link>
// q?kw=hello
<Link href={{pathname: "q", query: {kw: "hello"}}}>
<a>Search</a>
</Link>
直接放到 /public
目录,就能在根路径访问了。
Next.js 提供了 Image 组件,相对于裸 <img/>
标签做了不少优化。需要使用 import
显式导入。
import Image from 'next/image'
function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src="/me.png"
alt="Picture of the author"
// width={500} automatically provided
// height={500} automatically provided
// blurDataURL="data:..." automatically provided
// placeholder="blur" // Optional blur-up while loading
/>
<p>Welcome to my homepage!</p>
</>
)
}
Next.js 中提供了 next/head
包,省去了使用 react-helmet 修改 header 的逻辑。在 meta 标签
中最好使用 key,这样可以避免重复渲染多个标签。
不过,并不能在 head 中增加 css,而要使用 import 的方式。
import Head from 'next/head'
function IndexPage() {
return (
<div>
<Head>
<title>My page title</title>
<meta property="og:title" content="My page title" key="title" />
</Head>
<Head>
// 重复
<meta property="og:title" content="My new title" key="title" />
</Head>
<p>Hello world!</p>
</div>
)
}
Next.js 可以自定义 404 和 500 错误页面
修改 next.config.js, 增加 output: standalone 选项。
module.exports = {
// ... rest of the configuration.
output: 'standalone',
}
然后根据官方 Dockerfile 修改:https://github.com/vercel/next.js/tree/canary/examples/with-docker 在这个 dockerfile 中已经包含了复制 .next/static, .next/public 的逻辑,无需手动添加。
© 2016-2022 Yifei Kong. Powered by ynotes
All contents are under the CC-BY-NC-SA license, if not otherwise specified.
Opinions expressed here are solely my own and do not express the views or opinions of my employer.
友情链接: MySQL 教程站