小白教小白入門Nodejs——以建立本地靜態資源服務器爲例子(全文1.3萬字)

前言

我是一名剛剛接觸Nodejs有3周左右的新手小白,經歷了迷茫、困頓、挫敗以後終於對Nodejs有了基礎掌握,算是剛剛入門。
我想把我目前所掌握的Nodejs相關知識寫成文章,鞏固本身所學、爲其餘新手小白提供一點點Nodejs入門幫助。javascript

關於個人知識背景,補充幾點:css

  1. 我本來是一名網頁設計師,無任何後臺編程經驗,是最近幾個月才自學的前端(Http5+CSS3+JS),對VUE、Webpack等最新的前端技術棧只是簡單瞭解、並沒有任何實際經驗。
  2. 在我成爲網頁設計師更早以前(大概10年前),我曾經是一名Flash動畫設計與開發人員,10年前的AS3的編程經驗爲我如今學習JS和Nodejs提供了很是大的幫助。由於AS3是面對對象語言,因此我對類、面對對象、設計模式這些並不陌生。

言歸正傳,小白教小白入門Nodejs正式開始...html

免責聲明:本文中的知識點、講解內容僅僅是我我的目前的理解,不敢保證100%都是正確的,僅供參考,同時歡迎批評指正。前端

環境搭建:Nodejs + VSCode + CNPM

1. Nodejs簡介與安裝

Nodejs官方對本身的介紹很是簡單——Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。java

Nodejs與網頁JS的區別node

  1. 網頁中的JS,是運行在瀏覽器環境下的JavaScript,他其實是:ECMAScript標準 + WebAPI(DOM操做+Web事件)
  2. Nodejs是運行在Chrome V8環境下的Javascript,他其實是:ECMAScript標準 + Nodejs API(Chrome V8提供的系統底層操做)

JS和Nodejs雖然都遵循ECMAScript標準(都是Javascript),可是運行環境不一樣,擁有的API不一樣,因此他們功能相差很大。python

網頁JS與Nodejs的區別

相同點:
對於一些基礎類型語法,好比String、Array、Date,ES6新語法等,JS和Nodejs是沒有區別的。git

不一樣點:
好比JS能夠操做網頁元素(好比修改CSS樣式),擁有瀏覽器中的windows對象、擁有鼠標事件等,Nodejs都不具備這些——因此JS是前端。
一樣Nodejs能夠操做系統底層文件,建立服務監聽,而JS都不具備這些——因此Nodejs是後端。github

Nodejs的優點:
相對其餘編程語言,好比Java/.Net/python,這些語言可以作的事情很是很是多,好比開發桌面軟件或APP,Web服務端只是他們衆多應用領域中的其中一種,而Nodejs從誕生到如今惟一用途就是Web服務端。正則表達式

那些語言對於計算能力要求比較高,屬於CPU(或GPU)操做頻繁,也稱「CPU密集」,(好比用Python寫大數據處理、人工智能、區塊鏈等,對於計算量要求比較大),而Web服務對數據計算量少,但對I/O(文件讀寫)操做頻繁,也稱「I/O密集」,恰好正式Nodejs的優點。

Nodejs是I/O異步非阻塞:
能夠答應幹不少活,至於何時幹完不能保證,可是答應過的就必定會去幹,只是早晚而已。
拿比喻來講,異步非阻塞至關於一個飯店裏的店小二,來一位客人就記錄他點的菜,並把所點的菜名傳遞給後廚,接着就能夠接待下一位客戶,至於後廚何時作好店小二不能保證,可是若是後廚把飯菜作好後,店小二可以精準的把飯菜送到對應客人的桌子上。

