【AIGC实用案例分析9】:开发 Nodejs 全栈 AIGC 项目(已公开测试)踩过的 15 个坑

背景

最近我一直在开发一个 Node 全栈 AIGC 项目 划水AI,技术栈是 Nodejs + Next.js + pgsql 数据库 + React + Tiptap 编辑器 + ChatGPT API

这个项目(一期功能)计划 7 月上线,现还在公开测试中,想报名参与的可私聊我。

我开发的 2-3 个月期间,遇到了很多问题,踩了很多坑,本文分享一些比较典型的。这些都是非常宝贵的项目经验。

而且,这些问题都是真实上线的项目才能遇到的,你在本地开发一个 demo 练手是遇不到这些问题的。

PS:现在项目公开测试中,就是真实的线上环境(预发环境),托管在阿里云 Serverless 函数计算 FC 服务中。

问题1:next-theme 切换黑白主题的 warning

项目使用了 shadcn-ui 组件库,其中使用 next-theme 来切换黑白主题

但当代码运行时会有一个浏览器警告,如下图

通过查询 shadcn-ui GitHub issue 可找到一个解决方案,在 html 标签添加<html lang="en" suppressHydrationWarning> 属性即可。

根据 React 相关文档,这个问题是因为客户端内容和服务端渲染的内容不一致,而导致的一个警告,某些情况下这是难免的,所以它给出了这样的属性来避免。

问题2: prisma 连接 pgsql 的小问题

Prisma 是 Nodejs 非常流行的 ORM 工具,用于连接和操作各种数据库,划水AI 项目用的是 pgsql 数据库。

当用 prisma 连接 pgsql 数据库的时候,遇到了很多小问题。例如密码尽量不要选择特殊字符,否则需要替换

还有参与 划水AI 项目的其他同学,在项目 wiki 中分享的他自己遇到的一些问题,例如

问题3: Next.js middleware 只能运行在 Edge 运行时

Edge runtime (边缘运行时)是用于快速计算和分布式计算,和 Nodejs 运行时有区别,它更轻量级,支持的 API 更少。

Next.js middleware 是运行在 Edge runtime 的,一般用于根据 Request 请求做一些判断和处理。

所以,项目中想要在 middleware 中使用 Prisma 请求数据库的时候,Next.js 就报错了,如下图:

由于 Vercel 在国内没法访问,我们后来使用了其他方式来处理这个问题,暂时没用 middleware 。

问题4: docker build 导致服务器宕机

划水AI 线上环境部署到阿里云 Serverless 函数计算 FC ,但测试环境是用 Github Action + Docker 部署的,部署在一台云服务器上。体验不同的部署方法。

由于我买的这个云服务器配置有点低(价格便宜)所以执行 docker build 时候经常会导致服务器宕机,连接不上,报错 255

后来换了一种思路解决这个问题。先在 Github action 中构建 docker image ,然后推送到 docker hub

最后再在云服务器上 docker pull 这个镜像。这样免去了在云服务器上执行 docker build 也就不会再出现宕机的情况了。

这个过程说来简单,其实操作起来细节挺多的,这些我都记录在项目的 wiki 中,想了解的可以私信找我。

问题5: docker hub 被限制访问

上个问题解决后,又遇到 docker hub 访问不了的问题。今年 6 月才发生的,我正好赶上。

现在从 docker hub 下载的 docker 镜像非常不稳定,目前也没有找到合适的解决方案。只能先手动操作部署,等过一阵看看网络情况再说吧。在国内做个程序员太难了...

问题6: NextAuth 登录校验的一些问题

NextAuth 提供了丰富的登录校验功能,配置方便,在 nodejs 框架 Next 和 Nest 中使用都非常方便。但我在使用它过程中也遇到了几个问题

  • 频繁使用 github 登录时,会报错 (这也许是 GitHub OAuth 服务的机制)
  • 邮箱登录有时候会报错,可能是网络问题,例如我线上就需要用 gmail ,用 163 就不行
  • 频繁访问数据库获取 session ,没有缓存机制

问题7: Next.js 14 页面缓存的问题

Next.js Cache 缓存机制 是为了提高网页性能,减少数据请求和重复渲染的。但缓存了带来了很多问题。

例如,需要手动执行 revalidatePath(pathName) 才能导致页面缓存失效,重新刷新数据。如果忘记了 revalidatePath 你就会很困惑:为啥页面不刷新呢?

