現場演示:鏈接
跳到新功能?
Node.js Web應用程序的樣板。
如果您過去曾參加過任何黑客馬拉松,那麼您就會知道開始一個項目需要多少時間開始:確定要構建的內容,選擇編程語言,選擇網絡框架,選擇CSS框架。不久之後,您可能會在Github上進行初始項目,只有這樣,其他團隊成員才能開始貢獻。還是做像通過Facebook身份驗證簽名這樣的簡單的事情?如果您不熟悉Oauth 2.0的工作原理,則可以花幾個小時。
當我啟動這個項目時,我的主要重點是簡單性和易用性。我還試圖使其盡可能通用和重複使用,以涵蓋Hackathon Web應用程序的大多數用例,而不會太具體。在最壞的情況下,您可以將其用作項目的學習指南,例如,如果您只想登錄Google Authentication,而無需登錄。
“很好!獨自一人已經是金了!”
- 阿德里安·勒·巴斯(Adrian Le Bas)
“太棒了。簡直太棒了。”
- 史蒂文·魯特(Steven Rueter)
“我已經使用了一年,而且許多項目,這是一個很棒的樣板,並且該項目維護得很好!”
- 凱文·格蘭傑(Kevin Granger)
“與薩哈特(Sahat)的項目相關的小世界。上週末,我們正在為黑客馬拉松(Hackathon)使用他的黑客馬拉松首發球員,並獲得了一些獎品。真的很方便!”
- 面試我曾經與之合作的公司之一的候選人。
MongoDB(本地安裝或託管)
Node.js 18+
命令行工具
Mac OS X: Xcode(或OS X 10.9+ : xcode-select --install )
Windows: Visual Studio Code + Windows子系統用於Linux -Ubuntu或Visual Studio
ubuntu / linux薄荷: sudo apt-get install build-essential
Fedora : sudo dnf groupinstall "Development Tools"
opensuse: sudo zypper install --type pattern devel_basis
注意:如果您是Node或Express的新手,則可以找到Node.js&Express From Scratch系列,有助於學習Node和Express的基礎。另外,這是一個完整初學者的另一個很棒的教程 - 啟動Node.js,Express,MongoDB。
步驟1:最簡單的開始方法是克隆存儲庫:
# Get the latest snapshot
git clone https://github.com/sahat/hackathon-starter.git myproject
# Change directory
cd myproject
# Install NPM dependencies
npm install
# Then simply start your app
node app.js注意:我強烈建議安裝Nodemon。它查看您的node.js應用程序中的任何更改,並自動重新啟動服務器。安裝後,而不是node app.js使用nodemon app.js從長遠來看,它將為您節省很多時間,因為每次更改代碼時,您都不需要手動重新啟動服務器。要安裝,請運行sudo npm install -g nodemon 。
步驟2:在完成步驟1和本地安裝MongoDB後需要獲取API鍵並更改配置,您應該能夠通過Web瀏覽器訪問應用程序並使用本地用戶帳戶。但是,在您從服務提供商那裡獲取特定密鑰之前,某些功能諸如API集成之類的功能可能無法正常運行。項目中提供的鑰匙是佔位符,您可以保留它們的功能,以獲取當前使用的功能。為了將獲得的密鑰納入應用程序,您有兩個選擇:
export命令: export FACEBOOK_SECRET=xxxxxx 。這種方法被認為是一種更好的做法,因為它降低了在代碼存儲庫中意外將您的秘密包含在內的風險。.env.example文件中替換鍵:打開.env.example文件,然後用新獲取的鍵更新佔位符鍵。此方法有意外檢查您對代碼存儲庫的秘密的風險。獲得和配置的內容:
SMTP
recaptcha
OAuth進行社交登錄(登錄 /登錄)
如果您打算使用API示例,則在API示例中使用的API鍵。
Mongodb地圖集
電子郵件
NGrok和HTTPS如果您想使用一些需要HTTP的API(例如Pinterest或Facebook),則需要下載Ngrok。啟動NGrok,將您的base_url設置為轉發地址(即https://3ccb-1234-abcd.ngrok-free.app ),然後使用轉發地址訪問您的應用程序。如果您使用的是Ngrok之類的代理,則如果您嘗試在http://localhost:8080而不是https://...ngrok-free.app地址訪問該應用程序,則可能會遇到CSRF不匹配錯誤。
安裝或下載獨立的Ngrok客戶端后,您可以啟動NGrok,以攔截端口8080上的數據,並在Linux或Ngrok HTTP 8080或ngrok http 8080中使用./ngrok http 8080 。
步驟3:開發您的應用程序並自定義體驗
步驟4:可選 - 部署到生產,請參閱:
您需要為API和服務提供所需的API和服務提供適當的憑據(客戶ID,客戶端秘密,API鍵或用戶名和密碼)。有關更多信息,請參見“入門”部分中的步驟2。
從提供商那裡獲取用於交易電子郵件的SMTP憑據。相應地設置SMTP_USER,SMTP_Password和SMTP_HOST環境變量。選擇SMTP主機時,請記住該應用程序被配置為在端口465上使用安全的SMTP傳輸。您可以靈活地選擇適合您需求或利用以下提供商之一的提供商,每個提供商都提供免費的層,以方便您。
| 提供者 | 免費層 | 網站 |
|---|---|---|
| sendgrid | 免費的100封電子郵件 | https://sendgrid.com |
| SMTP2GO | 免費每月1000封電子郵件 | https://www.smtp2go.com |
| Brevo | 免費300封電子郵件/天免費 | https://www.brevo.com |
.env中。這些密鑰將在設置下可訪問,如果您稍後再需要,請retaptcha鍵下降http://localhost:8080等)http://localhost:8080/auth/google/callback callback ).env中http://localhost:8080/auth/snapchat/callback ).env中.env中.env中.env中的Facebook_secretlocalhosthttp://localhost:8080等)http://localhost:8080/auth/facebook/callback )注意:成功與Facebook進行了成功登錄後,將用戶將用戶重定向到主頁,並在URL中使用Hash #_=_ 。這不是錯誤。有關處理方法的方法,請參閱此堆棧溢出討論。
http://localhost:8080等)作為主頁URL。http://localhost:8080/auth/github/callback callback ).env文件中http://localhost:8080等)。http://localhost:8080/auth/twitter/callback ).env文件中http://localhost:8080/auth/linkedin/callback callback )http://localhost:8080等)。r_basicprofile.env文件中.env文件中.env文件中http://localhost:8080/auth/foursquare/callback callback ).env文件中http://localhost:8080/auth/tumblr/callback callback ).env文件.env文件中http://localhost:8080/auth/twitch/callback callback ).env.env中.env文件中。.env文件的客戶ID和客戶端秘密| 姓名 | 描述 |
|---|---|
| config /passport.js | 護照本地和OAUTH策略,以及登錄中間件。 |
| 控制器/Api.js | /API路由和所有API示例的控制器。 |
| 控制器/contact.js | 觸點表的控制器。 |
| 控制器/home.js | 主頁的控制器(索引)。 |
| 控制器/user.js | 用戶帳戶管理的控制器。 |
| 型號/user.js | 用戶的雜種模式和模型。 |
| 民眾/ | 靜態資產(字體,CSS,JS,IMG)。 |
| public / js / application.js | 指定客戶端JavaScript依賴項。 |
| public / js / app.js | 將客戶端的JavaScript放在此處。 |
| public / css / main.scss | 您的應用程序的主要樣式表。 |
| 視圖 /帳戶/ | 登錄模板,密碼重置,註冊,配置文件。 |
| 視圖 /API / | API示例的模板。 |
| 視圖 /partials /flash.pug | 錯誤,信息和成功閃存通知。 |
| 視圖 /partials /header.pug | NAVBAR部分模板。 |
| 視圖 /partials /footer.pug | 頁腳部分模板。 |
| views /layout.pug | 基本模板。 |
| views /home.pug | 主頁模板。 |
| .dockerignore | 文件夾和文件被Docker使用忽略。 |
| .env.example | 您的API鍵,令牌,密碼和數據庫URI。 |
| .eslintrc | Eslint Linter的規則。 |
| .gitignore | 文件夾和git忽略的文件。 |
| app.js | 主申請文件。 |
| docker-compose.yml | Docker組成配置文件。 |
| Dockerfile | Docker配置文件。 |
| package.json | NPM依賴性。 |
| 包裹鎖 | 包含package.json中的NPM依賴項的精確版本。 |
注意:您對您的姓名或構建視圖的方式不偏愛。如果這使您更容易,則可以將所有模板放在頂級views目錄中而無需嵌套文件夾結構。只是不要忘記更新extends ../layout和Controller中的相應res.render()路徑。
| 包裹 | 描述 |
|---|---|
| @fortawesome/fontawesome | 符號和圖標庫。 |
| @googleapis/drive | Google Drive API集成庫。 |
| @googleapis/sheet | Google表API集成庫。 |
| @ladjs/bootstrap-social | 社交按鈕庫。 |
| @lob/lob-typescript-sdk | LOB(USPS郵件 /物理郵件服務)庫。 |
| @node-rs/bcrypt | 用於哈希和醃製用戶密碼的庫。 |
| @octokit/休息 | GitHub API庫。 |
| @Passport-JS/Passport-Twitter | X(Twitter)登錄支持(OAUTH 2)。 |
| @popperjs/core | 前端JS庫,用於Poppers和Tooltips。 |
| 軸 | HTTP客戶端。 |
| 身體偏遠者 | Node.js身體解析中間件。 |
| 引導程序 | CSS框架。 |
| 柴 | BDD/TDD斷言庫。 |
| Cheerio | 使用jQuery風格的語法刮擦網頁。 |
| 壓縮 | Node.js壓縮中間件。 |
| 連接蒙哥 | Express的MongoDB會話商店。 |
| Dotenv | 從.env文件加載環境變量。 |
| ErrorHandler | 僅開發錯誤處理程序中間件。 |
| eslint | Linter JavaScript。 |
| eslint-config-airbnb bas | Airbnb配置ESLINT。 |
| Eslint-Plugin-chai友好 | 使Eslint對Chai.js的“期望”和“應該”的陳述友好。 |
| Eslint-Plugin-Import | ESLINT插件具有有助於驗證正確導入的規則。 |
| 表達 | Node.js Web框架。 |
| Express-Flash | 為Express提供閃存消息。 |
| 快速速率限制 | 限制濫用保護的中間件。 |
| 明確 | 簡單的會話中間件。 |
| 沙啞 | Git Hook Manager可以使用GIT自動化任務。 |
| jQuery | 前端JS庫與HTML元素交互。 |
| LastFM | last.fm API庫。 |
| 絨毛階段 | git上演的棉絨文件的實用程序。 |
| 高球 | LOB API庫。 |
| Lodash | 用於使用數組,數字,對象,字符串的實用程序庫。 |
| 盧斯卡 | CSRF中間件。 |
| MailChecker | 驗證電子郵件地址有效而不是一次性地址。 |
| 摩卡 | 測試框架。 |
| 片刻 | 解析,驗證,計算日期和時間。 |
| Mongodbmemoryserver | MongoDB在內存中(用於未運行DB的運行測試)。 |
| 貓鼬 | MongoDB ODM。 |
| 摩根 | http請求logger中間件。 |
| Multer | Node.js中間件,用於處理multipart/form-data 。 |
| Nodemailer | node.js庫發送電子郵件。 |
| 紐約 | 覆蓋測試。 |
| 護照 | Node.js的簡單優雅的身份驗證庫 |
| 護照 - 臉書 | 使用Facebook插件登錄。 |
| Passport-GitHub2 | 使用GitHub插件登錄。 |
| Passport-Google-Oauth | 使用Google插件登錄。 |
| 護照 - 鏈接蛋白 - 歐洲2號 | 使用LinkedIn插件登錄。 |
| 護照本地 | 使用用戶名和密碼插件登錄。 |
| 護照歐洲 | 允許您設置自己的OAuth 1.0A和OAuth 2.0策略。 |
| Passport-Oauth2-Refresh | 使用刷新令牌刷新OAuth 2.0訪問令牌的庫。 |
| 護照扣 | 使用Snapchat插件登錄。 |
| 護照式 - 開機 | OpenID 2.0蒸汽插件。 |
| 補丁包 | 修復維護者修復前方的損壞節點模塊。 |
| PayPal-Rest-SDK | PayPal API庫。 |
| 帕格 | Express的模板引擎。 |
| Sass | SASS編譯器以產生超級大國的CSS |
| 辛農 | 測試間諜,存根和模擬JavaScript。 |
| 條紋 | 官方條紋API庫。 |
| 超級 | HTTP斷言庫。 |
| Twilio | Twilio API庫。 |
| Twitch-Passport | 用Twitch插件登錄。 |
| 驗證器 | 字符串驗證器和消毒器的庫。 |
filesize(265318); // "265.32 kB" 。var token = _.find(req.user.tokens, { kind: 'twitter' }); ,其中第一個參數是一個數組,第二個參數是要搜索的對象。 403 Error: Forbidden ?您需要將以下隱藏的輸入元素添加到表單中。作為CSRF保護的一部分,已將其添加在拉動請求#40中。
input(type='hidden', name='_csrf', value=_csrf)
注意:現在可以使用某些URL。換句話說,您可以指定應繞過CSRF驗證檢查的路由列表。
注2:要使用CSRF中間件內的正則表達式測試,請查看req.originalUrl是否匹配您所需的模式。
這是app.js中定義的自定義錯誤消息,以指示連接到mongodb的問題:
mongoose . connection . on ( 'error' , ( err ) => {
console . error ( err ) ;
console . log ( '%s MongoDB connection error. Please make sure MongoDB is running.' , chalk . red ( '✗' ) ) ;
process . exit ( ) ;
} ) ;在啟動app.js之前,您需要讓MongoDB服務器運行。您可以在此處下載MongoDB,也可以通過軟件包管理器安裝它。 Windows用戶,閱讀Windows上的MongoDB。
提示:如果您始終連接到Internet,則可以使用MongoDB Atlas,而不是在本地下載和安裝MongoDB。您只需要在.env文件中更新數據庫憑據即可。
您沒有更改.env中的數據庫URI 。如果將MONGODB設置為localhost ,則只要MongoDB運行,它將僅在您的計算機上使用。當您部署渲染,OpenShift或其他一些提供商時,您將不會在localhost上運行MongoDB。您需要使用MongoDB地圖集創建一個帳戶,然後創建一個免費的層數據庫。有關如何與MongoDB Atlas逐步設置帳戶以及新的數據庫的更多信息,請參見部署。
為了簡單起見。雖然可能有更好的方法,例如此博客中概述的每個控制器將app程序上下文傳遞給每個控制器,但我發現這種風格會使初學者感到困惑。我花了很長時間才能掌握exports和module.exports的概念。 Exports,更不用說在其他文件中具有全局app參考。對我來說,這是落後的想法。 app.js是“應用程序的心臟”,它應該是一個引用模型,路線,控制器等。當在小型項目上獨奏時,我更喜歡在app.js中使用所有內容,就像此REST AST API服務器一樣。
本節旨在為您提供有關特定功能如何工作的詳細說明。也許您只是對它的工作原理感到好奇,或者也許在閱讀代碼時會迷失和困惑,我希望它為您提供一些指導。
HTML5 UP有許多漂亮的模板,您可以免費下載。
下載zip文件時,它將隨附index.html ,圖像, CSS和JS文件夾。那麼,您如何將其與黑客馬拉松首發者集成在一起? Hackathon Starter使用Bootstrap CSS框架,但這些模板不使用。嘗試同時使用兩個CSS文件可能會導致不希望的效果。
注意:使用自定義模板方法,您應該了解您無法重複使用我創建的任何視圖:佈局,主頁,API瀏覽器,登錄,註冊,註冊,帳戶管理,聯繫人。這些視圖是使用Bootstrap網格和样式建立的。您將必須使用模板中提供的不同語法手動更新網格。話雖如此,如果您願意,您可以混合和匹配:將Bootstrap用於主應用接口,以及用於登錄頁面的自定義模板。
讓我們從頭開始。對於此示例,我將使用逃生速度模板:
注意:為了簡單起見,我將僅考慮index.html ,然後跳過left-sidebar.html , no-sidebar.html , right-sidebar.html 。
將所有JavaScript文件從html5up-escape-velocity/js移動到public/js 。然後將所有CSS文件從html5up-escape-velocity/css移動到public/css 。最後,將所有圖像從html5up-escape-velocity/images移動到public/images 。您可以將其移至現有的IMG文件夾,但這需要手動更改每個img參考。抓住index.html的內容。
注意:不要忘記相應地更新所有CSS和JS路徑。
創建一個新的文件escape-velocity.pug views每當您看到代碼res.render('account/login')時,這意味著它將搜索views/account/login.pug文件。
讓我們看看它的外觀。在controllers/home.js中創建一個新的控制器逃生級別:
exports . escapeVelocity = ( req , res ) => {
res . render ( 'escape-velocity' , {
title : 'Landing Page'
} ) ;
} ;然後在app.js中創建路由。我將其放在索引控制器之後:
app . get ( '/escape-velocity' , homeController . escapeVelocity ) ;重新啟動服務器(如果您不使用Nodemon );然後,您應該在http://localhost:8080/escape-velocity上查看新模板
我將在這裡停下來,但是如果您想將此模板用作單頁,請看一下這些哈巴狗模板的工作方式: layout.pug基本模板, index.pug papug-主頁, partials/header.pug partials/footer.pug /header。您將必須手動將其分解成較小的碎片。弄清您要在所有頁面上保持相同的模板的哪個部分 - 這是您的新layout.pug 。然後,每個更改layout.pug頁面block content無論是index.pug , about.pug contact.pug使用現有模板作為參考。
這是一個相當漫長的過程,您從其他地方獲得的模板可能具有另一個網格系統。這就是為什麼我選擇Bootstrap作為黑客馬拉松首發球員的原因。許多人已經熟悉Bootstrap ,而且如果您從未使用過Bootstrap ,則很容易開始。您還可以在主題林上購買許多設計精美的引導主題,並將其用作Hackathon Starter的替換。但是,如果您想使用完全自定義的HTML/CSS設計,這應該有助於您開始!
Flash消息允許您在請求末尾顯示消息,並在下一個請求中訪問它,僅在下一個請求中訪問。例如,在失敗的登錄嘗試中,您將顯示帶有一些錯誤消息的警報,但是一旦刷新該頁面或訪問其他頁面並返回登錄頁面,該錯誤消息就會消失。它僅顯示一次。該項目使用快速消息的Express-Flash模塊。該模塊建立在Connect-Flash之上,這是我最初在該項目中使用的。使用Express-Flash,您不必向res.render()中的每個視圖明確發送閃存消息。由於Express-Flash ,默認情況下,您的messages中的所有閃存消息都可以在您的視圖中使用。
Flash消息具有兩個步驟的過程。您使用req.flash('errors', { msg: 'Error messages goes here' }在控制器中創建閃存消息,然後在您的視圖中顯示它們:
if messages . errors
.alert.alert-danger.fade.in
for error in messages . errors
div = error . msg在第一步中, 'errors'是Flash消息的名稱,該名稱應與視圖中messages對像上的屬性名稱匹配。 if message.errors您不想顯示閃存消息,則在內部將警報消息放在內部。為了{ msg: 'Error message goes here' }而不僅僅是字符串 - 'Error message goes here'原因是為了一致性。為了澄清一下,用於驗證和消毒用戶輸入的Express-Validator模塊將所有錯誤返回作為對像數組的所有錯誤,其中每個對像都有一個msg屬性,並帶有消息,為什麼發生了錯誤。這是一個更籠統的示例,說明存在錯誤時返回的內容:
[
{ param : "name" , msg : "Name is required" , value : "<received input>" } ,
{ param : "email" , msg : "A valid email is required" , value : "<received input>" }
]為了保持與該樣式一致,您應該將所有{ msg: 'My flash message' }而不是字符串。否則,您將看到一個沒有錯誤消息的警報框。那是因為在局部/flash.pug模板中,它將嘗試輸出error.msg (即"My flash message".msg ),換句話說,它將嘗試在字符串對像上調用一個msg方法,該方法將返回未定義。我剛才提到的有關錯誤的所有內容,也適用於“信息”和“成功”閃存消息,您甚至可以自己創建一個新的,例如:
數據使用控制器(示例)
req.flash('warning', { msg: 'You have exceeded 90% of your data usage' });
用戶帳戶頁面(示例)
if messages . warning
.alert.alert-warning.fade.in
for warning in messages . warning
div = warning . msg partials/flash.pug是一個部分模板,包含閃存消息的格式。以前,閃存消息散佈在每個使用閃存消息的視圖中(聯繫,登錄,註冊,配置文件),但現在,它使用了乾燥的方法。
flash消息部分模板包含在layout.pug ,以及頁腳和導航。
body
include partials/header
.container
include partials/flash
block content
include partials/footer如果您對Flash消息還有其他疑問,請隨時打開問題,我將相應地更新此迷你指南,或者如果您想包括我錯過的內容,請發送拉動請求。
一種更正確的方式來說這將是“我如何創建新路線?”主文件app.js包含所有路由。每個路由都有與之關聯的回調函數。有時,您會看到一條路線的三個或更多參數。在這樣的情況下,第一個參數仍然是URL字符串,而中間參數則稱為中間件。將中間件視為一扇門。如果這扇門阻止您繼續前進,則您將無法獲得回調功能。這樣的示例是需要身份驗證的路由。
app . get ( '/account' , passportConfig . isAuthenticated , userController . getAccount ) ;它總是從左到右。用戶訪問/account頁面。然後, isAuthenticated檢查您是否已驗證:
exports . isAuthenticated = ( req , res , next ) => {
if ( req . isAuthenticated ( ) ) {
return next ( ) ;
}
res . redirect ( '/login' ) ;
} ;如果您經過身份驗證,則可以通過致電return next(); 。然後,它將繼續進行下一個中間件,直到達到最後一個參數為止,這是一個回調函數,通常會在GET請求上呈現模板或在POST請求上重定向。在這種情況下,如果您經過身份驗證,您將被重定向到帳戶管理頁面;否則,您將被重定向到登錄頁面。
exports . getAccount = ( req , res ) => {
res . render ( 'account/profile' , {
title : 'Account Management'
} ) ;
} ; express.js具有app.get , app.post , app.put , app.delete ,但在大多數情況下,除非您構建一個rentful api,否則您只會使用前兩個http動詞。如果您只想顯示頁面,請使用GET ,如果要提交表單,發送文件,然後使用POST 。
這是用於將新路由添加到應用程序的典型工作流程。假設我們正在構建一個頁面,該頁面列出了數據庫中的所有書籍。
步驟1。首先定義路線。
app . get ( '/books' , bookController . getBooks ) ;注意:從Express 4.x開始,您可以這樣定義您的路線:
app . route ( '/books' )
. get ( bookController . getBooks )
. post ( bookController . createBooks )
. put ( bookController . updateBooks )
. delete ( bookController . deleteBooks )這是路由是否需要身份驗證和授權中間件的路線:
app . route ( '/api/twitter' )
. all ( passportConfig . isAuthenticated )
. all ( passportConfig . isAuthorized )
. get ( apiController . getTwitter )
. post ( apiController . postTwitter )使用哪種樣式對您有意義。兩者都是可以接受的。我認為將http動詞鏈接在app.route上是一種非常乾淨和優雅的方法,但是另一方面,當您每行有一條路線時,我再也看不到所有路線了。
步驟2。在模型目錄中創建一個新的模式和模型Book.js
const mongoose = require ( 'mongoose' ) ;
const bookSchema = new mongoose . Schema ( {
name : String
} ) ;
const Book = mongoose . model ( 'Book' , bookSchema ) ;
module . exports = Book ;步驟3。在控制器目錄中創建一個名為book.js的新的控制器文件。
/**
* GET /books
* List all books.
*/
const Book = require ( '../models/Book.js' ) ;
exports . getBooks = ( req , res ) => {
Book . find ( ( err , docs ) => {
res . render ( 'books' , { books : docs } ) ;
} ) ;
} ;步驟4。在app.js中導入該控制器。
const bookController = require ( './controllers/book' ) ;步驟5。創建books.pug服材模板。
extends layout
block content
.page-header
h3 All Books
ul
for book in books
li = book . name就是這樣!我會說,您可以將步驟1、2、3組合在一起:如下:
app . get ( '/books' , ( req , res ) => {
Book . find ( ( err , docs ) => {
res . render ( 'books' , { books : docs } ) ;
} ) ;
} ) ;當然,這更簡單,但是一旦您在app.js中傳遞了1000行代碼,導航該文件就變得有些挑戰。我的意思是,這個樣板項目的全部要點是分開關注點,因此您可以與隊友合作而不遇到合併衝突。想像一下,您有四個開發人員在一個app.js上工作,我向您保證,您不會一直很有趣地解決合併衝突。如果您是唯一的開發人員,那沒關係。但是正如我所說,一旦達到一定的LOC大小,就很難將所有內容保存在一個文件中。
這就是其中的全部。 Express.js非常易於使用。大多數情況下,您將與其他API打交道來完成實際工作:貓頭鷹查詢數據庫,socket.io,用於通過Websockets發送和接收消息,通過NodeMailer發送電子郵件,使用valiorator.js庫,使用Cheerio等網站等網站等,使用Cheerio等。
Dan Stroot提交了一個出色的拉力請求,該請求添加了帶有socket.io的實時儀表板。儘管我想將其添加到該項目中,但我認為它違反了黑客馬拉松首發的主要原則之一:
當我啟動這個項目時,我的主要重點是簡單性和易用性。我還試圖使其盡可能通用和重複使用,以涵蓋Hackathon Web應用程序的大多數用例,而不會太具體。
當我需要使用socket.io時,我確實需要它,但是大多數時候 - 我沒有。但更重要的是,Websockets支持仍在大多數託管提供商上進行實驗。由於過去的WebSocket提供了提供商問題,我尚未將Socket.io作為黑客馬拉松入門者的一部分。現在...如果您需要在應用中使用socket.io,請繼續閱讀。
首先,您需要安裝socket.io:
npm install socket . io替換const app = express();使用以下代碼:
const app = express ( ) ;
const server = require ( 'http' ) . Server ( app ) ;
const io = require ( 'socket.io' ) ( server ) ;我喜歡在app.js (從上到下)中具有以下代碼組織:模塊依賴項,導入控制器,導入配置,連接到數據庫,Express配置,路由,啟動服務器,socket.io stuff。這樣,我一直都知道在哪裡尋找東西。
在app.js的末尾添加以下代碼:
io . on ( 'connection' , ( socket ) => {
socket . emit ( 'greet' , { hello : 'Hey there browser!' } ) ;
socket . on ( 'respond' , ( data ) => {
console . log ( data ) ;
} ) ;
socket . on ( 'disconnect' , ( ) => {
console . log ( 'Socket disconnected' ) ;
} ) ;
} ) ;剩下的最後一件事要改變:
app . listen ( app . get ( 'port' ) , ( ) => {到
server . listen ( app . get ( 'port' ) , ( ) => {在這一點上,我們已經完成了後端。
現在,您可以選擇 - 將您的JavaScript代碼包含在PUG模板中,或將所有客戶端JavaScript放在單獨的文件中 - 在app.js中。我承認,當我首次從node.js和JavaScript開始時,我將所有JavaScript代碼放置在模板中,因為我可以訪問當時和那裡的Express變量。這是您可以做的最簡單的事情,但也是最不高效,更難維護的事情。從那時起,我幾乎再也不會在模板中包含Inline JavaScript。
但是,如果您想走更輕鬆的道路,也可以理解。在大多數情況下,您甚至都不關心黑客馬拉松期間的性能,您只想在時間用完之前“做好屎” 。好吧,無論哪種方式,無論採用哪種方法對您來說更有意義。歸根結底,您的構建至關重要,而不是如何構建它。
如果您想將所有JavaScript粘貼在模板中,則在layout.pug主模板文件中,將其添加到head塊中。
script ( src = '/socket.io/socket.io.js' )
script .
let socket = io . connect ( window . location . href );
socket . on ( ' greet ' , function ( data ) {
console . log (data);
socket . emit ( ' respond ' , { message : ' Hey there, server! ' });
});注意:注意socket.io.js的路徑,實際上您不必在項目中的任何地方都有socket.io.js文件;它將在運行時自動生成。
如果要將JavaScript代碼與模板分開,請將其內聯腳本代碼移動到app.js中,在$(document).ready()函數:
$ ( document ) . ready ( function ( ) {
// Place JavaScript code here...
let socket = io . connect ( window . location . href ) ;
socket . on ( 'greet' , function ( data ) {
console . log ( data ) ;
socket . emit ( 'respond' , { message : 'Hey there, server!' } ) ;
} ) ;
} ) ;我們完成了!
聲明一個只讀的命名常數。
const name = 'yourName' ;聲明塊範圍本地變量。
let index = 0 ; 使用`$ {}`語法,字符串可以嵌入表達式。
const name = 'Oggy' ;
const age = 3 ;
console . log ( `My cat is named ${ name } and is ${ age } years old.` ) ; 導入從外部模塊導出的函數,對像或原語。這些是最常見的導入類型。
const name = require ( 'module-name' ) ; const { foo , bar } = require ( 'module-name' ) ;從給定的文件或模塊導出功能,對像或原語。
module . exports = { myFunction } ; module . exports . name = 'yourName' ; module . exports = myFunctionOrClass ; 傳播操作員允許在預期多個參數(用於函數調用)或多個元素(對於數組文字)的地方擴展表達式。
myFunction ( ... iterableObject ) ; < ChildComponent { ... this . props } /> 在異步計算中使用承諾代表尚未完成但預計將來的操作。
var p = new Promise ( function ( resolve , reject ) { } ) ; catch()方法返回承諾,僅處理被拒絕的案件。
p . catch ( function ( reason ) { /* handle rejection */ } ) ; then()方法返回承諾。它需要兩個參數:成功和失敗案件的回調。
p . then ( function ( value ) { /* handle fulfillment */ } , function ( reason ) { /* handle rejection */ } ) ; Promise.all(iterable)方法返回了一個承諾,該承諾在峰值論點中的所有承諾都以第一個通過的拒絕承諾的原因解決或拒絕時解決了。
Promise . all ( [ p1 , p2 , p3 ] ) . then ( function ( values ) { console . log ( values ) } ) ; 箭頭功能表達式。較短的語法和詞法綁定了this值。箭頭功能是匿名的。
singleParam => { statements } ( ) => { statements } ( param1 , param2 ) => expression const arr = [ 1 , 2 , 3 , 4 , 5 ] ;
const squares = arr . map ( x => x * x ) ; 類聲明使用基於原型的繼承創建一個新類。
class Person {
constructor ( name , age , gender ) {
this . name = name ;
this . age = age ;
this . gender = gender ;
}
incrementAge ( ) {
this . age ++ ;
}
}?學分:Duckduckgo和@drksephy。
?回到頂部
Math . floor ( Date . now ( ) / 1000 ) ; moment().unix();
var now = new Date ( ) ;
now . setMinutes ( now . getMinutes ( ) + 30 ) ; moment().add(30, 'minutes');
// DD-MM-YYYY
var now = new Date ( ) ;
var DD = now . getDate ( ) ;
var MM = now . getMonth ( ) + 1 ;
var YYYY = now . getFullYear ( ) ;
if ( DD < 10 ) {
DD = '0' + DD ;
}
if ( MM < 10 ) {
MM = '0' + MM ;
}
console . log ( MM + '-' + DD + '-' + YYYY ) ; // 03-30-2016 console.log(moment(new Date(), 'MM-DD-YYYY'));
// hh:mm (12 hour time with am/pm)
var now = new Date ( ) ;
var hours = now . getHours ( ) ;
var minutes = now . getMinutes ( ) ;
var amPm = hours >= 12 ? 'pm' : 'am' ;
hours = hours % 12 ;
hours = hours ? hours : 12 ;
minutes = minutes < 10 ? '0' + minutes : minutes ;
console . log ( hours + ':' + minutes + ' ' + amPm ) ; // 1:43 am console.log(moment(new Date(), 'hh:mm A'));
var today = new Date ( ) ;
var nextWeek = new Date ( today . getTime ( ) + 7 * 24 * 60 * 60 * 1000 ) ; moment().add(7, 'days');
var today = new Date ( ) ;
var yesterday = date . setDate ( date . getDate ( ) - 1 ) ; moment().add(-1, 'days');
?回到頂部
User . find ( ( err , users ) => {
console . log ( users ) ;
} ) ; let userEmail = '[email protected]' ;
User . findOne ( { email : userEmail } , ( err , user ) => {
console . log ( user ) ;
} ) ; User
. find ( )
. sort ( { _id : - 1 } )
. limit ( 5 )
. exec ( ( err , users ) => {
console . log ( users ) ;
} ) ; 讓我們假設每個用戶都有一個votes字段,您想計算所有用戶數據庫中數據庫中的總數。一種非常低效的方法是循環瀏覽每個文檔並手動積累計數。或者,您可以使用MongoDB聚合框架:
User . aggregate ( { $group : { _id : null , total : { $sum : '$votes' } } } , ( err , votesCount ) => {
console . log ( votesCount . total ) ;
} ) ;?回到頂部
您需要在系統上安裝Docker和Docker-Compose。如果您使用的是WSL,則需要在Windows上安裝Docker桌面,然後在WSL上登錄。
Docker安裝
常見問題設置碼頭機
安裝Docker後,使用以下命令啟動應用程序:
# To build the project while supressing most of the build messages
docker-compose build web
# To build the project without supressing the build messages or using cached data
docker-compose build --no-cache --progress=plain web
# To start the application (or to restart after making changes to the source code)
docker-compose up web
要查看該應用程序,請找到您的Docker IP地址 +端口8080(通常是http://localhost:8080/ )。要使用8080以外的端口,您需要修改app.js,dockerfile和docker-compose.yml中的端口。
準備部署應用程序後,您將需要使用雲平台創建一個帳戶來託管它。這些不是唯一的選擇,但它們是我的首選。此外,您可以使用MongoDB Atlas創建一個帳戶,然後選擇以下提供商之一。同樣,還有很多其他選擇,您不僅限於下面列出的選擇。
渲染為Github和Gitlab上的存儲庫提供免費的NodeJS託管。
0.0.0.0/0的字段。單擊保存以保存0.0.0.0/0白名單。.env.example的mongodb_uri中的URI。確保用您在“安全性”選項卡下創建的數據庫用戶密碼替換。We are deploying your changes 。您將需要等待部署在應用程序中使用DB之前完成。sudo gem install rhc ?rhc login並輸入您的OpenShift憑據rhc app create MyApp nodejs-0.10git remote add openshift YOUR_GIT_REMOTE將這兩行添加到app.js ,只需將它們放在app.listen()之前。
var IP_ADDRESS = process . env . OPENSHIFT_NODEJS_IP || '127.0.0.1' ;
var PORT = process . env . OPENSHIFT_NODEJS_PORT || 8080 ;然後將app.listen()更改為:
app . listen ( PORT , IP_ADDRESS , ( ) => {
console . log ( `Express server listening on port ${ PORT } in ${ app . settings . env } mode` ) ;
} ) ;將其添加到package.json ,姓名和版本。這是必要的,因為默認情況下,OpenShift查找server.js文件。通過指定supervisor app.js它將在node.js進程崩潰時自動重新啟動服務器。
"main" : "app.js" ,
"scripts" : {
"start" : "supervisor app.js"
} ,git push -f openshift master將代碼推向OpenShift-f (force)標誌,因為OpenShift創建一個新的Node.js應用程序時,請使用歡迎頁面創建虛擬服務器。通過-f標誌將使用您的黑客馬拉松啟動項目存儲庫覆蓋所有內容。不要進行git pull ,因為它將造成不必要的合併衝突。git remote add azure [Azure Git URL]git push azure master請注意,此時看來,Bluemix的自由層託管Nodejs應用程序限制為30天。如果您正在尋找免費的層服務來託管您的應用程序,那麼渲染可能是一個更好的選擇
創建一個藍色帳戶
註冊Bluemix,或使用現有帳戶。
下載並安裝Cloud Foundry CLI,將您的應用程序推向Bluemix。
在您的應用程序的根部創建一個manifest.yml文件。
applications:
- name: <your-app-name>
host: <your-app-host>
memory: 128M
services:
- myMongo-db-name
您使用的主機最初將確定您的應用程序URL,例如<host>.mybluemix.net 。服務名稱“ mymongo-db-name”是您的MongoDB服務的聲明。例如,如果您使用其他服務,例如沃森(Watson),那麼您將以同樣的方式聲明它們。
$ cf login -a https://api.ng.bluemix.net
$ cf create-service mongodb 100 [your-service-name]
注意:這是MongoDB實例的免費實驗方面。使用MongoDB組成實例進行生產應用:
$ cf create-service compose-for-mongodb Standard [your-service-name]'
推動應用程序
$ cf push
$ cf env <your-app-name >
(To view the *environment variables* created for your application)
完成,現在轉到登台域( <host>.mybluemix.net ),然後查看您的應用程序運行。
請務必查看WATSON服務的完整列表,以促成稍作努力,從而增強您的應用功能。沃森服務很容易開始;這只是一個寧靜的API調用。這是Watson Toner分析儀的一個示例,可以理解您發送給Watson的文本的情感環境。
虛擬助手- 通過對話AI在所有渠道和接觸點上提供一致且聰明的客戶服務。
自然語言理解- 分析文本以從概念,實體,關鍵字等內容中提取元數據。
發現- 通過AI驅動的智能文檔理解和內容分析平台加速業務決策和流程。
編排- 將繁瑣的任務交給沃森,再也不會以同樣的方式工作。
沃森服務列表。
下載並安裝node.js
選擇或創建Google Cloud平台遊戲機項目
為您的項目啟用帳單(有300美元的免費試用版)
安裝並初始化Google Cloud SDK
在您的hackathon-starter文件夾的根部創建一個app.yaml文件,其中包含以下內容:
runtime : nodejs
env : flex
manual_scaling :
instances : 1確保已在.env.example中設置了MONGODB_URI
運行以下命令以部署hackathon-starter應用程序:
gcloud app deploy監視您在雲控制台中部署的應用程序
在雲控制台中查看應用程序的日誌
如果您從此樣板開始構建用於部署產品的應用程序,或者在黑客馬拉松之後,您希望將項目變硬供生產使用,請參見Prod-Checklist.md。
您可以在:changelog.md中找到該項目的更改程序
如果某件事不清楚,令人困惑或需要重構,請告訴我。始終歡迎拉動請求,但是由於該項目的自以為是的性質,我無法接受每個拉的請求。在提交拉動請求之前,請打開問題。該項目使用Airbnb JavaScript樣式指南,其中一些次要例外。如果要提交涉及哈巴狗模板的拉動請求,請確保您使用的是空格而不是選項卡。
麻省理工學院許可證(MIT)
版權(C)2014-2023 Sahat Yalkabov
特此免費授予獲得此軟件副本和相關文檔文件副本(“軟件”)的任何人,以無限制處理該軟件,包括無限制的使用權,複製,複製,修改,合併,合併,發布,分發,分發,分發,訂婚,和/或允許軟件的副本,並允許對以下條件提供以下條件,以下是以下條件。
上述版權通知和此許可通知應包含在軟件的所有副本或大量部分中。
該軟件是“原樣”提供的,沒有任何形式的明示或暗示保證,包括但不限於適銷性,特定目的的適用性和非侵權的保證。在任何情況下,作者或版權持有人都不應對任何索賠,損害賠償或其他責任責任,無論是在合同,侵權的訴訟中還是其他責任,是由軟件,使用或與軟件中的使用或其他交易有關的。