與之對應的是「I/O阻塞」,好比Apache服務器:
答應一件事,必須作完了才能夠去作另一件事,若是須要處理不少事就會一件件堆積「阻塞」起來。
還拿飯店店小二來比喻,就是來一個客人,這個店小二記錄他點的菜,而後把所點的菜名傳遞給後廚,而後很是耐心等待後廚作菜(這個時候又來了一位顧客,這個店小二也不去理會新客人,依然守在後廚門口耐心等待第一位客人的菜是否作好),時間過去了10分鐘,店小二和第二位顧客沒有任何溝通,第二位客人一臉懵,跟着店小二一塊兒等待。當後廚把第一位客人的飯菜作好,店小二把飯菜送到第一位客戶桌子上,說了一句:對您的服務已完成,我終於能夠去接待第二位顧客了。這時候纔去找第二位顧客,詢問你吃點什麼?

想象一下上面「非阻塞」和「阻塞」對應的飯店場景,在現實生活中哪一個更合理?哪一個飯店能更好生存下去?

若是不能理解異步非阻塞,學Nodejs會很艱難。會被各類狀況下的箭頭函數弄懵,因此上面就多囉嗦了幾句。

聽說,Nodejs性能是Php的80倍。 Php纔是最好的語言。

Nodejs安裝:

軟件下載地址:http://nodejs.cn/download/
根據本身電腦系統選擇對應版本下載,並一路下一步安裝。

VSCode簡介與安裝

VSCode簡介:全稱Visual Studio Code,是微軟推出的一款免費軟件開發IDE。

優秀的IDE有不少,好比HBuilderX、Sublime等,爲何Nodejs開發首選IDE是VSCode?

選擇VSCode的3個理由:
一、TypeScript是微軟開發的(雖然Nodejs入門時還用不到,但未來必定會用到),VSCode也是微軟開發的,毫無疑問VSCode是支持TypeScript最好IDE。
二、VSCode內置DOS操做窗口,調試Nodejs很是方便。
三、VSCode插件擴展衆多,自己仍是免費軟件。

VSCode安裝
軟件下載地址:https://code.visualstudio.com...
根據本身電腦系統選擇對應版本下載,並一路下一步安裝。

CNPM簡介與安裝

NPM是隨同NodeJS一塊兒安裝的包管理工具,除了Nodejs默認自帶的包(類模塊),平常開發會須要大量別人封裝好的包(類模塊),這些每次都須要從國外服務器上下載,爲了快速下載和安裝,可使用淘寶國內的npm鏡像:cnpm。

關於cnpm的具體介紹、安裝方法,使用方法,參見其官網:https://npm.taobao.org/

小結:
至此,已經完成了Nodejs開發環境的安裝,對Nodejs有了一點點初步印象。在正式開始學習Nodejs以前,須要一些計算機網絡通訊基礎知識,如今進入下一章。

背景知識:學習Nodejs前須要瞭解的幾個知識點

如下每個知識點均可以無限展開來說,可是做爲Nodejs入門的知識儲備,這裏只講最基礎的那個點,夠入門用便可。

HTTP傳輸協議

協議規定:任何一條網絡傳輸消息(也稱報文)都必須由:消息頭(字符串形式) + 消息內容主體(二進制數據) 兩部分構成。

補充說明:

  1. 一條消息能夠沒有消息主體,但必須有消息頭。
  2. 消息頭包含:固定名稱的字段(約定好的) + 用戶自定義的字段(能夠有,也能夠沒有)

先後端傳遞數據時,須要寫清楚是以"GET"仍是"POST"方式發送,這裏面的區別是什麼?其實就是告訴對方:

若是是"GET"方式,代表我(發送方)把數據寫在了「消息頭」裏,你(接收方)記得從「消息頭」裏獲取。
數據傳遞表現形式爲:http://www.xx.com/xx?name=puxiao&qq=78657141,這類數據比較簡單,信息量比較小。

若是是"POST"方式,代表我(發送方)把數據寫在了「消息主體」裏,你(接收方)記得從「消息主體」裏獲取。
數據不會在網址中出現,傳遞數據內容較大,好比上傳一張圖片或獲取一個網頁。

雖然本篇入門爲「靜態資源服務器」,不牽扯「動態數據交互」,可是瞭解上面知識點很是重要。

