Next.js 踩坑记录
发表于
浏览量1452
评论数0
Next.js 踩坑记录
最近博客前端重新换了技术栈写了一下,改用了支持SSR渲染的next.js前端框架,基于react,前前后后踩了不少的坑,从大概4月份开始的,中途遇到了很多卡手的难题,在网上查阅相关的资料也大多都是国外的,以至于到现在才算是有雏形(
其实也有摸鱼)。在这里先记录一些。
Next.js和已有后端项目的结合
首先Next.js中有一个API 路由
东西,可以理解为在 Next.js 中可以直接写 node 代码作为后端服务来运行,直接维护一个全栈项目,使用文件路径作为路由地址,开始的时候被这个误导了,一直在用它这个api路由,后来还真的想去用Next.js写全栈了。
不过在那个时候了解了一个叫Prisma的框架,是一个功能强大的数据库工具和 ORM 框架,它简化了与数据库的交互,并提供了类型安全、高效和直观的方式来管理应用程序的数据层。使用 Prisma,开发人员可以更专注于业务逻辑的开发,而无需过多关注底层数据库的操作 ,百科如是的说。实操了一下,感觉是挺新的,也挺厉害,就是我要是再推翻后端框架,感觉工作量就不是一般的大了。
我有后端服务的,所以我只需要直接在组件里调用即可,不过需要注意的是,Next.js它里面的组件分为服务端组件(页面组件)和客户端组件,在项目根目录下的pages
下的都是服务端组件,在服务端组件里面可以使用getInitialProps
, getServerSideProps
, getStaticProps
。这些都是用于数据获取的方法:
-
getInitialProps
: 这是 Next.js 早期版本中使用的一种方式,用于在服务器端获取数据并将其传递给页面组件。它可以用于服务器渲染和客户端渲染,并且可以在每次页面刷新时获取新数据。然而,自从 Next.js 9.3 版本起,推荐使用getServerSideProps
或getStaticProps
替代该方法。 -
getServerSideProps
: 这个方法用于在每个请求时在服务器端获取数据,并将其作为 props 传递给页面组件。它适用于需要在每次请求时获取最新数据的情况,比如需要根据用户的登录状态进行动态渲染。getServerSideProps 返回的数据将在每次请求时都被计算,因此它可以实现动态的服务器渲染。 -
getStaticProps
: 这个方法用于在构建时在服务器端获取数据,并将其作为 props 传递给页面组件。它适用于静态生成的页面,即页面内容在构建时就已经确定,并且不会因为用户的请求而变化。getStaticProps 可以在构建时预渲染页面,从而提供更好的性能和缓存效果。
这些方法都是异步函数,而且在方法里调用自己的后端api,要使用全路径,即使是代理转发也不行。
另外在Next.js 13中,新加了一种app目录模式,去掉了page
目录,大概了解了一下,app目录模式,默认是服务端组件,要转变成客户端组件可以在文件头部写上"use client"
,这个组件就变成客户端组件了,当然其下如果有组件也是客户端组件了。新版本也没有了以上三种方法,获取数据直接用异步函数获取即可。
以下是我在服务端获取数据的一个示例:
export default function Whisper({
data,
statistics,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
......
return (
......
);
}
export async function getServerSideProps() {
const baseUrl = process.env.BASE_URL;
let data: any = [];
await request.get(`${baseUrl}/messages`).then((res: any) => {
data =
res && res.success ? res.data.filter((v: any) => v.site !== "-1") : [];
});
const res1: any = (await request.get(`${baseUrl}/statistics`)) || null;
const statistics = (await res1) && res1.data;
return {
props: {
data,
statistics,
},
};
}
这里为了好维护,设置了一个环境变量来拼api的全路径。在getServerSideProps
方法里按照我的理解主要是为了预渲染,做SEO,后续的数据获取及交互的一些接口请求,正常在方法里面写就好了。那说到交互,那么就要来说说在Next.js中怎么解决跨域了。
Next.js的一些配置
在根目录会有一个
next.config.js
文件,就是项目的配置文件,配置这块很多,我只讲讲我用到了的,且觉得大概率都会用到的。
跨域配置
const nextConfig = {
async rewrites() {
const ret = [
{
source: "/api/:path*",
destination: "http://localhost:8001/:path*", // 根据实际情况来
},
......
];
return {
beforeFiles: ret,
};
},
};
module.exports = nextConfig;
设置环境变量
const nextConfig = {
env: {
BASE_URL: process.env.BASE_URL,
},
};
module.exports = nextConfig;
这里我是在根目录有.env
,取的它的值。
配置图片解析域名
const nextConfig = {
images: {
domains: [
"cdn.staticaly.com",
"s2.loli.net",
"i.loli.net",
],
},
};
module.exports = nextConfig;
这样配置后,Next.js将允许从这三个域名加载图像。如果你尝试从其他域名加载图像,Next.js将会阻止加载,并在控制台中显示错误信息。
domains
属性只在使用配置cdn
可以在Next.js中,将打包后的static
文件,使用cdn来优化网站加载速度,如下需要对配置做一些修改:
const isProd = process.env.NODE_ENV === "production";
const nextConfig = {
assetPrefix: isProd
? "https://cdn.example.com" // 根据自己的cdn服务来定
: "",
};
module.exports = nextConfig;
如上配置后,在生产环境下,项目加载静态资源文件,会从https://cdn.example.com
这个域名下找。
其他配置
如果你采用静态资源打包方式部署自己的项目,可能需要配置一下打包文件的输出目录:
const nextConfig = {
output: "standalone", // 这个目录名称是不能变的
};
module.exports = nextConfig;
如果需要对项目做体积优化,可能会用到:
experimental: {
legacyBrowsers: false,
},
这样的意思是不支持旧版浏览器。这意味着,Next.js将不会生成针对旧版浏览器的兼容性代码,以便提供更好的性能和较小的文件大小。看你需要对旧版浏览器兼容不。
写法上需要注意的点
- 在Next.js中,不要使用P标签下包裹着P标签,p标签下包裹着div标签,这样会导致出现服务端和客户端渲染的结果不同儿出现报错。
- 避免在预渲染的时候使用到
window
和storage
等客户端才有的功能。 - 在引入第三方依赖或者组件的时候,尽量使用
dynamic
动态导入,只加载需要的,避免打包体积太大。 - 在Next.js中如果需要自定义每一个页面组件的
head
做SEO或者是引入第三方js,css,font等,使用Next.js自带的对应组件,找到适合的模式,可以得到一定的性能提升。 - Next.js支持多种CSS样式的处理方式,包括内联样式、CSS模块和CSS-in-JS等。可以根据项目的需求选择合适的方式来处理样式,如果是使用CSS模块,有时候可能会用到动态改变className,可以用如下写法:
<div
className={
styles[`${card.key === active ? "k-info-card-option-active" : ""}`]
}
onClick={() => {
setActive(card.key);
}}
key={card.key}
></div>
大概有这些吧......
写在最后;
地点: 成都(
社畜ing) 时间: 2023-07-23 23:30:00 心情:头晕晕的有点难受