


前言需要注意的是,我们的pinia仓库持久化操作只有在客户端渲染时操作才能触发,比如当第一次访问页面时,你可能直接在setup中给仓库存储内容,这是无效的,我们需要保证在客户端渲染时触发才行,比较好的办法就是在onMounted生命钩子中触发。究其原因就是服务端是没法操作local、cookie这些浏览器配置,而在setup中的代码,是会在服务端也运行的,这就可能导致部分代码到了客户端不再运行。教程安装依赖pnpm i @pinia/nuxt @pinia-plugin-persistedstate/nuxt安装成功后在nuxt.config.ts中配置模块:// nuxt.config...
前言Nuxt3的环境变量配置有点和平时vue项目的不同,它为了考虑服务端渲染和客户端渲染两种情况,以及安全相关的考量,它的环境变量用起来会有点繁琐。在官方的预设中,你可以使用.env这个文件名的环境变量文件,但是它只会在开发中使用,并不会在构建生产的时候使用,所以我的建议就是放弃使用.env文件名,转而使用指定具体文件的形式。但是即便我们指定了环境变量文件,它也不会出现在Nuxt提供的useRuntimeConfig配置composable中,考虑到安全,我们在服务器渲染时可能有部分环境变量不能出现在客户端中,以防有人恶意获取从而产生破坏。所以nuxt并没有一股脑的把环境变量挂载上去,而...
前言实现了文件上传,自然要实现文件下载,经过我的实践总结出两个下载本地文件的方式:第一种是通过api请求,以返回文件流的形式将本地文件返给前端,前端自己接受到文件流后自己把Blob转一下;这种方式的话可以监听文件是否下载完成,完后下载完后删除本地磁盘上的文件。第二种是后端将文件存储在本地磁盘上,创建一个访客也能访问的下载目录,将文件丢到这里,再放开这个目录供访客下载,后端只需要在api返回下载地址即可。这种方式对于用户来说会更加方便,因为可以使用不同的下载工具下载文件。前端也省事,直接创建a链接元素,触发点击就是使用浏览器下载文件了。教程[hide]文件流下载我就不详细写服务了,直接在控...
前言当我们在服务器去拉取git仓库代码使用时候,比如生产环境中,我们去拉取代码,肯定要保证拉取成功,但是git如果本地文件有变化,就会导致拉取失败,一般情况下我们都是通过添加脚本的形式实现生产环境自动拉取,从而节省人力,如果因为本地文件与仓库不同就拉取失败,这就显然并不健壮。而且生产环境基本上都是可以让远程仓库直接覆盖本地文件的,一切以远程仓库文件为准,所以我们需要实现让远程仓库强制覆盖本地。教程假如我希望让远程的develop分支覆盖本地,就先fetch请求远程仓库对应分支的最新资源git fetch origin develop完毕后我们进行覆盖git reset --hard or...
前言三星浏览器是我目前个人觉得用起来比较舒服的一个软件,从三星s7e一直沿用到现在,相比较谷歌浏览器,三星浏览器的视频增强功能非常好用,当然还有一个广告拦截功能,需要安装专门的插件,但是这两年即便是从谷歌商店下载的三星浏览器还是beta版本,都不能启用abp插件。解决的方式就是需要手动调整一下,具体教程如下:教程在浏览器地址栏输入:internet://debug/此时会进入到一个页面此时在点击浏览器设置,翻到最底下就会出现一个Debug settings选项,点击进去。找到选项:Feature variation test,点击进入点击Sales code选项,翻到最底下点击Other...
前言最近在实际项目运用中,发现之前学习的DTO还是太浅显了,在实战后了解了两个非常重要的知识,特此分享出来。[hide]继承在代码中,复用是一个很重要的部分,如果编写的代码没有任何可复用的部分,只能说编写代码的能力太差,业务代码中,极大部分都是可以复用的,而复用的手段之一就是继承。在Nestjs中DTO是与class-validator配合做校验使用的,如果我们简单的使用extends继承的话,就会丢失class-validator的校验规则。import { IsNotEmpty, IsNumber, Min, Max } from "class-validator"...
前言对接第三方登录,最有名的肯定是谷歌了,全球大部分web程序,都有对接谷歌登录的功能。在之前的文章中我们通过passport的jwt策略,实现了本地jwt鉴权登录处理,passport本身就是一种策略模式,通过调用不同的策略实现不同的效果,其中就有关于谷歌登录的处理,这就大大的减少了我们的心智负担。但是需要注意,谷歌登录对网络要求非常高,因为咱们是国内环境,我尝试使用windows下的clash进行fq处理,哪怕是全局规则,nestjs这边还是无法访问到谷歌的服务,从而导致报错:Failed to obtain access token我最终通过路由器的OpenClash解决这个问题,...
前言在做node后端服务开发的时候,使用环境变量已经是基操了,但是在ts中默认的环境变量是第一个非常宽泛的类型:interface Dict<T> { [key: string]: T | undefined; } interface ProcessEnv extends Dict<string> { /** * Can be used to change the default timezone at runtime */ TZ?: string; }这就导致我们自定义的环境变量是没有属性提示的,有点难受,所以需要我们自己去声明一个...
前言回老家之后找到了之前忘记带走卖掉的极路由4,于是想着刷个鼎鼎大名的OpenWrt用一用,在恩山论坛找到了一个23年12月的固件,非常感谢那些还在更新的大佬,伸手党的我下载完刷入后就想着试试OpenClash,但是遇到了一些困难,折腾了几个小时才堪堪完成,期间也碰到了好多问题,为此写一篇教程,以便后续需要。教程[hide]配置OpenClash刚安装完OpenWrc,部分固件是会携带一些编译好的服务在里面,其中就会有OpenClash,这个玩意懂的都懂,作为一个程序员,我还是会有经常访问github的需求,但是国内网络环境真的一言难尽,搞这个也是刚需。假设我们现在已经有订阅连接了,我们...
前言安装stfp本意是因为OpenClash的内核更新没法通过在线的方式直接更新,谷歌搜索到了一篇本地上传文件更新的教程,教程上说通过ftp上传下载的文件,但是通过NxShell的ftp打开时提示:cannot read properties of null (reading 'readdir')显然OpenWrt自己没有sftp服务,需要自己安装。OpenWrn的账号和密码就是路由器账号密码,ssh地址为路由ip地址教程[hide]由于OpenWrn使用的是Dropbear这个ssh管理软件包,这是个比较轻量级的软件包,常用于嵌入式系统和小型足以不需要所有 Open...
前言Nestjs和Prisma的打包部署教程很少,网上比较热门的一个就是利用webpack将Nestjs打包 ,它和前端的打包差不多,会把所有的依赖项打包进来,生成的dist目录,可以直接单独部署,而如果我们使用Nestjs提供的build命令打包,不改动它的情况下,它只会将开发目录中的ts文件,转换成js文件,丢入dist目录中,其他什么也不做,就是个ts转js。这估计会让大部分人诧异,如果遵循官方这种方式,你在启动node服务的时候就必须使用dist目录下的main.js文件了。但是还要考虑环境变量等文件,我们下面细说。Prisma的打包部署需要考虑两方面:一是需要同步数据库模型,也...
前言在后端服务中,我们总是会遇到一些不安全的情况,毕竟web本身也不是一点漏洞都没有,好在有一些便捷的插件拱我们使用。helmet,通过设置 HTTP 响应标头来帮助保护 Express 应用程序;express-rate-limit,用于限制对公共 API 和/或终结点(例如密码重置)的重复请求,防止暴力攻击;本来还有一个跨域处理的CORS插件,但是目前还没有时间实际部署上线,所以在没有实际经验暂时就不写了,到时候单开一篇文章。安装依赖pnpm i helmet express-rate-limit教程这两个插件我们都需要在main.ts中启用。main.tsimport { Nest...
前言日志的记录在后端开发中是不可或缺的,在node中有一个很有名的库winston,这个库支持多种日志传输方式,比如本地文件,控制台,远程传输等。而nestjs有一个winston的模块库:nest-winston既然有了模块,那说明什么?说明我们可以通过依赖注入的形式,在其他地方直接调用模块的服务,从而实现日志记录。在log记录之前,需要分析我们要记录什么内容,比如最重要的错误日志,当发生错误的时候,我们需要记录日志,方便后续在生产环境查看问题,其次就是请求日志记录,我们记录用户的请求,url、ip地址、路由地址、请求参数等,以及我们的响应数据,也就是发送给前端的数据,针对这三种需求我...
前言之前使用了crypto-js做了一个md5加密用户密码的操作,但是由于该库本身没有提供比对方法,于是自己去实现了一个方法,而且还需要自己提供一个唯一值盐。最近发现bcrypt这个库更好用,于是改用它了。安装依赖pnpm i bcrypt pnpm i @types/bcrypt -D教程原来使用crypto-js的MD5方法,需要自己提供盐(salt),之前的做法是创建一个环境变量,然后预设一个定死的string字符串,这就导致我们需要维护一份唯一值的盐,有点麻烦。而bcrypt自身可以生成盐,并且它的盐会通过某些方式存储在加密后的字符串上,然后比对的时候,我们不需要知道之前它的盐是...
前言最近网络不太行,发现pnpm在下载一些库的时候经常卡住不动了,我记得推崇pnpm的时候,大伙都说pnpm不需要换源下载也很快,显然没有理想中那么好,无奈只能换源解决问题了。教程换淘宝源:pnpm config set registry https://registry.npmmirror.com 还原:pnpm config set registry https://registry.npmjs.org查看当前使用的源:pnpm get registry pnpm好像目前没看到有什么库能交互式操作切换。新方案我最近安装pnpm都是通过npm来安装的:npm i pnpm -g然后我发...
前言在之前的文章,我们实现了一个jwt的权限管理,通过一个自定义的Public装饰器声明公共接口,再通过app.module.ts添加一个全局守卫JwtAuthGuard。但是这种方式只能判断这个用户是登录了还是未登录了,没法实现更细化的权限管理,比如一个普通用户,他是无法管理自己的账号的,而管理员缺可以控制普通用户的账号,是禁用还是正常使用。显然我们需要一个更加细化的权限管理方式,经典就是 RBAC(Role-Based Access Control)角色访问控制设计。RBAC在RBAC中是通过不同的角色来实现权限的划分,比如普通用户user只能查看文章列表,而admin管理员是可以增...
Prisma是一个现代的数据库访问库,它本身不直接提供软删除(soft delete)和硬删除(hard delete)这样的内建机制,但你可以在应用层面实现这两种删除策略。硬删除:直接从数据库中删除记录,这是数据库最基本的删除操作。在Prisma中,你可以使用delete或deleteMany方法来执行硬删除。软删除:软删除通常是通过在数据库记录中设置一个标记(如deletedAt时间戳字段)来实现的,而不是实际从数据库中移除记录。这样做的好处是,你可以保留数据,以便将来需要恢复或保留删除记录的历史。为了在Prisma中实现软删除,你可以按照以下步骤操作:在你的模型中添加一个如dele...
前言在之前的文章中我们已经实现了格式化响应的数据结构,现在我们就来处理响应的具体数据,很常见的一个场景:我们查询了一条用户信息,这个信息可能包含了用户的账号、密码、昵称、头像,但是我们肯定不能把密码也返回给前端,所以我们就需要控制返回的数据。有很多种做法,比如简单的就是通过js的delete操作符去删除对象上的属性。如果是使用prisma的话,可以在查询的时候,配置select属性来限制返回的查询数据。// 假设我们有一个User模型,带有id, name, email和password字段 // 我们想要返回用户的id和name,但不返回email和password const us...
区分两种注册方式在nestjs中我们有两种注册全局的方式,一种是通过NestFactory.create得到app实例,在通过app.useGlobalXXX的方式去注册全局的东西,比如全局拦截器,全局过滤器等。import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app.module"; import { ResultFormatInterceptor } from "@/utils/interceptor"; async funct...
前言这个是非常常见的一种配置,我们的接口通过域名访问,但是这个域名不一定全部都给后端使用,所以一般后端服务都是基于域名,通过一个前缀路由来实现区分,比如:www.xxx.com # 后端服务1 www.xxx.com/v1 # 后端服务2 www.xxx.com/v2通过一个统一的路径名来区分。教程在nestjs中,这个配置放在了文档比较末端的地方,代码如下:import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app.module"; async f...
前言在前端项目开发的时候,使用路径别名@/已经是基操了,但是在后端开发的时候,如何使用路径别名确实也没怎么了解过,配置后才发现真的超级简单。教程由于Nestjs本身就是ts运行的,所以在项目初始化后就有tsconfig.json文件了,我们只需要配置一下paths就可以直接使用了。tsconfig.json{ "compilerOptions": { "paths": { "@/*": ["src/*"] } } }使用:import {...
前言Nestjs的文件上传官方文档给的讲解非常少,在掘金搜对应文章也大多数不全,有的都是好几年前的处理了,这里贴一下我学习到的处理方式。首先我们需要三个依赖:multer,这个是一个express的中间件,它只会处理multipart/form-data 类型的表单数据,主要用于上传文件。@types/multer 这个是multer的一个类型声明依赖。@nestjs/platform-express,这个依赖提供了上传模块和拦截器用于处理上传,它本身也依赖于multer。大概流程:首先我们从 @nestjs/platform-express引入MulterModule模块进行注册,为此...
最近评论