關於瀏覽器緩存

瀏覽器與服務器約定好的緩存依據,一共有4種方式:強制緩存(2種) + 協商緩存(2種)

強制緩存的2種方式:

一、Expires (到期時間,字符串形式(GMT或UTC形式))

服務端返回信息頭對應爲:res.setHeader['Expires',(new Date(Date.now() + 3600)).toGMTString()];//將當前服務器時間+3600毫秒,產生新的日期時間,並將該時間轉換爲GMT字符串形式

缺點:若客戶電腦時間不正確,或不一樣時區,不能保證必定和服務器時間匹配,可結合Cache-Control使用。

二、Cache-Control (有效期爲多少秒)

服務端頭返回信息頭對應爲:res.setHeader['Cache-Control','max-age=60'];//告訴瀏覽器60秒內不用詢問我,可直接使用本地緩存

補充說明:
將秒數設置比較小,可進行數據緩存策略,好比某一塊數據10秒內就使用本地緩存。
將描述設置比較大(好比N天),可進行靜態文件緩存策略,好比某圖片或css文件N天以內均可使用本地緩存。

協商緩存的2種方式:

一、Modified (修改時間,字符串形式(GMT或UTC形式)):服務端Last-Modified/客戶端If-Modified-Since

服務端獲取某文件的修改時間代碼爲:stats.mtime.toGMTString();
將服務器獲取文件的修改時間與客戶端文件修改時間進行對比,若相同則返回304,若不相同則發送新的文件給客戶端

特別提醒:在req.headers中,默認將瀏覽器消息頭中的大寫改成了小寫,因此正確獲取應該是res.headers['if-modified-since']。

二、Etag (電子戳):服務端Etage/客戶端If-None-Match

1.能夠簡單採用 文件大小 + 文件修時間,將獲得字符串值約定爲電子戳(可針對此值進行md5換算以便更加精準)
2.將服務器獲得文件電子戳與客戶端文件電子戳進行對比,若相同則返回304,若不相同則發送新的文件給客戶端

補充說明:

  1. 強制緩存不須要向服務器發送請求,瀏覽器本身默默從本地緩存中讀取,文件頭信息爲304
  2. 協商緩存須要向服務器發送請求,服務器根據判斷來決定是否能夠返回304
  3. 若當前地址爲整個頁面入口,則不響應上述緩存機制,上述緩存機制只針頁面入口中引用的文件或F5刷新模式(非地址欄裏敲回車進行的訪問)。
  4. 理論上直接地址欄敲地址摁回車訪問某個文件是不會產生緩存的。但平時直接訪問某個文件依然爲緩存是由於DNS的緩存而不是服務器的緩存。
  5. 若瀏覽器請求頭中Cache-Control: no-cache,此時請求信息頭中不會包含其餘3中緩存頭信息,所以服務器匹配任何緩存信息頭都會失敗,則會發送最新文件給客戶端(返回時依然包含緩存信息頭,客戶端可進行緩存)
  6. 若瀏覽器請求頭中Cache-Control: no-store,此時客戶端和服務器都不會進行緩存相關操做。

常見網頁信息狀態碼(響應碼)

  • 200 新的、正常的、成功的狀態碼
  • 304 緩存的狀態碼(僅有消息頭,不含消息主體)
  • 404 請求失敗,請求所但願獲得的資源未被在服務器上發現

更多狀態碼可查看:https://developer.mozilla.org...

Nodejs經常使用到的DOS命令

  • 盤符+: 進入某硬盤分區,例如進入F盤爲 f:
  • cd xxx 進入 xxx文件夾
  • cd .. 返回上一級文件夾
  • mkdir+名稱 新建文件夾
  • cls 清除已有文字信息(清屏)
  • code . 啓動VSCode並打開當前文件夾
  • Ctr+C 結束當前執行中的命令(或輸入exit)

正則表達式、箭頭函數、ES6新語法

正則表達式、箭頭函數、ES6新語法都屬於JS的基礎知識,若是你不熟悉,建議先百度瞭解。

全棧名詞解釋

在學習Nodejs以前,確定見過聽過各類全棧名詞,雖然Nodejs入門還都用不到這些框架和技術,可是先了解一下他們是作什麼的,作到心中有數,當看到別人說這些名詞時,不慌不亂

  • Vue、React、Angular:用來作前端數據頁面渲染(與之對應的是後端模板引擎SSR)
  • Koa、Express、Nest、Egg:基於Nodejs二次開發的服務框架
  • MySQL、MongoDB:數據庫
  • Typescript:微軟推出的,針對JS語言的一種「包裝」,甚至能夠理解爲「語法糖」,讓JS以面對對象方式進行編程
  • Webpack:一種代碼資源打包工具,減少代碼和圖片數量與體積
  • Eslint:一種代碼約定格式協議,方便整個項目開發人員以相同的風格來進行編寫,控制代碼可讀性、約束部分代碼可執行性
  • Sass、Less:針對CSS樣式的一種擴展處理方式
  • SSR:服務端渲染,服務端根據後臺數據,經過模板引擎,組織生成一個網頁文件返回給前臺(常見的模板引擎有Handlebars、騰訊技術牛人寫的art-template等)

進程線程名詞解釋:進程、線程、單線程、多線程、多核CPU

如下關於計算機的進程、線程名詞解釋、CPU任務分配原則,若不感興趣或理解不了(由於我也僅僅是有一個很大概、粗略的認識,若是說錯了敬請見諒 ),能夠跳過。

進程:假如電腦上目前運行的程序有Photoshop、QQ、Nodejs,每個程序都對應一個進程,一個CPU會給每個進程分配必定的內存。
線程:一個進程中能夠有多個線程,全部這些線程共享這個進程中的資源(內存、計算能力),若是其中一個線程發生錯誤則會影像整個進程。

單線程:一個進程中只有一個線程(如Nodejs)

缺點:一瞬間只能作一件事
優勢:進程中就本身一個線程,精力更加集中(徹底擁有本身所屬的進程擁有的所有內存資源調度)

單進程多線程:一個進程中可建立多個線程(如Apache)

優勢:能夠經過創造多個線程,一瞬間能夠同時作多件事情
缺點:CPU分配給本進程的資源是固定的,因此可以建立線程的數量是有限的,而且由於每一個線程共享一個進程,因此如有一個線程出問題卡住了,會影響其餘線程,進而影響整個進程。

Nodejs自己爲單進程單線程」,聽上去沒有多線程強大,可是Nodejs說本身是單線程,真的是這樣嗎?
還記得開頭是怎麼介紹Nodejs的嗎?「Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。」

沒錯,Nodejs背後靠山是Chrome V8,而這個V8在調用系統底層進行I/O操做時是多線程的,進而能夠約等於說Nodejs是"多線程"的。(背靠V8好乘涼)。

等一等!以上關於進程、線程、內存資源分配都是在電腦單核CPU的前提下,那若是電腦是多核CPU,那是又是什麼狀況呢?

多核CPU處理進程,任務分配原則:

假如電腦(服務器也是電腦)是4核處理器:A核、B核、C核、D核,那麼平時電腦是怎麼處理分配資源給不一樣進程呢?
好比電腦上恰好運行了4個程序(進程):PS、QQ、迅雷、Nodejs。
電腦怎麼安排任務?會不會是讓A核來處理PS,B核來處理QQ,C核來處理迅雷,D核來處理Nodejs?

答案是不會!
現實的狀況很殘酷(能者多勞原則),爲了整體性能,電腦的任務安排是:
A核你來處理PS、你來處理QQ,你來處理迅雷,你來處理Nodejs。
B核、C核、D核大家都歇着,何時A覈實在忙不過來了,B核你再上!
固然上面論述只是作了適當誇張,實際中還會加入別的平衡策略。

