服务端渲染-Next.js
之前有分享过服务端渲染的一些知识,本周继续就服务端渲染进行分享,对于NextJs我也是初次接触,有不正确的地方欢迎大家指正。
服务端渲染初识
Next.js
初始化项目
Bashnpx create-next-app@latest --typescript
# or
yarn create next-app --typescript
# or
pnpm create next-app --typescript
启动项目
"scripts": {
"dev": "next dev -p 6006",
"build": "next build",
"start": "next start -p 6006",
"lint": "next lint",
"server": "next build && next start -p 6006"
},
目录结构
TypeScript.next // 打包目录
components // 公用组件
Footer
Layout
Navbar
...
node_modules // npm包
pages // 页面
api // api目录
_app.tsx // 全局处理
index // 首页
...
public // 静态文件
styles // css样式表
utils // 工具函数集
next.config.js // next配置文件
package.json
...
配置next/image的远程模式
TypeScript/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**.myqcloud.com',
},
],
},
}
module.exports = nextConfig
切换路由时添加加载动画
pages/_app.tsx
通过监听路由事件,为next添加页面过渡动画
TypeScriptimport Router from "next/router";
import type { AppProps } from "next/app";
import { useEffect, useState } from "react";
import Layout from "../components/Layout";
import PageLoading from "../components/PageLoading";
import "../styles/globals.css";
export default function App({ Component, pageProps }: AppProps) {
const routeChangeComplete = () => {
(document.getElementById("__next") || window).scrollTo(0, 0);
};
const [loading, setLoading] = useState<boolean>(false);
useEffect(() => {
Router.events.on("routeChangeComplete", routeChangeComplete);
Router.events.on("routeChangeStart", () => {
setLoading(true);
});
Router.events.on("routeChangeComplete", () => {
setLoading(false);
});
Router.events.on("routeChangeError", () => {
setLoading(false);
});
return () => {
Router.events.off("routeChangeComplete", routeChangeComplete);
};
}, []);
return (
<Layout>{loading ? <PageLoading /> : <Component {...pageProps} />}</Layout>
);
}
实现动态路由 getStaticPaths
TypeScriptexport async function getStaticPaths() {
// 调用外部 API 获取内容
const res = await fetch(`https://wp-boke.work/api/getClassifyListPage`);
const posts = await res.json();
const arr = [] as string[];
for (let i = 1; i <= posts.data; i++) {
arr.push(i.toString());
}
return {
// 必须叫paths,值必须是数组
paths: arr.map((v) => ({ params: { page: v } })),
// https://nextjs.org/docs/api-reference/data-fetching/get-static-paths#fallback-false
fallback: 'blocking', // true false 'blocking'
};
}
设置缓存失效
getStaticProps生成静态页面后,可以添加revalidate设置页面缓存的时间,过期后,下次请求将重新生成页面数据
TypeScriptexport async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(
`https://wp-boke.work/api/getClassifyDetails?id=${params.blogID}`
);
const posts = await res.json();
// Pass post data to the page via props
return {
props: { posts },
revalidate: 60, // In seconds
};
}