Express/Node introduction - 學習該如何開發Web | MDN

文章推薦指數: 80 %
投票人數:10人

Node (或者說Node.js) 是一個開源、跨平台和允許開發者使用Javascript創造伺服器端工具和應用 ... 此教學不會告訴建議的檔案名稱或如何執行該檔案;-). SkiptomaincontentSkiptosearchSkiptoselectlanguage學習該如何開發Web伺服端網站程式設計Expresswebframework(Node.js/JavaScript)Express/NodeintroductionArticleActions正體中文(繁體)ThispagewastranslatedfromEnglishbythecommunity.LearnmoreandjointheMDNWebDocscommunity.什麼是Express和Node?歷史Node/Express有多流行?IsExpressopinionated?Express的程式碼長怎樣?總結SeealsoInthismoduleRelatedTopics 全新手請從這開始! Web入門 Web概述 安裝基本軟體 自己的網站會是什麼樣子? 處理檔案 HTML基礎概念 CSS基礎概念 JavaScript基礎概念 發佈自己的網站 Web運作的方式 HTML—架構Web HTML介紹 HTML概述 HTML入門 標題裡是什麼?HTML中的後設資料(Metadata) HTML文字基礎概念 建立超連結 進階文字格式 文件與網站架構 HTML除錯 親和度:設個字母 親和度:架構出具備內容的網頁 多媒體與嵌入 多媒體與嵌入的概述 HTML中的圖片 視訊與音訊內容 從物件到iframe—其他嵌入技巧 為Web新增向量圖 適應性圖片 親和度:Mozilla形象頁面 HTML表格 HTML表格概述 HTML表格基礎 HTMLtableadvancedfeaturesandaccessibility Assessment:Structuringplanetdata CSS—設計Web的風格 初探CSS 初探CSS(概述) CSS是什麼? CSS入門 HowCSSisstructured CSS怎麼運作 Assessment:Stylingabiographypage CSS組件 CSSbuildingblocksoverview Cascadeandinheritance CSSselectors Theboxmodel Backgroundsandborders Handlingdifferenttextdirections Overflowingcontent CSSvaluesandunits SizingitemsinCSS Images,media,andformelements Stylingtables DebuggingCSS OrganizingyourCSS Assessment:FundamentalCSScomprehension Assessment:Creatingfancyletterheadedpaper Assessment:Acool-lookingbox 樣式化文字 樣式化文字概述 基礎的文字與字型樣式化 樣式化列表 樣式化連結 Web字型 親合度:設定社區大學首頁的版面 CSS版面配置 CSS版面配置概述 IntroductiontoCSSlayout NormalFlow 彈性區塊 格線 浮動 定位 Multiple-columnlayout Responsivedesign Beginner'sguidetomediaqueries Legacylayoutmethods Supportingolderbrowsers Assessment:Fundamentallayoutcomprehension JavaScript—動態的用戶端指令 JavaScript第一步 JavaScript第一步概述 什麼是JavaScript? 初次接觸JavaScript 出了什麼問題?JavaScript疑難排解 儲存你所需的資訊—變數 JavaScript基礎概念—數字與運算子 處理文字—JavaScript中的字串 有用的字串函式 陣列 親合度:傻瓜故事產生器 JavaScript基礎要件 JavaScript基礎要件概述 於程式碼中決策—條件 程式碼迴圈 函式—可重複使用的程式碼區塊 建立自己的函式 函式回傳值 事件介紹 親合度:圖庫 JavaScript物件介紹 JavaScript物件概述 物件基礎概念 物件原型 Object-orientedprogrammingconcepts ClassesinJavaScript 使用JSON資料 物件建構實作 親合度:為彈跳球展示新增功能 非同步的JavaScript AsynchronousJavaScriptoverview IntroducingasynchronousJavaScript Howtousepromises Implementingapromise-basedAPI Introducingworkers Assessment:sequencinganimations 客戶端webAPIs 客戶端webAPIs IntroductiontowebAPIs 文件操作 Fetchingdatafromtheserver ThirdpartyAPIs Drawinggraphics VideoandaudioAPIs Client-sidestorage 網頁表單-與使用者資料合作 核心的表單學習途徑 網頁表單概述 Yourfirstform 如何建構網頁表單 Basicnativeformcontrols TheHTML5inputtypes Otherformcontrols Stylingwebforms Advancedformstyling UIpseudo-classes Client-sideformvalidation Sendingformdata 深入網頁表單 Howtobuildcustomformcontrols SendingformsthroughJavaScript CSSpropertycompatibilitytableforformcontrols 無障礙網頁—每個人都可以使用的網頁 無障礙網頁指南 無障礙網頁概述 何謂無障礙網頁? HTML:Agoodbasisforaccessibility CSSandJavaScriptaccessibilitybestpractices WAI-ARIA基礎 Accessiblemultimedia 行動裝置上的無障礙 無障礙網頁評估 Assessment:Accessibilitytroubleshooting MathML—WritingmathematicswithMathML MathMLfirststeps MathMLfirststepsoverview GettingstartedwithMathML Assessment:Threefamousmathematicalformulas 工具與測試 Client-sidewebdevelopmenttools Client-sidewebdevelopmenttoolsindex Client-sidetoolingoverview Commandlinecrashcourse Packagemanagementbasics Introducingacompletetoolchain Deployingourapp 介紹前端框架 前端框架簡介 Frameworkmainfeatures React GettingstartedwithReact BeginningourReacttodolist ComponentizingourReactapp Reactinteractivity:Eventsandstate Reactinteractivity:Editing,filtering,conditionalrendering AccessibilityinReact Reactresources Ember GettingstartedwithEmber Emberappstructureandcomponentization Emberinteractivity:Events,classesandstate EmberInteractivity:Footerfunctionality,conditionalrendering RoutinginEmber Emberresourcesandtroubleshooting Vue 開始學Vue CreatingourfirstVuecomponent RenderingalistofVuecomponents Addinganewtodoform:Vueevents,methods,andmodels StylingVuecomponentswithCSS UsingVuecomputedproperties Vueconditionalrendering:editingexistingtodos FocusmanagementwithVuerefs Vueresources Svelte Svelte入門 StartingourSvelteTodolistapp DynamicbehaviorinSvelte:workingwithvariablesandprops ComponentizingourSvelteapp AdvancedSvelte:Reactivity,lifecycle,accessibility WorkingwithSveltestores TypeScriptsupportinSvelte Deploymentandnextsteps Angular Angular新手入門 開始開發我們的Angular待辦事項應用程式 使用樣式點綴我們的Angular應用程式 建立一個item元件 篩選我們的待辦事項項目 建構Angular應用程式與更多資源 GitandGitHub GitandGitHub概述 HelloWorld GitHandbook ForkingProjects Aboutpullrequests MasteringIssues 跨瀏覽器測試 跨瀏覽器測試概述 跨瀏覽器測試介紹 測試執行策略 處理常見的HTML與CSS問題 處理常見的JavaScript問題 處理常見的親合度問題 建置功能偵測 自動化測試介紹 設定自己的自動化測試環境 伺服端網站程式設計 第一步 第一步概述 伺服端介紹 用戶端概述 伺服端網路框架 網站安全 Django網站框架(Python) Django網站框架(Python)概述 介紹 設定開發環境 線上教學:本地圖書館網站 線上教學2:建立網站骨架 線上教學3:使用模型 線上教學4:Django管理網站 線上教學5:建立我們的首頁 線上教學6:泛型清單與細節檢視 線上教學7:會話(Sessions)框架 線上教學8:使用者授權與許可 線上教學9:搭配表單 線上教學10:測試Django的WebApp 線上教學11:佈署Django至產品 WebApp安全性 親合度:DIY迷你部落格 Express網站框架(node.js/JavaScript) Express網站框架(Node.js/JavaScript)概述 Express/Node介紹 設定Node(Express)的開發環境 Express教學1:本地圖書館網站 Express教學2:建立骨架網站 Express教學3:使用資料庫(Mongoose) Express教學4:路由與控制器 Express教程5:呈現圖書館的資料 Express教學6:使用表單 Express教學7:佈署到正式環境 更多資源 常見問題 HTML問題 CSS問題 JavaScriptquestions Web的運作方式 工具與設定 設計與親合度 什麼是Express和Node?歷史Node/Express有多流行?IsExpressopinionated?Express的程式碼長怎樣?總結SeealsoInthismoduleExpress/Nodeintroduction Overview:ExpressNodejs 次頁 在這篇文章中回答了「什麼是Node?」和「什麼是Express」,同時概述是什麼讓Express框架如此特別。

