沒有盡頭,沒有開始,只有對生活無盡的熱情。
- 微信公眾號 《JavaScript全棧》
- 掘金 《合一大師》
- 視訊講解:Bilibili 《合一大師》
內容持續更新
介紹
為什麼學習Nestjs
不知大家可否聽說過 Java
語言大名鼎鼎的幾個框架——SpringBoot、SpringMVC。不可否認這些框架的設計思想在後端服務領域都是領先的。作為以 Javascript
為主要開發語言的我們,也想有這樣一些優秀的、漸進式的服務端框架,雖然在此之前有 Express
、Koa
、Egg
等基於Nodejs的服務端框架,但都不是我鍾愛的,因為我入門程式設計就是使用Java的三大框架SSH。MVC
也許是大多開發者所能接受的開發思想了,這裡解釋一下,M(Model模型即資料層)、V(View檢視,現多為前後端分離專案,後端只提供介面服務)、C(Controller控制器,控制前端請求來的路由分發等)。明白這三點只是基礎,隨著業務不斷複雜,我們需要管理的資料越來越多、資料庫操作越來越複雜、關於效能快取的要求越來越高,我們可能會變得束手無策。如何優雅地管理專案模組,變得尤為重要,我覺得 Nestjs
正是這樣一個幫助我們更好開發的框架。我們開始學習吧!
Nestjs的主要思想
Nest (NestJS)是基於Nodejs的服務端框架,建議使用Typescript進行開發(不過也同樣支援使用JavaScript開發)。通過這個框架學習,我們不僅能夠打通前後端開發任督二脈,還能學到譬如 OOP(物件導向程式設計)、FP(函數語言程式設計)、FRP(函式響應式程式設計)思想,助力高薪。
Nestjs預設選擇 Express
作為底層服務框架,你也可以通過配置選擇 Fastify
。
安裝
相信使用過 Vue
、 React
或 Angular
的同學都熟悉專案初始化的腳手架工具,Nestjs也為大家提供了一個腳手架工具,有了這個工具我們能夠更快搭建起Nestjs專案,下面我們來安裝它吧。
npm i -g @nestjs/cli
複製程式碼
為了版本一致,我們統一制定版本號為:@6.14.0,安裝命令就是
npm i -g @nestjs/cli@6.14.0
複製程式碼
安裝完成以後,我們可以通過幫助命令檢測腳手架工具是否安裝成功,命令很簡單,如下
nest -h
複製程式碼
我們如果可以看到類似如下內容,則表示安裝成功
Usage: nest <command> [options]
Options:
-v, --version Output the current version.
-h, --help Output usage information.
Commands:
new|n [options] [name] Generate Nest application.
build [options] [app] Build Nest application.
start [options] [app] Run Nest application.
generate|g [options] <schematic> [name] [path] Generate a Nest element.
Available schematics:
┌───────────────┬─────────────┐
│ name │ alias │
│ application │ application │
│ angular-app │ ng-app │
│ class │ cl │
│ configuration │ config │
│ controller │ co │
│ decorator │ d │
│ filter │ f │
│ gateway │ ga │
│ guard │ gu │
│ interceptor │ in │
│ interface │ interface │
│ middleware │ mi │
│ module │ mo │
│ pipe │ pi │
│ provider │ pr │
│ resolver │ r │
│ service │ s │
│ library │ lib │
│ sub-app │ app │
└───────────────┴─────────────┘
info|i Display Nest project details.
update|u [options] Update Nest dependencies.
add [options] <library> Adds support for an external library to your project.
複製程式碼
到這裡,你是不是迫不及待想初始化一個專案練手了呢?那我們就來建立一個專案
nest new nest-demo
複製程式碼
現在只需要靜靜地等待~ 初始化並安裝完成以後,啟動專案
npm run start
複製程式碼
然後開啟瀏覽器,輸入 http://localhost:300,就能看到呈現給我們的頁面了。我完事了,你呢?
九個核心概念
我看多很多人的演講和課程以後,發現了一個很有意思的規律,晦澀難懂的概念想講明白但是聽眾實在是聽不明白,簡單明瞭的概念不想讓聽眾覺得容易故意往復雜了說導致聽眾一樣糊里糊塗。我不想這樣,我想我的這套課程能夠從實用出發,逐步深入,最後講解該框架的設計原理與實現,可是就算我想說的很明白,框架本身的很多概念我們也沒法躲避開,與其在我們後面的工作和學習中與這些概念糾纏不休,我們長痛不如短痛,先從要害下手。
九個核心概念貫穿Nestjs開發始終,也只有你深刻理解了這些核心概念,你才能構建出優秀的Nestjs專案,就像早些年Java面試必問JSP中九大內建物件
。
- Controllers
- Providers
- Modules
- Middleware
- Exception Filters
- Pipes
- Guards
- Interceptors
- Custom decorators
Controllers
英文直譯:控制器,控制?控制什麼?
客戶端就像一個懵懂的小男生,看到了喜歡的女孩子就會示好表白,是給你這壞男孩好人卡還是傾心相待,控制權在女孩子手中。客戶端的請求最終交給那個函式或者模組處理都需要通過預先處理,直接處理客戶端請求(路由、方法等)的模組我們稱之為控制器。@Controller
Providers
英文直譯:提供者,提供?提供什麼?
場景一:
我:親愛的,我想吃燒烤。
女友:好冷啊,我不想做。
我:剛好我看到樓下開了一家麼斯烤肉,去嚐嚐吧。
場景二:
我:親愛的,我們房子馬上要裝修了,你做總設計師可以嗎?
老婆:我是UI設計師!不是室內設計,不過我有個朋友公司做設計挺棒,要不?
我:好的,我去學室內設計,然後去你朋友那上班
從以上兩個場景,我們能看出什麼?女朋友不愛我不管要幹嘛,都能找到提供服務的商家。提供者使我們預先定義好的一些服務,為我們後續開發過程服務。@Injectable()
裝飾的類。
Modules
英文直譯:模組,什麼時候模組?
君子由什麼組成?我們可以想到忠孝仁義,這四個特質拆開來個個都是優秀品質,組合在一起就成了受人尊敬的正人君子。Nestjs個個模組、功能、服務等都是優秀個體,裝載到一起便是優秀的服務架構。@Module()
裝飾的類來組織應用結構。
Middleware
英文直譯:中間賤件,誰的中間?
中間,是客戶端和路由處理的中間,我們前面提到路由交給了控制器處理,如果我們想請求在到達控制器之前或者在響應傳送給客戶端之前對request
和response
做一些處理,就可以使用中介軟體,在中介軟體定義的過程中,有一個很重要的函式——next()
,他決定了請求-響應的迴圈系統。提一點,你知道Koa
的洋蔥模型嗎?
一直講中文有點累,我們貼上點express官方給的中介軟體描述
Middleware functions can perform the following tasks:
- execute any code.
- make changes to the request and the response objects.
- end the request-response cycle.
- call the next middleware function in the stack.
- if the current middleware function does not end the request-response cycle, it must call
next()
to pass control to the next middleware function. Otherwise, the request will be left hanging.
Exception filters
英文直譯:異常過濾器,過濾誰?
當你的專案中出現了異常,而程式碼中卻沒有處理,那麼這個異常就會到Nestjs內建的異常處理層,我們通過預定義異常處理過濾器,就能將異常更友好地響應給前端。
Pipes
英文直譯:管道,和水管有區別嗎?
有用過Linux系統的同學,可否知道bash命令中那小小的一個豎線,這個命令有印象嗎?
ls | grep '*.js'
複製程式碼
列舉當前目錄下的檔案及資料夾,然後得到的結果進行過濾,過濾規則為滿足檔案字尾名為js
的檔案。我們通過這個操作,能感受到管道的作用,其作用可以歸納為一下兩點
- 轉換:將輸入的內容轉換為希望得到的結果
- 驗證:驗證輸入的內容是否滿足預先定義的規則,如果驗證通過,則會進入到後續操作;否則將丟擲異常
filter
和 Pipes
使用的階段相似,都是在請求處理之前,但是他們的職責卻有很大差別,各自職責以列舉,詳細的使用場景我們後續介紹。管道是用@Injectable()
裝飾並實現了PipeTransform
介面的類。
Guards
英文直譯:守衛,守衛誰?
我們的房子為什麼需要鑰匙?因為我們不允許外人進入我們的房間。應用中有些請求處理不是對所有前來請求的使用者完全開放的,只有具有指定身份的人才能請求某些介面,負責這一職責的功能模組稱之為守衛。管守衛是用@Injectable()
裝飾並實現了CanActivate
介面的類。提示一點
Guards are executed after each middleware, but before any interceptor or pipe.
Interceptors
英文直譯:攔截器,攔截誰?為什麼要攔截,攔截了做什麼?
一個流水線,如果中間臨時需要加一道工序,隨加隨撤,我們發現這一道工序只是目前臨時新增的,他並不屬於這條流水線上完整環境中的一個步驟,因此這道工序我們可以將它看做外來者,有沒有他不影響我們現有的流水線工作,但加入了它,我們現在流水線製造出的產品更趨於定製化。這道工序我們是切入到現有流水線中來的,這種做法我們稱之為面向切面,當然在程式界,他就是很有名的一個思想 Aspect Oriented Programming
(AOP)思想,即面向切面程式設計,它有一下幾點優勢
- 在現有某個函式執行前/後新增一個額外邏輯
- 轉換一個函式返回的值,這點概念上與
Pipes
相近 - 轉換一個函式執行時丟擲的異常
- 可以繼承某個基礎函式的行為,更優雅的組合功能
- 重寫某個函式
攔截器是用@Injectable()
裝飾並實現了 NestInterceptor
介面的類。
Custom decorators
英文直譯:自定義裝飾器
在此之前,介紹了很多裝飾器,比如:@Injectable()
、@Module()
、@Controller
等,還有請求相關的裝飾器:@Get()
、@Post()
、@Param
等。