1. 程式人生 > >初探 Node.js 框架:eggjs (環境搭配篇)

初探 Node.js 框架:eggjs (環境搭配篇)

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',
        }
    };
};

最新版的 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/ 或當前文章連結,否則視為侵犯著作