本文將概述主要特性、展示一些Express應用的主要建構模塊(雖然此時你還沒有能測試它的開發環境) 前置需求: 基本的電腦知識。

對伺服器端網站程式設計的基本了解,特別是網站中客戶端-伺服器交互的機制(en-US)。

目標: 提升對Express的了解、如何與Node搭配使用、提供的功能和Express應用的主要建構模塊。

什麼是Express和Node?Node(或者說Node.js)是一個開源、跨平台和允許開發者使用Javascript創造伺服器端工具和應用的執行環境。

運行的目的是為了能在瀏覽器外使用,例如:直接執行在電腦或伺服器上。

所以該環境捨棄了瀏覽器限定的JavaScriptAPIs並增加更多傳統OSAPIs的支援,例如:HTTP和檔案系統的程式庫。

從網站伺服器開發的觀點來看Node有幾項優點: 高效能!Node旨在提升生產率和網頁應用的可擴充性。

而且它非常適合網站開發常見的問題,例如:即時網站應用 使用舊版本的JavaScript進行程式編寫,這表示不用多花力氣在轉換瀏覽器和伺服器上的程式碼 與其他傳統的Web伺服器語言(例如Python,PHP等)相比,JavaScript是一種相對新的程式語言,它受益於語言設計的改進。