再例如,Next.js 页面缓存失效是全部刷新,没法部分数据刷新,这块只能自己通过客户端组件来解决。

划水AI 点击左侧文档列表跳转页面,这里我就使用了 pushState H5 history 方式来解决的。没法用 Next.js 自带的路由跳转,否则会被缓存机制搞的乱七八糟的。

所以,Next.js 15 RC 去掉了缓存。

问题8: 网络配置对访问速度的影响

由于项目域名 huashuiAI.com 还没有备案(当前使用 GPT 接口,备案有困难),所以服务器和 CDN 不能选择国内的。当前 CDN 的网络情况测速效果不好,因为节点都在国外(下图右侧)

如果选择香港地区,效果会好很多,如下图。后面会备案,选择国内的 CDN ,速度就全在 10ms 之内,起飞!

对于 Web 项目的性能优化,前端的作用非常小,最重要的是网络、其次是服务端响应速度。前端优化那几十 几百 kb,对于现代的网速来说都不叫事。

所以,作为一个项目的技术负责人,得有全局思维和全栈思维,不能只盯着前端这一亩三分地。

问题9: 前端压缩图片,节省空间和带宽

现在手机拍照、电脑截图,一张图片就 1Mb 甚至几 Mb ,体积太大了。图片要存储在 OSS 服务,体积大了占用空间、浪费带宽,这都是钱。

所以,图片得压缩。一张图片压缩到几百 kb 就可以满足网页的浏览需求,同时提高了网页的加载性能。

压缩可以从两方面入手。

第一,上传图片时压缩,可以使用 browser-image-compression 插件,用它给出的 demo 可以看到一个普通图片可以压缩到 1/3 体积。

使用也非常简单

 

const imageCompressionOptions = { maxSizeMB: 1, maxWidthOrHeight: 1200, useWebWorker: true, } // 压缩图片 const blob = await imageCompression(file, imageCompressionOptions) const compressedFile = new File([blob], file.name) // 上传文件

第二,加载时压缩图片。阿里云 OSS 自带压缩图片的尺寸的功能,文档 help.aliyun.com/zh/oss/user…

一个图片 url 后面加上 ?x-oss-process=image/resize,w_800,m_lfit 就可以把图片宽度设置为 800px

经过图片的压缩和其他优化操作,最终效果非常好。一张图片原图 2M ,最终在编辑器中加载是 422Kb

问题10: 阿里云 Serverless 遇到 maxMemoryUsage问题

“本地没问题,但发布以后就报错” —— 这种情况很常见,一个高级程序员要能独立解决这种功能问题,而不是束手无策。

但想要学习和体验这种问题,你就需要找一个真实线上项目去学习和参与。划水AI 项目就经常遇到这种功能问题。

项目本地运行没问题,docker 发布到测试机也没问题,但是发布到阿里云 Serverless 函数计算 FC 后遇到了 maxMemoryUsage问题,是在登录跳转时发生的。

这个报错信息,一开始以为真的是内存问题,但是看服务器的内存监控,并没有出现内存暴增的情况,而且光点击个登录按钮,也不能触发消耗内存的操作。所以应该不是内存相关的问题。

后来通过 N 次分析和其他同学的讨论,发现是 NextAuth 跳转路由的问题,使用 Next.js 自带的 redirect 方法跳转就会遇到这个问题。

于是,就换了一种方式:点击登录按钮就用普通的跳转方式,不用 redirect,就不会在出现这个问题。

这个问题的详细原因我至今尚未找到,看报错是 Next.js 提示的,但又只在阿里云 FC 环境下才报错,很迷惑。

但这个不重要,重要的是我把问题解决了,可以在线上使用了,可以和老板(如有)交代了。至于原因以后可以慢慢分析。

问题11: OpenAI Rate limit 规避限制

OpenAI API 服务有 Rate limit 请求频率限制,文档 platform.openai.com/docs/guides…

文档中对 Rate limit 的原因也说的很清楚:防止滥用,更公平,更好的管理 —— 这没问题。

如果项目用户多了,大家高频请求 AI 接口,就可能触发 OpenAI Rate limit ,这些都得提前考虑,如何规避。

我考虑了好久,发现最有效的方式是:用多个实例轮流请求,分摊请求,就不容易达到 Rate limit 。而且这种设计扩展性非常好,可以扩展多个 key 和实例。

问题12: 关于 ChatGPT 的 token 和计算

