前言:最近在学习Nest.js的文档,听着马伯庸的长安十二时辰的小说,于是就有了下面这篇学习成果......
序言
凡有井水处,皆能歌柳词;凡有浏览器处,皆需 JavaScript。
但这世间的事,往往坏就坏在"界限"二字上。
前端主"相",后端主"骨"。画皮难画骨,是以多少惊才绝艳的前端少侠,终其一生,都被困在那方寸屏幕之间,对着后端传来的 JSON 数据望洋兴叹,不得寸进。
直到那一日,Nest.js 的信鸽飞入长安,带来了一张名为"架构"的藏宝图。
这不是一本劝你转行的书,这是一本教你如何拆墙的策。
墙推倒了,便是桥。
第一章:长安城的困局
天宝十四载,长安城的坊间正是热闹非凡。
Vue 门派的旌旗在朱雀大街上猎猎作响,React 宗门的弟子们在西市高谈阔论,讲的是 Hooks 心法,论的是 Virtual DOM 幻术。乍一看,这前端江湖繁花似锦,烈火烹油。
然而,对于李少侠来说,这繁华背后却透着一丝凉意。
作为一名在前端江湖摸爬滚打多年的刀客,他的一手组件化刀法已臻化境,切页面如庖丁解牛,游刃有余。可每当夜深人静,对着那惨白的显示器,他总觉得手中的刀,短了半寸。
这半寸,便是"后端"。
每逢与后端神机营的校尉们对接接口,李少侠便觉处处掣肘。 "这字段为何要嵌套三层?" "那鉴权逻辑为何如此繁琐?" 神机营的人只冷冷回一句:"此乃系统架构之规矩,尔等切图画面的,依样画葫芦便是。"
李少侠心中不忿。前端虽妙,终究是在此岸画皮;要想真正掌控数据的洪流,非得渡河去彼岸不可。
这日,他在茶馆听说,西域传来一门奇术,名唤 Nest.js。传闻此术虽是 Node.js 的底子,却蕴含着后端架构的无上心法,且与 TypeScript 这门官话无缝契合,竟能让前端游侠也能使得动后端的重剑。
"有点意思。"李少侠放下茶盏,眼中精光一闪,"这 Nest.js,我便去会它一会。"
第二章:初探神机营
初入 Nest.js 的地界,李少侠不由得倒吸一口凉气。
这哪里是什么轻灵的脚本,分明是一座戒备森严的军营。
这里没有随意的 function 乱飞,没有 var 遍地走。取而代之的,是层层叠叠的 Module(模块) ,森严壁垒的 Controller(控制器) ,以及深藏不露的 Service(服务)。
"这布局,竟与当年的 Angular 宗门有几分神似?"李少侠暗自思忖。
正疑惑间,一位扫地僧模样的老者走了出来,那是 Nest.js 的接引使者。 "少侠可是觉得繁琐?"老者笑道,"前端求的是'快',如快马轻裘;后端求的是'稳',如步步为营。Nest.js 的第一课,便是这依赖注入(Dependency Injection)。"
李少侠不解:"何为依赖注入?"
老者指了指营帐:"假设你要造一辆战车(Class)。若你在车内自造轮子、自炼钢铁,这车便重若千钧,难以拆卸。若你只需在图纸上写明'需轮子一对',造车时自有军需官将轮子送来装上,这便是依赖注入。如此,战车与轮子解耦,想换铁轮换铁轮,想换木轮换木轮,岂不快哉?"
李少侠闻言,若有所悟。原来后端所谓的"架构",不过是把"谁来干活"和"怎么干活"分得清清楚楚,不让一人独大,亦不让一人累死。这便是 IoC(控制反转) 的精髓。
第三章:通关文牒与锦衣卫
入了营门,李少侠才知后端江湖的水有多深。
以前写前端,数据来了便是来了,不管脏净,拿来便渲染。可在 Nest.js 里,数据要想进城,得先过三道关卡。
第一道关,名唤 DTO(Data Transfer Object) 。 这好比是通关文牒。前线传来的 JSON 数据,必须严丝合缝地对上 DTO 的格式,少一个字段,多一个类型,都会被守城士兵当场拿下。 "繁琐是繁琐了些,"李少侠在定义 CreateUserDto 时叹道,"但如此一来,城内的逻辑便安如磐石,不必担心混入奸细。"
第二道关,名唤 Guard(守卫) 。 这便是负责查验身份的锦衣卫。 "站住!既要访问这 admin 路由,腰牌何在?" 只需一个 @UseGuards(AuthGuard) 的装饰器,便能在路由之前立下一尊门神。JWT 便是那腰牌,验过了,方能放行;验不过,便是一句 401 Unauthorized,冷面无情。
第三道关,名唤 Interceptor(拦截器) 。 这更像是潜伏在暗处的观察者。数据进出,皆要在它眼皮底下过一遍。你想把返回的数据统一包装成 { code: 200, data: ... } 的格式?不必在每个 Controller 里手动去写,只需在拦截器里设个埋伏,所有出城的数据便自动穿上了这层制服。
李少侠耍了一套 AOP(面向切面编程)的剑法,只觉酣畅淋漓。以前在前端代码里,业务逻辑和鉴权、日志逻辑混作一团,如乱麻难理;如今在 Nest.js 里,业务归业务,切面归切面,井井有条,如排兵布阵。
第四章:兵器库的秘密
真正让李少侠感到震撼的,是兵器库------TypeORM。
以往操作数据库,需得手写 SQL,如同赤手空拳去搏老虎,稍有不慎便是 SQL 注入的重伤。
而 TypeORM,则是给了他一套机甲。 他只需定义一个 Entity(实体) 类:
typescript
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
}
这便是用 TypeScript 的官话,去号令数据库的蛮语。不需要懂什么 SELECT * FROM,只需调用 userRepository.find(),底层的 SQL 洪流便如臂使指,奔涌而来。
"这便是 ORM 之力吗?"李少侠抚摸着代码,感受到了那种掌控数据的厚重感。
第五章:破局
三个月后。
李少侠再次站在长安城的朱雀大街上。此时的他,已不再是那个只会切图的刀客。
他的腰间,左边挂着 Vue 的短剑,右边佩着 Nest.js 的长刀。
当产品经理再次提出那个"五彩斑斓黑"的需求,并说"后端可能做不了"时,李少侠微微一笑,按住了刀柄。 "无妨,"他淡淡说道,"接口我来写,数据库我来建。"
那一刻,风起云涌。他终于明白了,所谓的全栈,并非是多学了一门语言,而是打破了那堵隔绝了数据源头与展现末端的墙。
从此,江湖上多了一位能上九天揽月(前端),可下五洋捉鳖(后端)的游侠。
而 Nest.js,便是他手中那把破局的钥匙。
批注: 欲练此功,必先修 TypeScript。若无类型系统护体,Nest.js 恐难发挥十成威力。切记,切记。