許多其他新的和流行的語言都可以編譯/轉換成JavaScript,因此你還可以使用CoffeeScript,ClojureScript,Scala,LiveScript等 NodePackageManager(NPM)提供數十萬個第三方套件,是最佳的依賴解決方案也可以用來自動化大部分構建工具鏈。

它是可移植的,能夠在Windows,OSx,Linux,Solaris,FreeBSD,OpenBSD,WebOS和NonStopOS上執行。

許多web主機提供方也支援使用Node,通常會提供特定的基礎設施和文件 擁有非常活耀的第三方生態系統和開發者社群,許多人樂意提供幫助 你可以只用Node的HTTP模組創造一個簡單的web伺服器來回應任何請求,如下所示。

此教學不會告訴建議的檔案名稱或如何執行該檔案;-) 這將創造一個伺服器並會監聽http://127.0.0.1:8000/上任何種類的HTTP請求,當接收到任何請求時回傳一個「HelloWorld」的純文字回應。

//載入HTTP模組 varhttp=require("http"); //創建HTTP伺服器並監聽8000port http.createServer(function(request,response){ //SettheresponseHTTPheaderwithHTTPstatusandContenttype response.writeHead(200,{'Content-Type':'text/plain'}); //Sendtheresponsebody"HelloWorld" response.end('HelloWorld\n'); }).listen(8000); //PrintURLforaccessingserver console.log('Serverrunningathttp://127.0.0.1:8000/'); Node並不原生支持其他常見的web開發任務,如果你想為不同的HTTP方法(例如:GET,POST,DELETE等)增加特定的處理、替不同的URL路徑提供靜態檔案、使用樣板或動態性的產生response,你需要自己完成相關的程式或者是避免重新造輪子-使用web框架! Express是最受歡迎的Nodeweb框架,還是其他許多流行的Nodeweb框架的底層庫,它提供: 替不同HTTPMethod、不同URL路徑的requests編寫不同的處理方法 透過整合「畫面」的渲染引擎來達到插入資料到樣板中產生response 設定常見的web應用設定,例如:連線用的port和產生response的樣板位置 在request的處理流程中增加額外的「中間層」進行處理 雖然Express本身非常簡單,但開發者們已經創造相容的中間層套件來解決大部份web開發的問題,這些套件能處理cookies,sessions,登入,URL參數,POST資料,安全標頭等等,你能在ExpressMiddleware中找到這些套件的列表(以及其他流行的第三方套件) 備註:這種靈活性是一把雙刃劍。

有一些中間層套件能解決大部份的問題或需求,但使用正確的套件有時會是一個問題。

也沒有「正確的方法」來創建應用,你在網路上找到的範例也並非都是最佳解或是只有開發上所需要做的一小部份。

歷史2009年Node在Linux平台上初次發佈.2010年NPM套件管利器發佈,2012年增加Windows的原生支援.現在的LTS版本為Nodev8.11.2,最新版本為Nodev10.1.0。

這只是它深厚歷史的一小片斷,欲知更多詳情請洽Wikipedia。

2010年11月Express初次發佈,現在的API版本為4.16。

你可以查閱更新紀錄來了解此版本做了甚麼更改或是從GitHub中了解詳細的歷史紀錄。

Node/Express有多流行?對於web框架而言流行度很重要,這代表他會不會被繼續更新、文件、附加套件和技術支援方面有多少資源 現在沒有一個明確的指標來評斷伺服器端框架的流行度,雖然有HotFrameworks透過計算GitHub的專案數量和StackOverflow的問題來衡量流行度。

更好的問題是,Node和Express是否「夠流行」以避免成為不流行的平台。

有沒有持續進步?需要時是否能得到幫助?能不能找到Express相關的工作? 從眾多使用Express的公司、貢獻程式碼的人數和那些提供免費/收費支援的人員來看,是的!Express是一個流行的框架。

IsExpressopinionated?Web框架通常自稱為"opinionated"或"unopinionated". Opinionated指的是那些有「正確」方法解決特定問題的框架。

在特定的需求上他們通常能快速開發,因為正確的方法通常易懂且有良好的文件,然而在面對其他問題時則會失去靈活性。

這類型的框架通常傾向於提供較少的選擇和套件來解決問題。

反過來說Unopinionated框架,對於如何組合套件來解決問題尚有較少的限制,開發者可以更輕易的使用適當的套件來解決特定問題,儘管代價是你需要自己找到適合的套件。

