Node.js 國產 MVC 框架 ThinkJS 開發 config 篇

来源:http://www.cnblogs.com/xxuyou/archive/2017/07/13/nodejs-thinkjs-study-start.html
-Advertisement-
Play Games

原創: "荊秀網 網頁即時推送 https://xxuyou.com" | 轉載請註明出處 鏈接: "https://blog.xxuyou.com/nodejs thinkjs study config/" 本系列教程以 ThinkJS v2.x 版本( "官網" )為例進行介紹,教程以實際操作為 ...


原創:荊秀網 網頁即時推送 https://xxuyou.com | 轉載請註明出處
鏈接:https://blog.xxuyou.com/nodejs-thinkjs-study-config/

本系列教程以 ThinkJS v2.x 版本(官網)為例進行介紹,教程以實際操作為主。

按模塊定義配置文件

thinkjs 允許開發者直接在 src/common/config/ 下麵配置自己的參數,直接增加 js 文件即可,文件名只要符合 json 屬性名要求即可,文件內容遵照如下格式:

// 新增文件 assets.js 鍵入如下內容
'use strict';
export default {
  // key: value
};

文件內容只要符合一個 json 對象格式的定義即可。來看一個 log4js 的配置定義:

// log4js.js
'use strict';
export default {
  appenders: [
    {
      type    : "console",
      category: "console"
    },
    // 定義一個日誌記錄器
    {
      type                : "dateFile",                 // 日誌文件類型,可以使用日期作為文件名的占位符
      filename            : "logs/",     // 日誌文件名,可以設置相對路徑或絕對路徑
      pattern             : "debug/yyyyMMddhh.txt",  // 占位符,緊跟在filename後面
      absolute            : true,                   // filename是否絕對路徑
      alwaysIncludePattern: true,       // 文件名是否始終包含占位符
      category            : "logInfo"               // 記錄器名
    }
  ],
  levels   : {
    logInfo: "DEBUG"
  }        // 設置記錄器的預設顯示級別,低於這個級別的日誌,不會輸出
}

配置文件屬於靜態設置,一般存放不經常變動的設置參數(當然可以在記憶體中更改配置參數的值,下麵會詳細說明)。

另外配置文件是以 ES6 格式導出變數定義的 js 文件,而非 json 文件,這裡有個好處就是可以增加以 // 開頭的註釋說明。

細心的你肯定也發現了:除了 src/common/config 以外,src/home/ 模塊下麵也有個 config 文件夾。

一般來說按照配置文件的作用範圍來定義和安排,是比較合理的做法。

比如:所有模塊都會用到的配置放在 src/common/config 下麵比較合適,而僅用於 home 模塊的配置,放在 src/home/config 下麵比較合適。

當配置文件多了之後,我們需要關註一下多個配置文件的載入順序。

配置文件載入順序

官網是這麼描述配置文件載入順序的:

框架預設的配置 -> 項目模式下框架配置 -> 項目公共配置 -> 項目模式下的公共配置 -> 模塊下的配置

先問個問題:這五個配置都指的是哪裡呢?

前兩個可以忽略掉,那是 thinkjs 框架自身的配置設置,通常裡面不會有我們項目會用到的配置參數。

第三個和第四個則是在不同的項目創建模式(項目創建模式參見 Node.js 國產 MVC 框架 ThinkJS 開發 入門(荊秀網))下的預設 config 配置文件夾,位置在:

