Config / 配置

实际项目中,肯定需要各种配置,包括:框架需要的配置以及项目自定义的配置。ThinkJS 将所有的配置都统一管理,文件都放在 src/config/ 目录下(多模块项目放在 src/common/config/),并根据不同的功能划分为不同的配置文件。

  • config.js 通用的一些配置
  • adapter.js adapter 配置
  • router.js 自定义路由配置
  • middleware.js middlware 配置
  • validator.js 数据校验配置
  • extend.js extend 配置

配置格式

// src/config.js

module.exports = {
  port: 1234,
  redis: {
    host: '192.168.1.2',
    port: 2456,
    password: ''
  }
}

配置值即可以是一个简单的字符串,也可以是一个复杂的对象,具体是什么类型根据具体的需求来决定。

多环境配置

有些配置需要在不同的环境下配置不同的值,如:数据库的配置在开发环境和生产环境是不一样的,此时可以通过环境下对应不同的配置文件来完成。

多环境配置文件格式为:[name].[env].js,如:config.development.jsconfig.production.js

在以上的配置文件中,目前只有 config.jsadapter.js 是支持不同环境配置文件的。

系统默认配置

系统内置一些默认配置,方便项目里直接使用,具体有:

  • config.js 通用的默认配置

    {
      port: 8360, // server port
      // host: '127.0.0.1', // server host, removed from 3.1.0
      workers: 0, // server workers num, if value is 0 then get cpus num
      createServer: undefined, // create server function
      startServerTimeout: 3000, // before start server time
      reloadSignal: 'SIGUSR2', // reload process signal
      stickyCluster: false, // sticky cluster, add from 3.1.0
      onUnhandledRejection: err => think.logger.error(err), // unhandledRejection handle
      onUncaughtException: err => think.logger.error(err), // uncaughtException handle
      processKillTimeout: 10 * 1000, // process kill timeout, default is 10s
      jsonpCallbackField: 'callback', // jsonp callback field
      jsonContentType: 'application/json', // json content type
      errnoField: 'errno', // errno field
      errmsgField: 'errmsg', // errmsg field
      defaultErrno: 1000, // default errno
      validateDefaultErrno: 1001 // validate default errno
    };
    

配置合并方式

系统启动时,会对配置合并,最终提供给开发者使用。具体流程为:

  • 加载 [ThinkJS]/lib/config/config.js
  • 加载 src/config/config.js
  • 加载 src/config/config.[env].js
  • 加载 [ThinkJS]/lib/config/adapter.js
  • 加载 [ThinkJS]/lib/config/adapter.[env].js
  • 加载 src/config/adapter.js
  • 加载 src/config/adapter.[env].js

[env] 为当前环境名称。最终会将这些配置按顺序合并在一起,同名的 key 后面会覆盖前面的。

配置加载是通过 think-loader 模块实现的,获取到合并后的配置后,通过 think-config 模块实例化后放在 think.config 上,后续通过 think.config 来获取或者设置配置。

使用配置

框架提供了在不同的环境下不同的方式快速获取配置:

  • 在 ctx 中,可以通过 ctx.config(key) 来获取配置
  • 在 controller 中,可以通过 controller.config(key) 来获取配置
  • 其他情况下,可以通过 think.config(key) 来获取配置

实际上,ctx.configcontroller.config 是基于 think.config 包装的一种更方便的获取配置的方式。

const redis = ctx.config('redis'); //获取 redis 配置
module.exports = class extends think.Controller {
  indexAction() {
    const redis = this.config('redis'); // 在 controller 中通过 this.config 获取配置
  }
}

动态设置配置

除了获取配置,有时候需要动态设置配置,如:将有些配置保存在数据库中,项目启动时将配置从数据库中读取出来,然后设置上去。

框架也提供了动态设置配置的方式,如:think.config(key, value)

// src/bootstrap/worker.js

//HTTP 服务启动前执行
think.beforeStartServer(async () => {
  const config = await think.model('config').select();
  think.config('userConfig', config); //从数据库中将配置读取出来,然后设置
})

常见问题

能否将请求中跟用户相关的值设置到配置中?

不能。配置设置是全局的,会在所有请求中生效。如果将请求中跟用户相关的值设置到配置中,那么多个用户同时请求时会相互干扰。

config.js 和 adapter.js 中的 key 能否重名?

不能。由于 config.js 和 adapter.js 是合并在一起的,所以要注意这二个配置不能有相同的 key,否则会被覆盖。

怎么查看合并后的所有配置?

系统启动时,会合并 config.js 和 adapter.js 的配置,最终会将配置写到文件 runtime/config/[env].json 文件中,如:当前 env 是 development,那么写入的文件为 runtime/config/development.json

配置写入文件时,是通过 JSON.stringify 将配置转化为字符串,由于 JSON.stringify 不支持正则、函数等之类的转换,所以配置中由于字段的值是正则或者函数时,生成的配置文件中将看不到这些字段对应的值。

多模块项目配置文件存放位置?

以上文档中描述的配置文件路径都是单模块项目下的,多模块项目下配置文件的路径为 src/common/config/,配置文件名称以及格式和单模块相同,如:src/common/config/config.jssrc/common/config/adapter.jssrc/common/config/middleware.js 等。

多模块项目下有些配置可以放在模块目录下,路径为:/src/[module]/config/[module] 为具体的模块名称。

如何查看配置文件的详细加载情况?

有时候希望查看配置文件的详细加载情况,这时候可以通过 DEBUG=think-loader-config-* npm start 来启动项目查看。

think-loader-config-40322 load file: //demo/app/config/adapter.js +3ms
think-loader-config-40323 load file: /demo/node_modules/thinkjs/lib/config/adapter.js +5ms
think-loader-config-40320 load file: /demo/app/config/adapter.js +4ms
think-loader-config-40323 load file: /demo/app/config/adapter.js +3ms
think-loader-config-40325 load file: /demo/app/config/config.js +0ms
think-loader-config-40325 load file: /demo/node_modules/thinkjs/lib/config/adapter.js +5ms
think-loader-config-40325 load file: /demo/app/config/adapter.js +3ms
think-loader-config-40321 load file: /demo/app/config/config.js +0ms
think-loader-config-40321 load file: /demo/node_modules/thinkjs/lib/config/adapter.js +5ms
think-loader-config-40321 load file: /demo/app/config/adapter.js +3ms
think-loader-config-40324 load file: /demo/app/config/config.js +0ms
think-loader-config-40319 load file: /demo/app/config/config.js +0ms
think-loader-config-40319 load file: /demo/node_modules/thinkjs/lib/config/adapter.js +6ms
think-loader-config-40324 load file: /demo/node_modules/thinkjs/lib/config/adapter.js +5ms
think-loader-config-40319 load file: /demo/app/config/adapter.js +7ms
think-loader-config-40324 load file: /demo/app/config/adapter.js +8ms

由于服务是通过 Master + 多个 Worker 启动的,debug 信息会打印多遍,这里为了区分加上了进程的 pid 值,如:think-loader-config-40322 为进程 pid 为 40322 下的配置文件加载情况。

如发现文档中的错误,请点击这里修改本文档,修改完成后请 pull request,我们会尽快合并、更新。