默認Nodejs是單進程,即便電腦上是多核CPU,也只能使用其中一個CPU而已。
可是能夠經過Nodejs自帶的類模塊:cluster(集羣)來實現多進程(實際上是子進程,每一個子進程裏依然是一個單線程),幾核CPU能夠分裂出幾個子進程,充分利用好多核CPU的性能。

基礎概念:Nodejs開發的基本知識

NPM簡介與操做

在Nodejs開發過程當中,咱們須要不斷引用別人編寫好的代碼包。

  • 這些代碼包都是全球Nodejs開發者經過NPM官網https://www.npmjs.com,加入到(貢獻給)npm公共代碼資源庫裏的。
  • 其中A開發者編寫的代碼裏可能引用了B開發者(其餘開發者)的代碼包,而B開發者的代碼裏有引用了C開發者的代碼包。當你的項目須要使用A開發者的代碼包時,理論上你還須要引入B代碼包、C代碼包,這樣會很是麻煩。爲了簡化你的代碼引用這部分工做,因而有了「npm」這個代碼包管理器。

關於NPM更多中文介紹,能夠訪問:https://www.npmjs.cn

再次強調一下,npm代碼包都存放在國外服務器上,咱們爲了方便最好使用淘寶的npm國內鏡像服務,即cnpm

NPM引入(安裝)第三方代碼包的幾個知識點

  • npm 可替換爲 cnpm
  • install 可簡寫爲 i
  • -g 表示全局安裝(其餘任何項目均可使用)
  • --save 本項目需使用(代碼包會自動下載到你項目的node_modules文件夾中)
  • --save-dev 僅供本項目本地使用(請注意是「本地使用」,若是別人經過「npm install --production」也想建立一份你的項目,他建立的時候是不包含 --save-dev 引用的代碼包的)

其中--save和--save-dev的區別略微有一點繞,若是不明白能夠百度或者暫時先放一下,不影響本文後續編程。

本篇入門文章講的「建立靜態資源服務器」所用到的代碼模塊,都是Nodejs內置的(由於這些模塊太基礎、使用太頻繁,因此Nodejs內置了這些模塊),只須要引入2個別人的代碼包。

第1個:@types/node
默認在VSCode裏建立的項目只有網頁JS代碼提示,缺乏Nodejs的代碼提示(沒有代碼提示不表明不能正常運行),因此在本次代碼示例中,咱們須要引入一個叫「@types/node」的代碼包。

關於@types/node,可訪問官方地址(英文):https://www.npmjs.com/package...

官方提供的安裝示例:
npm install --save @types/node

1. install 可簡寫爲 i,即 npm i --save @types/node
2. npm 可替換爲 cnpm,即:cnpm i --save @types/node

有些時候,若是使用cnpm安裝不成功(極少狀況),只能用npm,爲了下載代碼包快一些,咱們能夠經過新增一個參數,繼續使用淘寶國內鏡像文件。
上述安裝代碼可修改成:

npm i --save @types/node --registry=https://registry.npm.taobao.org

第2個:art-template(模板引擎)
當返回某個目錄內的資源列表式,經過這個模板引擎生成對應頁面。
Nodejs模板引擎有很是多種,常見的有:handlebars、jade、ejs、art-template
本次咱們選擇使用art-template,詳細使用方法請訪問:https://aui.github.io/art-tem...

Commonjs模塊化概念解釋

擁有面對對象編程經驗的人都知道,一個複雜的項目必定須要被拆分紅多個小模塊,每一個小模塊又會繼續往下劃分不一樣的類,每個類擁有本身的屬性、方法。

目前不管網頁JS仍是Nodejs,都不是傳統的面對對象語言(儘管ES6之後已經很是進步了、Typescript就是爲了彌補這個缺憾而誕生的,Typescript模擬出了相似面對對象的編程寫法,但僅僅是模擬並非原生),沒法提供標準意義上的「類」。

因而有了Commonjs模塊化這個概念(本文一直稱呼這種代碼形式爲類模塊或代碼模塊),詳細介紹能夠參考:http://javascript.ruanyifeng....

類模塊實現方法是經過內置的module類的exports屬性,來對外聲明(提供)本身內部屬性和方法的調用。
這裏的某個類模塊其實就是一個編寫好的.js文件。
調用方則經過 const xx = require('./xxx.js') 來將xxx.js模塊引入到本身內部(其餘面對對象語言通常都採用import xxx的形式引入)。

  • ./ 表示同一目錄(引入本身寫的類模塊必須使用./或者../)
  • 若是不寫./則表示引入的類來自內置類
  • 想引入的xxx.js中的後綴.js能夠省略掉不寫
  • 一般引入寫法爲:const xx = require('./xxx') 便可。

如下爲我的對Commonjs模塊化的一個理解:

仍是以其餘面對對象語言(好比jave、AS3)來和Commonjs模塊化作對比。

其餘面對對象語言的屬性和類,在聲明以前都會有訪問修飾符,好比public(公開)、private(私有)、protect(僅子類可見),static(歸屬於類的,而非實例的)。

Commonjs模塊化的exports表現出來的,特別像其餘語言中的「public static」這個概念。
被引入的類模塊(代碼模塊),「不須要實例化(也沒辦法實例化)」,使用起來相似「面對對象中類的公開靜態屬性或方法」。

以上僅爲我我的理解,當我把module.exports理解爲 public static 後,我對於Commonjs模塊化一會兒清晰了不少。

本項目使用的Nodejs類模塊

想學任何一門編程語言,最應該先看、多看、反覆看的就是他們的官方幫助文檔,Nodejs中文文檔請訪問:http://nodejs.cn/api/

內置代碼模塊太多,做爲剛開始入門,沒有必要和精力所有看完。
本文講的建立靜態資源服務器,只須要看如下幾個點便可:

http(建立http server服務)http://nodejs.cn/api/http.html
僅看http類模塊整體介紹和http.createServer方法便可

path(資源路徑相關)http://nodejs.cn/api/path.html
全看

fs(文件系統)http://nodejs.cn/api/fs.html
fs整體介紹、fs.stat方法、fs.Stats類、fs.readdir方法(讀取某個文件夾的內容)、fs.createReadStream(以流的方式讀取某個文件)
這裏讀取文件咱們不使用fs.readFile方法,由於該方法只有把文件所有讀取完成後纔會觸發後續事件,不像createReadStream方法,以流的形式讀取(讀取一點就輸出一點)。

module(內置模塊,即Commonjs模塊化)http://nodejs.cn/api/modules....
僅看module.exports便可

process(內置進程類模塊)http://nodejs.cn/api/process....
僅看process.cwd()便可。

zlib(壓縮)http://nodejs.cn/api/zlib.html
僅看zlib整體介紹、zlib.gzip方法和zlib.createGzip方法、
通常網頁有3中壓縮方式:gzip、deflate、br,這3種壓縮方式在zlib中的使用方法相似,只是類的名字不同而已。
這3個用法相似:zlib.gzip、zlib.deflate、zlib.brotliCompress(注意不是zlib.br)
這3個用法相似:zlib.createGzip、zlib.createDeflate、zlib.createBrotliCompress(注意不是zlib.createBr)

Nodejs目前一共有41個內置類模塊,而上面已列出的有6個模塊,耐心看完,後續代碼照着再反覆敲幾遍,真的能夠達到Nodejs入門的標準了

---前面鋪墊了那麼多,終於該進入項目正式內容了---

需求分析:靜態資源服務器項目

需求概述

本次開發的項目名稱爲「建立本地靜態資源服務器」,咱們分析一下這個Nodejs項目須要知足的業務內容。

從用戶的角度講,他的操做流程是

1. 在瀏覽器地址欄中輸入本地請求地址,如http://127.0.0.1:8899 摁回車
2. 網頁顯示出根目錄下的靜態資源內容:各類文件(如.html、.jpg、.js等)和文件夾
3. 若點擊某個文件,則經過網頁打開此文件
4. 若點擊某個文件夾,則顯示該文件夾內的資源:各類文件(如.html、.jpg、.js等)和文件夾