Express是Unopinionated框架,你可以在request處理流程中使用任何相容套件,使用單一或複數個檔案來建構應用,有時候甚至會覺得擁有太多選擇了。

Express的程式碼長怎樣?傳統的資料驅動網站中,web應用程式會等待來自瀏覽器(或其他客戶端)的HTTPRequest,接收到Request後根據URL和可能夾帶的POST/GET資料來決定需要回應什麼動作,根據需要可能對資料庫進行讀寫或執行滿足Request所需的其他任務。

web應用程式會回應Response給瀏覽器,通常是藉由插入檢所到的資料到HTML模板中動態產生HTML頁面讓瀏覽器顯示。

ExpressprovidesmethodstospecifywhatfunctioniscalledforaparticularHTTPverb(GET,POST,SET,etc.)andURLpattern("Route"),andmethodstospecifywhattemplate("view")engineisused,wheretemplatefilesarelocated,andwhattemplatetousetorenderaresponse.YoucanuseExpressmiddlewaretoaddsupportforcookies,sessions,andusers,gettingPOST/GETparameters,etc.YoucanuseanydatabasemechanismsupportedbyNode(Expressdoesnotdefineanydatabase-relatedbehaviour). Thefollowingsectionsexplainsomeofthecommonthingsyou'llseewhenworkingwithExpressandNodecode.HelloworldExpressFirstletsconsiderthestandardExpressHelloWorldexample(wediscusseachpartofthisbelow,andinthefollowingsections). 備註:IfyouhaveNodeandExpressalreadyinstalled(orifyouinstallthemasshowninthenextarticle),youcansavethiscodeinatextfilecalledapp.jsandrunitinabashcommandpromptbycalling: ./node./app.js varexpress=require('express'); varapp=express(); app.get('/',function(req,res){ res.send('HelloWorld!'); }); app.listen(3000,function(){ console.log('Exampleapplisteningonport3000!'); }); Thefirsttwolinesrequire()(import)theexpressmoduleandcreateanExpressapplication.Thisobject,whichistraditionallynamedapp,hasmethodsforroutingHTTPrequests,configuringmiddleware,renderingHTMLviews,registeringatemplateengine,andmodifyingapplicationsettingsthatcontrolhowtheapplicationbehaves(e.g.theenvironmentmode,whetherroutedefinitionsarecasesensitive,etc.) Themiddlepartofthecode(thethreelinesstartingwithapp.get)showsaroutedefinition.Theapp.get()methodspecifiesacallbackfunctionthatwillbeinvokedwheneverthereisanHTTPGETrequestwithapath('/')relativetothesiteroot.Thecallbackfunctiontakesarequestandaresponseobjectasarguments,andsimplycallssend()ontheresponsetoreturnthestring"HelloWorld!" Thefinalblockstartsuptheserveronport'3000'andprintsalogcommenttotheconsole.Withtheserverrunning,youcouldgotolocalhost:3000inyourbrowsertoseetheexampleresponsereturned.ImportingandcreatingmodulesAmoduleisaJavaScriptlibrary/filethatyoucanimportintoothercodeusingNode'srequire()function.Expressitselfisamodule,asarethemiddlewareanddatabaselibrariesthatweuseinourExpressapplications. Thecodebelowshowshowweimportamodulebyname,usingtheExpressframeworkasanexample.Firstweinvoketherequire()function,specifyingthenameofthemoduleasastring('express'),andcallingthereturnedobjecttocreateanExpressapplication.Wecanthenaccessthepropertiesandfunctionsoftheapplicationobject. varexpress=require('express'); varapp=express(); Youcanalsocreateyourownmodulesthatcanbeimportedinthesameway. 備註:Youwillwanttocreateyourownmodules,becausethisallowsyoutoorganiseyourcodeintomanagableparts—amonolithicsingle-fileapplicationishardtounderstandandmaintain.Usingmodulesalsohelpsyoumanageyournamespace,becauseonlythevariablesyouexplicitlyexportareimportedwhenyouuseamodule. Tomakeobjectsavailableoutsideofamoduleyoujustneedtoassignthemtotheexportsobject.Forexample,thesquare.jsmodulebelowisafilethatexportsarea()andperimeter()methods: exports.area=function(width){returnwidth*width;}; exports.perimeter=function(width){return4*width;}; Wecanimportthismoduleusingrequire(),andthencalltheexportedmethod(s)asshown: varsquare=require('./square');//Herewerequire()thenameofthefilewithoutthe(optional).jsfileextension console.log('Theareaofasquarewithawidthof4is'+square.area(4)); 備註:Youcanalsospecifyanabsolutepathtothemodule(oraname,aswedidinitially). Ifyouwanttoexportacompleteobjectinoneassignmentinsteadofbuildingitonepropertyatatime,assignittomodule.exportsasshownbelow(youcanalsodothistomaketherootoftheexportsobjectaconstructororotherfunction): module.exports={ area:function(width){ returnwidth*width; }, perimeter:function(width){ return4*width; } }; ForalotmoreinformationaboutmodulesseeModules(NodeAPIdocs).UsingasynchronousAPIsJavaScriptcodefrequentlyusesasynchronousratherthansynchronousAPIsforoperationsthatmaytakesometimetocomplete.AsynchronousAPIisoneinwhicheachoperationmustcompletebeforethenextoperationcanstart.Forexample,thefollowinglogfunctionsaresynchronous,andwillprintthetexttotheconsoleinorder(First,Second). console.log('First'); console.log('Second'); Bycontrast,anasynchronousAPIisoneinwhichtheAPIwillstartanoperationandimmediatelyreturn(beforetheoperationiscomplete).Oncetheoperationfinishes,theAPIwillusesomemechanismtoperformadditionaloperations.Forexample,thecodebelowwillprintout"Second,First"becauseeventhoughsetTimeout()methodiscalledfirst,andreturnsimmediately,theoperationdoesn'tcompleteforseveralseconds. setTimeout(function(){ console.log('First'); },3000); console.log('Second'); Usingnon-blockingasynchronousAPIsisevenmoreimportantonNodethaninthebrowser,becauseNodeisasinglethreadedevent-drivenexecutionenvironment."singlethreaded"meansthatallrequeststotheserverarerunonthesamethread(ratherthanbeingspawnedoffintoseparateprocesses).Thismodelisextremelyefficientintermsofspeedandserverresources,butitdoesmeanthatifanyofyourfunctionscallsynchronousmethodsthattakealongtimetocomplete,theywillblocknotjustthecurrentrequest,buteveryotherrequestbeinghandledbyyourwebapplication. ThereareanumberofwaysforanasynchronousAPItonotifyyourapplicationthatithascompleted.ThemostcommonwayistoregisteracallbackfunctionwhenyouinvoketheasynchronousAPI,thatwillbecalledbackwhentheoperationcompletes.Thisistheapproachusedabove. 備註:Usingcallbackscanbequite"messy"ifyouhaveasequenceofdependentasynchronousoperationsthatmustbeperformedinorder,becausethisresultsinmultiplelevelsofnestedcallbacks.Thisproblemiscommonlyknownas"callbackhell".Thisproblemcanbereducedbygoodcodingpractices(seehttp://callbackhell.com/),usingamodulelikeasync,orevenmovingtoES6featureslikePromises. 備註:AcommonconventionforNodeandExpressistouseerror-firstcallbacks.Inthisconventionthefirstvalueinyourcallbackfunctionsisanerrorvalue,whilesubsequentargumentscontainsuccessdata.Thereisagoodexplanationofwhythisapproachisusefulinthisblog:TheNode.jsWay-UnderstandingError-FirstCallbacks(fredkschott.com). CreatingroutehandlersInourHelloWorldExpressexample(seeabove),wedefineda(callback)routehandlerfunctionforHTTPGETrequeststothesiteroot('/'). app.get('/',function(req,res){ res.send('HelloWorld!'); }); Thecallbackfunctiontakesarequestandaresponseobjectasarguments.Inthiscasethemethodsimplycallssend()ontheresponsetoreturnthestring"HelloWorld!"Thereareanumberofotherresponsemethodsforendingtherequest/responsecycle,forexampleyoucouldcallres.json()tosendaJSONresponseorres.sendFile()tosendafile. 備註:Youcanuseanyargumentnamesyoulikeinthecallbackfunctions;whenthecallbackisinvokedthefirstargumentwillalwaysbetherequestandthesecondwillalwaysbetheresponse.Itmakessensetonamethemsuchthatyoucanidentifytheobjectyou'reworkingwithinthebodyofthecallback. TheExpressapplicationobjectalsoprovidesmethodstodefineroutehandlersforalltheotherHTTPverbs,whicharemostlyusedinexactlythesameway:post(),put(),delete(),options(),trace(),copy(),lock(),mkcol(),move(),purge(),propfind(),proppatch(),unlock(),report(),mkactivity(),checkout(),merge(),m-``search(),notify(),subscribe(),unsubscribe(),patch(),search(),andconnect(). Thereisaspecialroutingmethod,app.all(),whichwillbecalledinresponsetoanyHTTPmethod.Thisisusedforloadingmiddlewarefunctionsataparticularpathforallrequestmethods.Thefollowingexample(fromtheExpressdocumentation)showsahandlerthatwillbeexecutedforrequeststo/secretirrespectiveoftheHTTPverbused(provideditissupportedbythehttpmodule). app.all('/secret',function(req,res,next){ console.log('Accessingthesecretsection...'); next();//passcontroltothenexthandler }); RoutesallowyoutomatchparticularpatternsofcharactersinaURL,andextractsomevaluesfromtheURLandpassthemasparameterstotheroutehandler(asattributesoftherequestobjectpassedasaparameter). Oftenitisusefultogrouproutehandlersforaparticularpartofasitetogetherandaccessthemusingacommonroute-prefix(e.g.asitewithaWikimighthaveallwiki-relatedroutesinonefileandhavethemaccessedwitharouteprefixof/wiki/).InExpressthisisachievedbyusingtheexpress.Routerobject.Forexample,wecancreateourwikirouteinamodulenamedwiki.js,andthenexporttheRouterobject,asshownbelow: //wiki.js-Wikiroutemodule varexpress=require('express'); varrouter=express.Router(); //Homepageroute router.get('/',function(req,res){ res.send('Wikihomepage'); }); //Aboutpageroute router.get('/about',function(req,res){ res.send('Aboutthiswiki'); }); module.exports=router; 備註:AddingroutestotheRouterobjectisjustlikeaddingroutestotheappobject(asshownpreviously). Tousetherouterinourmainappfilewewouldthenrequire()theroutemodule(wiki.js),thencalluse()ontheExpressapplicationtoaddtheRoutertothemiddlewarehandlingpath.Thetworouteswillthenbeaccessiblefrom/wiki/and/wiki/about/. varwiki=require('./wiki.js'); //... app.use('/wiki',wiki); We'llshowyoualotmoreaboutworkingwithroutes,andinparticularaboutusingtheRouter,lateroninthelinkedsectionRoutesandcontrollers.UsingmiddlewareMiddlewareisusedextensivelyinExpressapps,fortasksfromservingstaticfilestoerrorhandling,tocompressingHTTPresponses.WhereasroutefunctionsendtheHTTPrequest-responsecyclebyreturningsomeresponsetotheHTTPclient,middlewarefunctionstypicallyperformsomeoperationontherequestorresponseandthencallthenextfunctioninthe"stack",whichmightbemoremiddlewareoraroutehandler.Theorderinwhichmiddlewareiscalledisuptotheappdeveloper. 備註:Themiddlewarecanperformanyoperation,executeanycode,makechangestotherequestandresponseobject,anditcanalsoendtherequest-responsecycle.Ifitdoesnotendthecyclethenitmustcallnext()topasscontroltothenextmiddlewarefunction(ortherequestwillbelefthanging). Mostappswillusethird-partymiddlewareinordertosimplifycommonwebdevelopmenttaskslikeworkingwithcookies,sessions,userauthentication,accessingrequestPOSTandJSONdata,logging,etc.YoucanfindalistofmiddlewarepackagesmaintainedbytheExpressteam(whichalsoincludesotherpopular3rdpartypackages).OtherExpresspackagesareavailableontheNPMpackagemanager. TousethirdpartymiddlewareyoufirstneedtoinstallitintoyourappusingNPM.Forexample,toinstallthemorganHTTPrequestloggermiddleware,you'ddothis: npminstallmorgan Youcouldthencalluse()ontheExpressapplicationobjecttoaddthemiddlewaretothestack: varexpress=require('express'); varlogger=require('morgan'); varapp=express(); app.use(logger('dev')); ... 備註:Middlewareandroutingfunctionsarecalledintheorderthattheyaredeclared.Forsomemiddlewaretheorderisimportant(forexampleifsessionmiddlewaredependsoncookiemiddleware,thenthecookiehandlermustbeaddedfirst).Itisalmostalwaysthecasethatmiddlewareiscalledbeforesettingroutes,oryourroutehandlerswillnothaveaccesstofunctionalityaddedbyyourmiddleware. Youcanwriteyourownmiddlewarefunctions,andyouarelikelytohavetodoso(ifonlytocreateerrorhandlingcode).Theonlydifferencebetweenamiddlewarefunctionandaroutehandlercallbackisthatmiddlewarefunctionshaveathirdargumentnext,whichmiddlewarefunctionsareexpectedtocalliftheyarenotthatwhichcompletestherequestcycle(whenthemiddlewarefunctioniscalled,thiscontainsthenextfunctionthatmustbecalled). Youcanaddamiddlewarefunctiontotheprocessingchainwitheitherapp.use()orapp.add(),dependingonwhetheryouwanttoapplythemiddlewaretoallresponsesortoresponseswithaparticularHTTPverb(GET,POST,etc).Youspecifyroutesthesameinbothcases,thoughtherouteisoptionalwhencallingapp.use(). Theexamplebelowshowshowyoucanaddthemiddlewarefunctionusingbothmethods,andwith/withoutaroute. varexpress=require('express'); varapp=express(); //Anexamplemiddlewarefunction vara_middleware_function=function(req,res,next){ //...performsomeoperations next();//Callnext()soExpresswillcallthenextmiddlewarefunctioninthechain. } //Functionaddedwithuse()forallroutesandverbs app.use(a_middleware_function); //Functionaddedwithuse()foraspecificroute app.use('/someroute',a_middleware_function); //AmiddlewarefunctionaddedforaspecificHTTPverbandroute app.get('/',a_middleware_function); app.listen(3000); 備註:Abovewedeclarethemiddlewarefunctionseparatelyandthensetitasthecallback.Inourpreviousroutehandlerfunctionwedeclaredthecallbackfunctionwhenitwasused.InJavaScript,eitherapproachisvalid. TheExpressdocumentationhasalotmoreexcellentdocumentationaboutusingandwritingExpressmiddleware.ServingstaticfilesYoucanusetheexpress.staticmiddlewaretoservestaticfiles,includingyourimages,CSSandJavaScript(static()istheonlymiddlewarefunctionthatisactuallypartofExpress).Forexample,youwouldusethelinebelowtoserveimages,CSSfiles,andJavaScriptfilesfromadirectorynamed'public'atthesamelevelaswhereyoucallnode: app.use(express.static('public')); Anyfilesinthepublicdirectoryareservedbyaddingtheirfilename(relativetothebase"public"directory)tothebaseURL.Soforexample: http://localhost:3000/images/dog.jpg http://localhost:3000/css/style.css http://localhost:3000/js/app.js http://localhost:3000/about.html Youcancallstatic()multipletimestoservemultipledirectories.Ifafilecannotbefoundbyonemiddlewarefunctionthenitwillsimplybepassedontothesubsequentmiddleware(theorderthatmiddlewareiscalledisbasedonyourdeclarationorder). app.use(express.static('public')); app.use(express.static('media')); YoucanalsocreateavirtualprefixforyourstaticURLs,ratherthanhavingthefilesaddedtothebaseURL.Forexample,herewespecifyamountpathsothatthefilesareloadedwiththeprefix"/media": app.use('/media',express.static('public')); Now,youcanloadthefilesthatareinthepublicdirectoryfromthe/mediapathprefix. http://localhost:3000/media/images/dog.jpg http://localhost:3000/media/video/cat.mp4 http://localhost:3000/media/cry.mp3 Formoreinformation,seeServingstaticfilesinExpress.HandlingerrorsErrorsarehandledbyoneormorespecialmiddlewarefunctionsthathavefourarguments,insteadoftheusualthree:(err,req,res,next).Forexample: app.use(function(err,req,res,next){ console.error(err.stack); res.status(500).send('Somethingbroke!'); }); Thesecanreturnanycontentrequired,butmustbecalledafterallotherapp.use()androutescallssothattheyarethelastmiddlewareintherequesthandlingprocess! Expresscomeswithabuilt-inerrorhandler,whichtakescareofanyremainingerrorsthatmightbeencounteredintheapp.Thisdefaulterror-handlingmiddlewarefunctionisaddedattheendofthemiddlewarefunctionstack.Ifyoupassanerrortonext()andyoudonothandleitinanerrorhandler,itwillbehandledbythebuilt-inerrorhandler;theerrorwillbewrittentotheclientwiththestacktrace. 備註:Thestacktraceisnotincludedintheproductionenvironment.TorunitinproductionmodeyouneedtosetthetheenvironmentvariableNODE_ENVto'production'. 備註:HTTP404andother"error"statuscodesarenottreatedaserrors.Ifyouwanttohandlethese,youcanaddamiddlewarefunctiontodoso.FormoreinformationseetheFAQ. FormoreinformationseeErrorhandling(Expressdocs).UsingdatabasesExpressappscanuseanydatabasemechanismsupportedbyNode(Expressitselfdoesn'tdefineanyspecificadditionalbehaviour/requirementsfordatabasemanagement).Therearemanyoptions,includingPostgreSQL,MySQL,Redis,SQLite,MongoDB,etc. InordertousetheseyouhavetofirstinstallthedatabasedriverusingNPM.Forexample,toinstallthedriverforthepopularNoSQLMongoDByouwouldusethecommand: npminstallmongodb Thedatabaseitselfcanbeinstalledlocallyoronacloudserver.InyourExpresscodeyourequirethedriver,connecttothedatabase,andthenperformcreate,read,update,anddelete(CRUD)operations.Theexamplebelow(fromtheExpressdocumentation)showshowyoucanfind"mammal"recordsusingMongoDB. //thisworkswitholderversionsofmongodbversion~2.2.33 varMongoClient=require('mongodb').MongoClient; MongoClient.connect('mongodb://localhost:27017/animals',function(err,db){ if(err)throwerr; db.collection('mammals').find().toArray(function(err,result){ if(err)throwerr; console.log(result); }); }); //formongodbversion3.0andup letMongoClient=require('mongodb').MongoClient; MongoClient.connect('mongodb://localhost:27017/animals',function(err,client){ if(err)throwerr; letdb=client.db('animals'); db.collection('mammals').find().toArray(function(err,result){ if(err)throwerr; console.log(result); client.close(); }); } Anotherpopularapproachistoaccessyourdatabaseindirectly,viaanObjectRelationalMapper("ORM").Inthisapproachyoudefineyourdataas"objects"or"models"andtheORMmapsthesethroughtotheunderlyingdatabaseformat.ThisapproachhasthebenefitthatasadeveloperyoucancontinuetothinkintermsofJavaScriptobjectsratherthandatabasesemantics,andthatthereisanobviousplacetoperformvalidationandcheckingofincomingdata.We'lltalkmoreaboutdatabasesinalaterarticle. FormoreinformationseeDatabaseintegration(Expressdocs).Renderingdata(views)Templateengines(referredtoas"viewengines"byExpress)allowyoutospecifythestructureofanoutputdocumentinatemplate,usingplaceholdersfordatathatwillbefilledinwhenapageisgenerated.TemplatesareoftenusedtocreateHTML,butcanalsocreateothertypesofdocuments.Expresshassupportforanumberoftemplateengines,andthereisausefulcomparisonofthemorepopularengineshere:ComparingJavaScriptTemplatingEngines:Jade,Mustache,DustandMore. InyourapplicationsettingscodeyousetthetemplateenginetouseandthelocationwhereExpressshouldlookfortemplatesusingthe'views'and'viewengines'settings,asshownbelow(youwillalsohavetoinstallthepackagecontainingyourtemplatelibrarytoo!) varexpress=require('express'); varapp=express(); //Setdirectorytocontainthetemplates('views') app.set('views',path.join(__dirname,'views')); //Setviewenginetouse,inthiscase'some_template_engine_name' app.set('viewengine','some_template_engine_name'); Theappearanceofthetemplatewilldependonwhatengineyouuse.Assumingthatyouhaveatemplatefilenamed"index."thatcontainsplaceholdersfordatavariablesnamed'title'and"message",youwouldcallResponse.render()inaroutehandlerfunctiontocreateandsendtheHTMLresponse: app.get('/',function(req,res){ res.render('index',{title:'Aboutdogs',message:'Dogsrock!'}); }); FormoreinformationseeUsingtemplateengineswithExpress(Expressdocs).FilestructureExpressmakesnoassumptionsintermsofstructureorwhatcomponentsyouuse.Routes,views,staticfiles,andotherapplication-specificlogiccanliveinanynumberoffileswithanydirectorystructure.WhileitisperfectlypossibletohavethewholeExpressapplicationinonefile,typicallyitmakessensetosplityourapplicationintofilesbasedonfunction(e.g.accountmanagement,blogs,discussionboards)andarchitecturalproblemdomain(e.g.model,vieworcontrollerifyouhappentobeusinganMVCarchitecture). Inalatertopicwe'llusetheExpressApplicationGenerator,whichcreatesamodularappskeletonthatwecaneasilyextendforcreatingwebapplications.總結恭喜,您已完成Express/Node之旅的第一步!您現在應該了解Express和Node的主要優點,以及Express應用程序的主要部分(路由,中間件,錯誤處理和模板代碼)。