# normal mode
thinkjs_normal/src/config/*
# module mode
thinkjs_module/src/common/config/*

最後一個是指的在 module mode 下的項目,每個 module 自己的 config,位置在:

thinkjs_module/src/home/config/*

需要註意的是:多個配置文件最終會在 thinkjs 運行時被全部載入,並合併在一起(註意加粗文字)。

所以當存在多個配置文件時,需要註意配置參數的 key(即屬性名)儘量不要重覆,因為按照載入順序,後載入的 key 的值會覆蓋先載入的 key 的值,導致出現不希望的結果。

提示:教程主要講解處於模塊模式(moudule mode)下的開發方式。

自動切換配置文件

前面講到我們可以在 src/common/config 下麵放置配置文件,可以是全部配置參數都放在一個文件中,也可以分散在多個文件中。

有個常見的場景相信每個開發人員都會遇到:

有些配置參數是本地開發時才會用到,有些則是線上運行時才會用到。當開發完成在做持續集成時,配置參數上傳時卻發現開發參數和線上參數混合在一起。。。

thinkjs 在 src/common/config/env/ 下提供了三種配置參數環境,分別是 開發配置 development、生產配置 production、測試配置 testing,可以拯救我們的持續集成。

我們可以把項目配置分成三份一樣屬性名的參數,分別放在不同的配置環境中,這樣在本地開發是 thinkjs 自動載入開發配置,持續集成後線上載入的是生產配置,是不是很方便~

開發配置

開發配置文件是:src/common/config/env/development.js

如前所述,開發配置適用於本地開發使用,那麼 thinkjs 是怎麼知道現在是哪個環境呢?

答案是:已經在 package.json 裡面定義好了

{
  "scripts": {
    "start": "node www/development.js",
    "compile": "babel src/ --out-dir app/",
    "watch-compile": "node -e \"console.log('<npm run watch-compile> no longer need, use <npm start> command direct.');console.log();\"",
    "watch": "npm run watch-compile"
  }
}

可以看到 scripts.start 屬性定義了我們直接使用 npm start 時具體執行的實際上是 node www/development.js 命令。

本著打破沙鍋問到底的原則,看看這個文件裡面都有啥:

var thinkjs = require('thinkjs');
var path = require('path');

var rootPath = path.dirname(__dirname);

var instance = new thinkjs({
  APP_PATH: rootPath + path.sep + 'app',
  RUNTIME_PATH: rootPath + path.sep + 'runtime',
  ROOT_PATH: rootPath,
  RESOURCE_PATH: __dirname,
  env: 'development'  // <-- 這裡定義了當前的 thinkjs 實例的運行環境
});

// Build code from src to app directory.
instance.compile({
  log: true
});

instance.run();

:-)

生產配置

生產配置文件是:src/common/config/env/production.js

明白了開發配置的原理,也就不難明白生產配置了。

使用 node www/production.js 命令可以告訴 thinkjs 現在運行的是生產環境。

同理,生產配置中的參數名(屬性名)一般與開發配置一樣,只是值不同而已。

比較常見的是資料庫連接,本地開發時連接的是測試庫,而生產環境中連接的是生產庫,不同的地址、用戶、密碼和庫名,這些都是要交給運維人員來管理了。

測試配置

測試配置文件是:src/common/config/env/testing.js

明白了前兩個配置,這個也不難明白~

使用 node www/testing.js 命令可以告訴 thinkjs 現在運行的是測試環境。

定義和使用配置文件

前面其實有介紹過配置文件的分佈原則和定義方法,只要確保不與系統特定配置衝突即可自由定義。

系統特定配置

下麵是 thinkjs 預設的配置文件清單,這些系統特定配置都是有相應的使用場景和參數設置,詳細說明及完整參數詳見:https://thinkjs.org/zh-cn/doc/2.2/config.html#toc-f2a

src/common/config/
├── config.js  # 可以放置自己的配置
├── db.js  # 資料庫連接
├── env  # 運行時配置,下麵會詳述
│   ├── development.js
│   ├── production.js
│   └── testing.js
├── error.js  # 錯誤配置
├── hook.js  # 鉤子配置
├── locale  # 多語言版配置
│   └── en.js
├── session.js
└── view.js  # 視圖文件配置

自定義配置

一般做法是使用帶有層級的配置定義來組織配置參數(當然你一定要把全部參數都放在根下麵也不是不可以),參見如下配置:

// development.js
'use strict';
export default {
  site_name: "",
  site_title: "",
  site_keywords: "",
  site_description: "",
  db: {  // 這裡的配置替代 db.js
    type   : 'mysql',
    log_sql: true, //是否記錄 sql 語句
    adapter: {
      mysql: {
        host    : '127.0.0.1',
        port    : '3306',
        database: '',
        user    : '',
        password: '',
        prefix  : 'thinkjs_',
        encoding: 'utf8'
      }
    }
  },
  jwt: { // 第三方模塊的公共定義
    options: {
      algorithm: 'HS128',
      expiresIn: '7d'
    }
  },
  pay: {
    // 定義與線上支付介面相關的參數
  },
  backend: {
    // 定義管理後臺相關的參數
  },
  home: {
    // 定義前端網站相關的參數
  },
  rest: {
    // 定義 REST API 相關的參數
  },
  task: {
    // 定義 crond 相關的參數
  }
};

配置參數按照層次組織之後,需要註意的一點是:獲取配置的時候,不能無限制的 this.config(參數.參數.參數.參數) 下去,詳見下麵讀取配置的幾種方式描述。

幾種讀取配置的方式

配置文件定義之後,需要在項目運行的特別業務中讀取(也可以設置)到配置參數的值,根據讀取配置的位置的不同,thinkjs 提供了以下幾種讀取方式。

this.config()

這是使用率最高的讀取配置方法,絕大多數位置都可以使用此方法來讀取配置,比如 controller logic model service middleware 等地方。

// 配置 development.js
let dbOpt = this.config('db');
let jwtOpt = this.config('jwt.options');

這裡有一點需要註意:thinkjs 只能解析兩層配置參數,超過的層級不予解析(源碼中寫死了僅返回兩層)。

// 配置 development.js
let jwtOpt = this.config('jwt.options');
console.log(jwtOpt);
// 讀取成功,列印:
// {
//   options: {
//     algorithm: 'HS128',
//     expiresIn: '7d'
//   }
// }
let jwtOptAlg = this.config('jwt.options.algorithm');
console.log(jwtOptAlg);
// 超過三層,讀取失敗,只能讀取到兩層內容,列印:
// {
//   options: {
//     algorithm: 'HS128',
//     expiresIn: '7d'
//   }
// }
jwtOptAlg = jwtOpt['algorithm'];
console.log(jwtOptAlg);
// 正確的讀取方式,列印:
// HS128

think.config()

think.config 方法可以:

  • 無須考慮當前位置來讀取配置參數(其內部運行方式類似 this.config )
  • 跨模塊讀取配置參數

對於前者可以無須思考當前所在的模塊,更自由的讀取配置參數。

對於後者則對開發多模塊協作有著比較重要的意義,配置參數只有一份,不可能向不同的模塊複製相同的配置,因此需要“一處配置、多處可用”。因此無須考慮“我在哪裡讀取配置”,只要考慮“我要讀取哪裡的配置”即可。

// 配置文件:src/home/config/assets.js
let siteName = think.config('assets.site_name', undefined, 'home');

方法的第二個參數設置為 undefined 是為了避免將讀取動作變為設置動作。

方法的第三個參數標明瞭這個配置參數在哪個模塊下麵,一旦給定此參數,thinkjs 會認為 src/home/config/ 下麵的配置是你需要讀取的目標。

http.config()

http.config 方法實質上是 think.config() 的一個別名,可以讀取和設置配置參數。

避免踩坑之正確讀取參數

如果不能理解 thinkjs 設計配置文件讀取策略的情況下,會無意中踩坑,如下便是一個例子,代碼說話。

假設有兩個配置文件 src/common/config/assets.jssrc/home/config/assets.js,其中有著一樣的屬性名:

// src/common/config/assets.js
export default {
  "site_title": "my site"
};

// src/home/config/assets.js
export default {
  "site_title": "my test"
};
// 兩個配置參數屬性名一樣的情況下
// 使用不同的讀取方式
// 註意 config 方法的上下文對象的不同
// 會導致讀取的結果的不同
// src/home/controller/index.js
let assets = this.config('assets');
let siteTitle = assets['site_title'];
console.log('siteTitle is: ', siteTitle);
// 列印:
// my test

// src/home/controller/index.js
let assets = think.config('assets', undefined, 'common');
let siteTitle = assets['site_title'];
console.log('siteTitle is: ', siteTitle);
// 列印:
// my site

明白了 thinkjs 配置文件載入順序,就不會對上面發生的情況驚訝了~

如果你實在懶得去思考 this.configthink.config 兩者的分別,建議你乾脆使用後者,當讀取參數只傳入第一個參數時,它的表現與前者一致。這樣貌似更有利於代碼的維護~

避免踩坑之動態修改配置參數

當讀取到了配置參數後,當然是可以動態修改其為新的值,以讓後續的處理都讀到新的值。動態修改方法也很簡單:config 方法的第二個參數就是給定的新值。

let siteTitle = this.config('assets.site_title');
console.log(siteTitle);
// 列印:
// my test
this.config('assets.site_title', 'test 123');
siteTitle = this.config('assets.site_title');
console.log(siteTitle);
// 列印:
// test 123

上面的動態修改方法其實平淡無奇,來看看更有趣的修改方法,如下:

let siteAuthor = this.config('assets.site_author');
console.log(siteAuthor);
// 列印:
// {
//   name: 'xxuyou.com',
//   email: '[email protected]'
// }
siteAuthor['name'] = 'cap';
siteAuthor = this.config('assets.site_author');
console.log(siteAuthor);
// 列印:
// {
//   name: 'cap',
//   email: '[email protected]'
// }

假如上面的代碼片段修改一下寫法,就可以得到預期的效果,如下:

let siteAuthor = think.extend({}, this.config('assets.site_author')); // <-- 不同點在這裡
console.log(siteAuthor);
// 列印:
// {
//   name: 'xxuyou.com',
//   email: '[email protected]'
// }
siteAuthor['name'] = 'cap';
siteAuthor = this.config('assets.site_author');
console.log(siteAuthor);
// 列印:
// {
//   name: 'xxuyou.com',
//   email: '[email protected]'
// }

暫且不管這個 think.extend 是何方神聖,為啥修改等號左邊的變數的效果跟直接修改配置方法是一樣的?

原因其實很簡單:

  1. thinkjs 內部會緩存配置參數。
  2. 配置參數的值是一個 Object 而不是 String

OK~

語言包

語言包其實本身可以作為 i18n 來單獨描述,不過由於國際化在實際開發甚至架構過程中極少涉及到,因此這裡簡略描述。

src/config/locale/en.js

系統預設的英語語言環境,其中定義了相關的語言模版。

src/config/locale/zh-CN.js

規範起見,建議手工設立這個語言模版文件,並修改 src/common/config/local.js 中的 default 參數為 zh-CN即可啟用本語言模版。

done~

上一篇:Node.js 國產 MVC 框架 ThinkJS 開發 入門(荊秀網)
下一篇:Node.js 國產 MVC 框架 ThinkJS 開發 controller 篇(荊秀網)

原創:荊秀網 網頁即時推送 https://xxuyou.com | 轉載請註明出處
鏈接:https://blog.xxuyou.com/nodejs-thinkjs-study-config/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • java在jdk1.5中引入了註解,spring框架也正好把java註解發揮得淋漓盡致。 下麵會講解Spring中自定義註解的簡單流程,其中會涉及到spring框架中的AOP(面向切麵編程)相關概念。 不清楚java註解的,可以先瞭解java自定義註解: "Java自定義註解" 一、創建自定義註解 ...
  • if(!empty($_FILES["fileField"]["name"])){//檢測表單傳遞文件數據 $fileinfo = $_FILES["fileField"]; if($fileinfo['size'] < 10000000 && $fileinfo['size'] > 0){//大小 ...
  • 發現一批好文,完整系列,攢~~ 隨筆分類 - DDD - 『聖傑』 DDD理論學習系列(1)-- 通用語言 DDD理論學習系列(2)-- 領域 蒙 2017-07-13 09:24 周四 ...
  • 方法一: 雙層迴圈,外層迴圈元素,內層迴圈時比較值 如果有相同的值則跳過,不相同則push進數組 方法二:利用splice直接在原數組進行操作 雙層迴圈,外層迴圈元素,內層迴圈時比較值 值相同時,則刪去這個值 註意點:刪除元素之後,需要將數組的長度也減1. 優點:簡單易懂缺點:占用記憶體高,速度慢 方 ...
  • 代碼如下: ...
  • Math Math.trunc() 取出一個小數的小數部分,返回整數部分 Math.trunc(1.239); //1 Math.trunc( 3,1415926); // 2 Math.trunc(3.9); //3 對於空值和無法截取整數的值,返回NaN Math.trunc("a"); //N ...
  • 前面的話 Robots協議(也稱為爬蟲協議、機器人協議等)全稱是“網路爬蟲排除標準”(Robots Exclusion Protocol),網站通過Robots協議告訴搜索引擎哪些頁面可以抓取,哪些頁面不能抓取。本文將詳細介紹爬蟲協議robots 概述 robots.txt文件是一個文本文件,是搜索 ...
  • 前段時間一直忙於期末考試和找實習,好久沒寫博客了。 這段時間做了個小項目,包含了翻頁和富文本編輯器Ueditor的兩個知識點,Ueditor玩的還不是很深,打算玩深後再寫篇博客。 要實現翻頁功能,只需要設置一個pageIndex即可,然後每次載入頁面時通過pageIndex去載入數據就行。 那麼我們 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...