須要考慮的意外狀況有:

  1. 用戶直接在地址欄中,輸入請求某個具體的文件或文件夾資源地址,而這個文件或文件夾並不存在,例如:http://127.0.0.1:8899/puxiao或http://127.0.0.1:8899/puxiao/index.html
  2. 用戶在請求某資源時,給該資源地址上增長某些參數,而咱們這次爲靜態資源服務器,如何應對?例如:https://127.0.0.1:8899/logo.png?v=1

從後臺的角度講,他的業務流程是

1. 建立一個本地http服務,靜靜開始等待用戶訪問併爲其提供服務
2. 偵聽到用戶的http請求,分析url地址獲取到請求資源地址,並將該地址轉化爲本地資源地址
3. 嘗試獲取該資源信息
4. 若發現本地不存在該資源,向用戶發送404,告知用戶該資源不存在
5. 若發現本地該資源存在,則判斷該資源是文件仍是文件夾
6. 如果文件,則將該文件內容發送給用戶
7. 如果文件夾,則將該文件夾內資源信息,整理髮送給用戶

須要額外考慮的幾點:

  1. 如果文件,考慮是否告知用戶使用本地緩存,仍是真實發送該文件給用戶
  2. 如果文件,考慮是不是受支持、可訪問的文件格式,是否應該將本文件發送給客戶(好比服務器設定不容許用戶訪問.mp4資源,那麼即便服務器上有該資源,依然告知用戶該資源不存在)
  3. 如果文件,考慮是否能夠對該文件進行壓縮,減少傳輸體積
  4. 如果文件夾,如何把文件夾內的文件列表信息生成對應的網頁數據,以及如何壓縮該網頁數據

業務執行流程梳理

根據上述的需求分析,能夠大致梳理出後端業務執行流程,以下圖:
靜態資源服務器業務執行流程.jpg

注意,當你訪問任意某個資源時,瀏覽器會額外多一條針對站標favicon.ico文件的請求,咱們忽略這個便可。

核心代碼:類模塊劃分和實現

項目初始化

以windows系統爲例,假設咱們要將本項目全部源代碼存放在F:\node\hello中。

項目初始化的操做步驟是

  1. 左下角系統 開始 -> cmd.exe -> 進入DOS命令窗口
  2. 經過DOS命令進入到F:\node\hello 目錄中(可使用mkdir命令新建對應文件夾,或者直接在電腦經過右鍵新建對應文件夾)
  3. (DOS命令可參考本文中的「背景知識:學習Nodejs前須要瞭解的幾個知識點 -> Nodejs經常使用到的DOS命令」)
  4. 執行初始化:npm init,以後會進行一系列設置詢問,並最終初始化完成。若不理解這一步,能夠百度「npm init」,有大量相關介紹文章。
  5. 若想跳過中間的各類詢問,可將初始化代碼換成:npm init -y (使用默認值)

此致項目Nodejs初始化第一階段完成,下一步開始第二階段:引入咱們須要使用的2個第三方類模塊

  1. 引入@types/node:cnpm i --save @types/node 儘管引用的是淘寶國內代碼庫鏡像,可是依然須要幾秒鐘的下載時間,請等待
  2. 引入art-template:cnpm i --save art-template 安裝完成後,至此項目初始化完成
  3. 執行:code . 讓VSCode打開本目錄(或者直接打開VSCode,選擇打開項目文件夾)。

VSCode調試配置

項目初始化後,緊接着要進行VSCode調試配置,操做步驟及流程,以下圖所示:

VSCode調試配置.jpg

調試配置設置

  1. 默認項目啓動文件爲index.js。能夠根據本身喜愛修改,好比改成app.js。
  2. 默認調試每次都啓動默認js,也能夠新增本身的調試方式,好比修改launch.json,將configurations的值(默認數組裏就只有一種調試模式),複製新增一份,並將其中的name值修改成"當前文件"、program值修改成"${file}",該模式下能夠啓動當前js文檔,方便調試使用。

