333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';
 
const debug = require('debug')('egg-bin');
const Command = require('../command');
const path = require('path');
const utils = require('egg-utils');
const detect = require('detect-port');
 
class DevCommand extends Command {
  constructor(rawArgv) {
    super(rawArgv);
    this.usage = 'Usage: egg-bin dev [dir] [options]';
 
    this.defaultPort = 7001;
    this.serverBin = path.join(__dirname, '../start-cluster');
 
    this.options = {
      baseDir: {
        description: 'directory of application, default to `process.cwd()`',
        type: 'string',
      },
      workers: {
        description: 'numbers of app workers, default to 1 at local mode',
        type: 'number',
        alias: [ 'c', 'cluster' ],
        default: 1,
      },
      port: {
        description: 'listening port, default to 7001',
        type: 'number',
        alias: 'p',
      },
      framework: {
        description: 'specify framework that can be absolute path or npm package',
        type: 'string',
      },
      require: {
        description: 'will add to execArgv --require',
        type: 'array',
        alias: 'r',
      },
    };
  }
 
  get description() {
    return 'Start server at local dev mode';
  }
 
  get context() {
    const context = super.context;
    const { argv, execArgvObj } = context;
    execArgvObj.require = execArgvObj.require || [];
    // add require to execArgv
    if (argv.require) {
      execArgvObj.require.push(...argv.require);
      argv.require = undefined;
    }
    return context;
  }
 
  * run(context) {
    const devArgs = yield this.formatArgs(context);
    const env = {
      NODE_ENV: 'development',
      EGG_MASTER_CLOSE_TIMEOUT: 1000,
    };
    const options = {
      execArgv: context.execArgv,
      env: Object.assign(env, context.env),
    };
    debug('%s %j %j, %j', this.serverBin, devArgs, options.execArgv, options.env.NODE_ENV);
    yield this.helper.forkNode(this.serverBin, devArgs, options);
  }
 
  /**
   * format egg startCluster args then change it to json string style
   * @function helper#formatArgs
   * @param {Object} context - { cwd, argv }
   * @return {Array} pass to start-cluster, [ '{"port":7001,"framework":"egg"}' ]
   */
  * formatArgs(context) {
    const { cwd, argv } = context;
    /* istanbul ignore next */
    argv.baseDir = argv.baseDir || cwd;
    /* istanbul ignore next */
    if (!path.isAbsolute(argv.baseDir)) argv.baseDir = path.join(cwd, argv.baseDir);
 
    argv.port = argv.port || argv.p;
    argv.framework = utils.getFrameworkPath({
      framework: argv.framework,
      baseDir: argv.baseDir,
    });
 
    // remove unused properties
    argv.cluster = undefined;
    argv.c = undefined;
    argv.p = undefined;
    argv._ = undefined;
    argv.$0 = undefined;
 
    // auto detect available port
    if (!argv.port) {
      debug('detect available port');
      const port = yield detect(this.defaultPort);
      if (port !== this.defaultPort) {
        argv.port = port;
        console.warn(`[egg-bin] server port ${this.defaultPort} is in use, now using port ${port}\n`);
      }
      debug(`use available port ${port}`);
    }
    return [ JSON.stringify(argv) ];
  }
}
 
module.exports = DevCommand;