项目的 AI 写作功能可以免费使用,但是也不能无限制的使用。毕竟 AI 接口是需要花钱购买的,用户多了成本太高。

限制使用,有的网站会限制次数,如 notion ,新用户试用 30 次 AI 功能。而我们是限制 token 数量,这样会更加公平,因为每次请求的 token 都不一样。

限制 token 就需要计算每次请求的 token 数量,token 不是 char length ,它有单独的计算方法。

我查询了好久该如何计算 token ,最后发现 OpenAI 的接口直接可以给返回 …… 白费功夫。但查询过程中让我深刻理解了什么是 token ,也算是一种学习过程。

问题13: AI 请求中止时,无法得到 token 数量

接着上一个问题,但我们中止 AI 请求时,它就不返回 token 数量了。因为 token 数量是在最后返回的。

此时本应该去手动计算 token 数量的,但是这样做成本太高,因为计算起来很麻烦。所以我暂时没有做,中止了就干脆不去计算 token ,也不影响用户使用。

对于一个完整的项目来说,有些问题解决不了(或优先级比较低)就可以先不解决,只要不影响用户使用即可。毕竟精力有限,问题得一个一个解决,按优先级顺序来。

问题14: OpenAI key 政策不稳定

前几天 OpenAI 对 API key 进行了政策调整,导致很多 key 不能使用了,直接报 429 错误

划水AI 的重要接口都有监控和报警,如遇到某个 key 不能使用会立刻报警,并用其他的 key 代替

既然 OpenAI 的使用难度越来越大,那我们就要考虑接入国内的 AI 服务,例如 Coze deepseek 。待有结论了我会继续写文章分享。

问题15: AI 支持 markdown 格式

最开始 AI 是不支持 markdown 格式的,只支持纯文本。但当 AI 输出 markdown 格式时,就只能按照纯文本输入,很别扭。

划水AI 使用的是 tiptap 编辑器,而 tiptap insertContent 不支持 markdown 格式,文档 tiptap.dev/docs/editor…

所以得先把 markdown 转换为 html 格式,再插入编辑器。使用 markdown-it www.npmjs.com/package/mar…

现在 划水AI 可生成各种富文本格式,如大纲、代码块、表格等。

总结

经常有同学说:面试时感觉项目没有难点,没啥可说的。

其实无论是工作项目,还是业余项目,只要你认真做,当个正式的项目来做,你肯定会遇到很多很多的问题,积累下来面试时就有的说。

重点是正式项目,你在本地开发一个 demo 玩耍一下,那肯定遇不到啥困难。

要创建一个Node.js全栈项目,你可以按照以下步骤进行操作: 1. 在根目录下创建一个名为`app.js`的文件,作为项目的入口文件。 2. 在`app.js`中导入所需的模块和中间件。首先,导入`express`模块: ```javascript const express = require('express'); ``` 3. 创建一个`express`的服务器实例: ```javascript const app = express(); ``` 4. 配置跨域。运行以下命令,安装`cors`中间件: ```shell npm i cors@2.8.5 ``` 在`app.js`中导入并配置`cors`中间件: ```javascript const cors = require('cors'); app.use(cors()); ``` 5. 配置解析表单数据的中间件。运行以下命令,安装`body-parser`中间件: ```shell npm i body-parser@1.19.0 ``` 在`app.js`中导入并配置`body-parser`中间件: ```javascript const bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); ``` 6. 导入其他所需的模块和中间件,根据项目的需求进行配置。 7. 在`app.js`中编写路由和处理程序,可以根据业务需求将路由和处理程序分离到不同的模块中。 8. 在`app.js`中启动服务器,指定端口号并监听请求: ```javascript app.listen(3000, () => { console.log(`api server running at http://127.0.0.1:3000`); }); ``` 通过按照上述步骤进行配置,你就可以创建一个基本的Node.js全栈项目了。记得在项目中使用`jsonwebtoken`包来生成和验证Token字符串,可以在`router_handler/admin_handler.js`模块中导入该包并进行相应的操作。另外,你还可以在`config.js`文件中配置加密和还原Token所使用的`jwtSecretKey`字符串。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Vue3+nodejs全栈项目(资金管理系统)——后端篇(一)登录、注册](https://blog.csdn.net/weixin_45732235/article/details/128008481)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青少年编程作品集

你的赞赏将带来极佳的运气和才气

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值