您還應該明白,Express是一個不固執己見的框架,您將這些組件組合在一起的方式以及您使用的函式庫,在很大程度上取決於您! 當然,Express是一個非常輕量級的Web應用程序框架,它的許多好處和潛力來自第三方函式庫和功能。

我們將在以下文章中更詳細地介紹這些內容。

在下一篇文章中,我們將介紹如何設置Node開發環境,以便您可以開始查看一些Express代碼。

Seealso Venkat.R-ManageMultipleNodeversions Modules(NodeAPIdocs) Express(homepage) Basicrouting(Expressdocs) Routingguide(Expressdocs) UsingtemplateengineswithExpress(Expressdocs) Usingmiddleware(Expressdocs) WritingmiddlewareforuseinExpressapps(Expressdocs) Databaseintegration(Expressdocs) ServingstaticfilesinExpress(Expressdocs) Errorhandling(Expressdocs) Overview:ExpressNodejs 次頁 Inthismodule Express/Nodeintroduction SettingupaNode(Express)developmentenvironment ExpressTutorial:TheLocalLibrarywebsite ExpressTutorialPart2:Creatingaskeletonwebsite ExpressTutorialPart3:UsingaDatabase(withMongoose) ExpressTutorialPart4:Routesandcontrollers ExpressTutorialPart5:Displayinglibrarydata ExpressTutorialPart6:Workingwithforms ExpressTutorialPart7:Deployingtoproduction Foundaproblemwiththispage?EditonGitHubSourceonGitHubReportaproblemwiththiscontentonGitHubWanttofixtheproblemyourself?SeeourContributionguide.Lastmodified:2022年9月20日,byMDNcontributors



請為這篇文章評分?