VSCode_調試設置.jpg

至此,終於能夠開始編寫代碼了。

類模塊劃分及具體實現

這裏直接列出項目結構

Nodejs建立靜態服務器源碼項目結構.jpg

項目結構說明
./config/config.js 用來存放一些基礎配置常量,好比要建立服務的端口889九、哪些格式的文件須要被壓縮等
./config/mimetype.js 用來存放服務器支持的文件格式以及該文件格式對應消息頭部中的Content-Type
./view/404.html 定義好的404頁面
./view/dir.html 定義好的目錄頁面模板
./cache.js 用來處理緩存相關的類模塊
./compress.js 用來處理壓縮相關的類模塊
./index.js 項目啓動js,用來建立http服務,並根據用戶url請求得到對應資源在服務器的絕對路徑
./route.js 整個項目核心類模塊,根據請求資源路徑進行一系列後續操做

不少服務端框架都有「路由」這個概念,這裏的route.js的做用就是將資源請求進行下一步分配(判斷)並進行迴應。

這裏就不針對每一個js類模塊展開來說了,你能夠直接下載個人項目源碼進行分析。

項目源文件下載地址https://pan.baidu.com/s/1Chbg... 密碼:g4yy

在VSCode中進行調試,正常運行結果以下:

項目調試運行結果.jpg

爲啥不展開來說?每一個類模塊具體都是什麼代碼,具體實現了哪些功能不該該是本篇文章的核心嗎?
我是這樣認爲的

  1. 我相信讀這篇文章的人,是擁有必定網頁JS源碼編寫能力的。
  2. 不一樣類模塊裏須要使用到的Nodejs方法和屬性,我已經在本文上面部分中「Commonjs模塊化概念解釋、本項目使用的Nodejs類模塊」中作了充分介紹。
  3. 遇到不懂的Nodejs屬性和方法,可查閱官方幫助文檔,那裏有充分詳細的介紹,我就不必再複述一遍。
  4. 我代碼裏用的都是最基礎的JS語法,整個代碼業務推動的方式和本文上面「業務執行流程梳理」徹底一致。
  5. 在返回給用戶的數據中,關於如何設置狀態碼(200/304/404)、如何設置緩存,如何壓縮等,均已經在本文上面部分中作了充分講述。

我但願你必定先把官方幫助文檔看明白、而後再看我提供的源碼、而後再本身從頭寫一遍。
這樣你才能真正入門,才能真正領悟到Nodejs的開發編寫思路

若你真的真的基礎太差,理解不了,可私信給我。

項目總結

  1. Nodejs的入門核心點在於新的知識儲備(好比DOS命令)、Nodejs運行原理、網絡通訊協議、設計模式等,不在於某個Nodejs的具體語法使用。
  2. 這些語法具體去編寫代碼時,和寫前臺JS沒有太大的差異,只不過這些新的函數是Nodejs API提供的而已。
  3. 前端JS不須要考慮性能(CPU和內存)、然後端性能、安全才是第一。必定要在思惟方式上進行一個切換。
  4. 本文中的「Nodejs簡介與安裝」、「背景知識:學習Nodejs前須要瞭解的幾個知識點」、「基礎概念:Nodejs開發的基本知識」纔是整個Nodejs入門核心,至於項目中的源碼,那只是一些基礎語法的組合而已。

Nodejs思想,網絡通訊知識才是最難理解和須要學習的那部分,再次強調一下,那些具體的代碼僅僅是一個表象而已

後語

但願你養成一個好的學習、解決問題的方法:看官方文檔、在思否/掘金上搜索或提問、或百度一下。

小白教小白Nodejs入門是我花了2天時間寫出來的第一篇Nodejs技術分享文章,感謝你的閱讀

明天就是2020年1月1日,咱們一塊兒加油!

相關文章
相關標籤/搜索