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

 

第二步:將 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/ 或當前文章鏈接,否則視為侵犯著作權。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM