eggjs 是一個優秀的 Node.js 框架
概述:為什么標題上說 eggjs 是一個優秀的 Node.js 框架(可跳過)?
換言之,我們為什么選擇 eggjs 進行開發而不是之前初學時使用的 Express 框架呢?
Express 是最著名的 Node.js 框架,它甚至是官方唯一推薦過的(目前)
但是根據實際開發,我覺得它的配置相當冗長,比方說:它可以一句 app.use() 布滿長達數十行
這一點,我沒法繼續使用下去,所以就停止對它的學習。
就配置方面來說: eggjs 做得很好,它通過開發約束,將所有的配置文件放置在 config 文件中。
起初加載時便進行逐一對服務器進行設置,后設置的將會覆蓋之前的。配置則是基於 類似 json 一樣的寫法,這使得我們容易定位某一處配置並進行修改(因為 key 不能重復,檢索一下就知道在哪了)
同樣的,eggjs 擁有大量的插件,開發者需要怎樣的功能,在官方插件上幾乎都可以找到。
如果沒有找到所需插件,eggjs 也支持定制。
在這里可以找到官方 API 以及使用文檔:https://eggjs.org/zh-cn/
不再進行多說了,讓我們開始進行一個 eggjs 框架工程吧(跟官方的有些不同,按照官方的快速入門,總是遇到莫名其妙的錯誤)
官方的錯誤,配置讓我耗費了三四個小時才得以真正明白框架的使用方法,希望你看完這篇文章,只需半小時就能寫出一個高質量的項目
1.1 使用 腳手架 進行初步的工程目錄建立
這一步也是所有基於 Node.js 工程所必備的環節之一:當然,你也可以手動創建。
打開 DOS / 終端 ,使用以下命令轉到你需要存放的項目位置(這里是我的項目存放位置):
cd C:\Users\chong\Documents\NodeJS
我是在 Windows 系統下的 “文檔” 中創建了一個 NodeJS 目錄,它將是我用於所有 Node 項目的根目錄。
創建一個項目文件夾並進入( project 是項目名稱,可更改):
mkdir project && cd project
在這里,開始進行 腳手架 的初始化和安裝依賴並進行啟動:
# 初始化目錄(會創建必備的文件夾和JS,package.json 文件)
npm init egg --type=simple
# 安裝依賴
npm i
執行初始化目錄的時候,需要你填寫一些信息,這些信息最終都會導入 package.json 配置文件中。
紅框是 eggjs 初始化時創建的文件以及文件夾,后續我們再來了解它們的作用【重要】
而箭頭所指的則是需要填寫的信息,例如項目名稱,描述信息,作者以及 Cookie 密鑰
現在,你已經得到了一個較為完整的目錄結構(我已經運行過幾次,比剛創建的還多了一些文件,不必在意):
好了,再啟動項目,這里有幾種啟動方式:
# 啟動項目
npm run dev
npm start
npm start 屬於生產環境中使用,使用這種方式的話,需要打印信息輸出到控制台就看不到了。
而 npm run dev 是開發中所推薦的啟動方式,當你修改代碼時,則不必手動重啟服務器,eggjs 會自己重啟,你只需要等待一會就可以在瀏覽器看到相對應的修改。
重要的是:你隨時可以在代碼中寫上 console.log ,控制台也會有相應的顯示。
下方是多種啟動或測試的命令( package.json ),均在前方加入 npm 即可使用。
也可以修改它們,如果你需要換個端口,例如 dev,修改為 egg-bin dev --port 8081 (注意:兩個 - 符號)
啟動完成后,在瀏覽器中訪問 DOS / 終端 顯示的路徑(紅色箭頭):
黃色部分是被修改的文件,在這里不必理會。
到這里,你的初始化工作已經做完,不妨休息會,再繼續往下閱讀。
1.2 了解各個目錄、文件的作用以及 eggjs 如何處理它們
相信你已經成功初始化了吧,現在讓我們來了解 eggjs 的目錄結構,各個文件的作用:
重新回到之前的一張圖,我們可以清晰地看見 eggjs 到底創建了什么。
前一些以 . 開頭的文件我們不必理會,從 package.json 文件開始(我們已經知道這是配置文件),往下看:
它創建了兩個文件夾,分別是: app、config (test 屬於測試,如單元測試等,我們也不必理會)
app 是網站處理用戶請求,以及瀏覽器請求服務器資源的應用文件夾
它包含:router(路由文件)、controller(處理器)
是的,初始化就這么兩個,所以我建議在 app 目錄下再手動創建以下幾個文件夾:
public(存放靜態資源,如 css、js、img)
view (存放視圖文件)
service(處理數據等業務操作)
先來詳細說說路由文件,所有的網站都會有一個訪問地址,路由則是客戶端首先進入位置:
客戶端(瀏覽器)會發送一個請求,這個請求將會首先進入路由分發文件,匹配成功到某一個 處理器(Controller)后
這個處理器將會去進行相關業務操作(Service)拿到數據,之后 view 渲染一個頁面成功后一層層返還回去。
controller 文件夾下則放置着我們所有核心的網站代碼(后續解釋)
任何一個網站都需要進行配置,而所有的 Web服務器 都應該自身有創建環境的能力,而不是人為去為這個服務器配置好環境。
那么 config 文件夾就是為此而生。
由前面得知:eggjs 有着豐富的插件,所以必然有一個插件的管理、配置文件,它就是 plugin.js
后續我們將知道一個插件應該怎樣啟用,關閉,安裝,這里先不說明;
eggjs 最重要的配置文件則是 :config.default.js,它管理着整個 Node服務器 的所有配置,包括插件、Cookie安全密鑰、視圖渲染等等配置。
好了,看到這里你已經對生成的 eggjs 項目工程有了一個大致的了解(我昨天才接觸 node.js ,若有不對,望在評論中指出,我會進行修改,多謝)
1.3 了解一個請求是如何被處理的【重要】
讀完前面,你已經明白:eggjs 工程中的目錄,文件的作用(只介紹了部分),現在讓我們來深入了解代碼層次上,eggjs 如何處理用戶請求(不解析源碼,從生成的文件來看):
先來了解路由文件怎樣工作(建議所有的路由設計都放在一個文件中):
'use strict'; /** * @param {Egg.Application} app - egg application */ module.exports = app => { const { router, controller } = app; router.get('/', controller.main.index); };
router.get() 方法指的是 GET 請求。
第一個參數表示 URL,例如 www.cnblogs.com 是域名,那么 www.cnblogs.com/index 中的 / 開始,則都是該網站下的‘路由’
第二個參數表示 controller 文件夾下的 main.js 中的 index 方法【重要】,如下:
'use strict'; const Controller = require('egg').Controller; class MainController extends Controller { async index() { this.ctx.body = '<h1>Hello world</h1>'; } } module.exports = MainController;
所以,你會在瀏覽器的窗口中看見:
看,你已經知道它的請求過程了!先在 router.js 文件中找到用戶請求的位置,而網站進入默認是 /
所以我們已經捕獲到了這次請求,之后根據路由文件的描述找到 controller 文件夾下的 main 文件,在從中檢索到 index 方法
這個方法設置了body,讓它輸出一個 h1 標簽,寫上 Hello world 。
即 router -> controller.main.index()
但是這樣的網站根本不具備使用能力,留不住用戶,我們還需要根據不同用戶數據,渲染一個好看的頁面給用戶。
這時,我們就可以知道 eggjs 插件的強大之處了(再緩緩,梳理下閱讀到的知識,准備好了再繼續了解吧)。
1.4 通過模板引擎渲染頁面
eggjs 強大的插件足以使你在 Node服務器 上做到與其它Web服務器不同的體驗
先述說模板引擎,之后,讓我們了解一下網站多語言一鍵配置。
以 Nunjucks 模板引擎為例:
首先引入兩個插件:egg-view、egg-view-nunjucks
npm i egg-view -save
npm i egg-view-nunjucks -save
之后打開 config/config.default.js 文件:
'use strict'; const path = require('path'); module.exports = appInfo => { return { // Cookie 安全密鑰 keys: "_skfhj8546542354.16554", // 項目日志存放文件夾 logger: { dir: path.join(appInfo.baseDir, 'logs'), }, // 渲染模板配置 view: { // 配置視圖根路徑 root: path.join(appInfo.baseDir, 'app/view'), // 是否緩存路徑 cache: true, // 配置文件默認擴展名 defaultExtension: '.nj', // 默認渲染模板引擎 defaultViewEngine: 'nunjucks', // 文件映射配置 mapping: { '.nj': 'nunjucks' } } }; };
我已經注明了各個屬性的作用,可復制到你的文件中。
之后啟用插件:egg-view-nunjucks,打開 config/plugin.js 文件
'use strict'; /** * 模板引擎:用於渲染頁面數據 */ exports.nunjucks = { enable: true, package: 'egg-view-nunjucks', };
配置方面已經准備完畢,之后需要在 app/view 目錄下創建一個 index.nj 模板文件
<html> <head> <title>{{ page_title }}</title> </head> <body> <h1>{{ page_content }}</h1> </body> </html>
雙括號是模板引擎的語法之一,還有循環等(是不是覺得跟 jsp 差不多)
好了,讓我們修改 controller/main.js 文件
'use strict'; const Controller = require('egg').Controller; class MainController extends Controller { async index() { const { ctx } = this; await ctx.render('index',{ page_title : "標題", page_content : "模板引擎所渲染的頁面" }); } } module.exports = MainController;
注意:請加上 await 關鍵字,它表示等待一個 Promise 對象,如果不加上,會出現 404 錯誤,
因為在渲染過程中,處理器卻返回了結果(沒數據的結果),自然客戶端也會認為服務器沒有找到資源。
現在已經跟我們所想的一致,那么到這里,你已經具備了開發一個項目的能力;
之后會逐步介紹數據庫連接,數據處理等方法。敬請期待。
1.4.1 多語言配置(將會引用一些官方例子)
多語言顯示(按需配置),很簡單,基於插件擴展能力,我們首先在 config.default.js 中增加配置,完整看起來是這個樣子的:
'use strict'; const path = require('path'); module.exports = appInfo => { return { // Cookie 安全密鑰 keys: "_tourism_2650159865482545.265", // 項目日志存放文件夾 logger: { dir: path.join(appInfo.baseDir, 'logs'), }, // 渲染模板配置 view: { // 配置視圖根路徑 root: path.join(appInfo.baseDir, 'app/view'), // 是否緩存路徑 cache: true, // 配置文件默認擴展名 defaultExtension: '.qyml', // 默認渲染模板引擎 defaultViewEngine: 'nunjucks', // 文件映射配置 mapping: { '.qyml': 'nunjucks' } }, // 多語言配置 i18n: { // 默認語言,默認 "en_US" defaultLocale: 'zh-CN', // URL 參數,默認 "locale" queryField: 'locale', // Cookie 記錄的 key, 默認:"locale" cookieField: 'locale', // Cookie 的 domain 配置,默認為空,代表當前域名有效 cookieDomain: '', // Cookie 默認 `1y` 一年后過期, 如果設置為 Number,則單位為 ms cookieMaxAge: '1y', } }; };
第二步:將 egg-i18n 插件進行安裝,並寫入項目配置文件中
npm i egg-i18n -save
最新版的 eggjs 中默認開啟多語言插件,所以我們不必手動啟用。
之后在 config 目錄下創建一個 locale 文件夾【重要:拼寫一定要正確】
在 locale 文件夾中創建所需配置的語言文件(圖僅示例兩種),可以是 JSON 文件,也可以是 JS 文件,大概是這樣的(我的是 JS 格式):
所有的多語言開發都會基於一種語言,我以英語為例(國際化也都是英語):
zh-CN.js 是這樣配置的(用官方的例子):
module.exports = { "Email": "郵箱", "Welcome back, %s!": "歡迎回來,%s!" };
如果你是基於 JSON 文件,也就是 zh-CN.json ,那么編寫是這個樣子的:
{ "Email": "郵箱", "Welcome back, %s!": "歡迎回來,%s!" }
就算是英語也需要配置:
en_US.js 會是這樣編寫的:
module.exports = { "Email": "Email", "Welcome back, %s!": "Welcome back,%s!" };
至於 %s %d 之類的 format 標識,它們的作用是這樣的(引用官方例子):
// config/locale/zh-CN.js module.exports = { 'Welcome back, %s!': '歡迎回來,%s!', }; ctx.__('Welcome back, %s!', 'Shawn'); // zh-CN => 歡迎回來,Shawn! // en-US => Welcome back, Shawn!
好了,一切准備就緒,如果需要在 Controller 中直接輸出,需要調用 __ 方法進行轉義,注意是兩個下斜杠,不是讓你填空...
class HomeController extends Controller { async index() { const ctx = this.ctx; ctx.body = { message: ctx.__('Welcome back, %s!', ctx.user.name) // 或者使用 gettext,gettext 是 __ 函數的 alias // message: ctx.gettext('Welcome back', ctx.user.name) user: ctx.user, }; } }
在視圖模板中這樣使用,假設你是 nunjucks 模板引擎:
<html> <head> <title>{{ page_title }}</title> </head> <body> <h1>{{ __('Welcome back, %s!', page_content) }}</h1> </body> </html>
經過處理后,我們將得到這樣的頁面效果:
現在你也可以開發一個支持多語言的網站了,我所示例的都是基礎代碼,關於多語言支持請參考以下網址:
https://eggjs.org/zh-cn/core/i18n.html
今天就到這里了,后續會出一些插件使用,或者是可以快速開發的方法。
2020-2-11 寫於揭陽
轉載請附上本博客地址:https://www.cnblogs.com/chongsaid/ 或當前文章鏈接,否則視為侵犯著作權。