egg 시작 과정

10568 단어
선언: 최근에 노드 백엔드를 쓰고 egg를 사용했는데 프레임의 운행 과정을 잘 몰라요. 벽돌을 옮기는 설정이 더 많아서 자신이 없어요!
오늘 원본 코드를 꺼내서 여기에 기록해 주십시오
시작 명령줄:egg-bin dev
실행 과정을 보려면 node 디버깅을 사용하십시오:
프로젝트 실행 node --inspect-brk=6666./node_modules/egg-bin/bin/egg-bin.js dev 코드는 다음과 같습니다.
// egg-bin/bin/egg-bin.js
const Command = require('..');new Command().start();

require('.') 도입 모듈egg-bin/index.js EggBin
'use strict';
const path = require('path');
const Command = require('./lib/command');
class EggBin extends Command {
  constructor(rawArgv) { 
    super(rawArgv); 
    this.usage = 'Usage: egg-bin [command] [options]';   
    this.load(path.join(__dirname, 'lib/cmd'));
  }
}
module.exports = exports = EggBin;
exports.Command = Command;
exports.CovCommand = require('./lib/cmd/cov');
exports.DevCommand = require('./lib/cmd/dev');
exports.TestCommand = require('./lib/cmd/test');
exports.DebugCommand = require('./lib/cmd/debug');
exports.PkgfilesCommand = require('./lib/cmd/pkgfiles');

코드 보기 EggBin extends Command, Command 상속 Common-bin
다음 개체 new Command()를 만듭니다.start();,최상위 상위 클래스 CommonBin을 초기화하고 명령행 매개 변수 dev 가져오기
맵 컬렉션 만들기
class CommonBin {
  constructor(rawArgv) { 
   this.rawArgv = rawArgv || process.argv.slice(2);
   this.yargs = yargs(this.rawArgv);
   this.parserOptions = {
      execArgv: false,
      removeAlias: false, 
     removeCamelCase: false,
    };    
  this[COMMANDS] = new Map();
  } 
...

}

다음은 부류를 초기화하고 매개 변수를 초기화합니다
class Command extends CommonBin { 
 constructor(rawArgv) { 
   super(rawArgv);
    this.parserOptions = {
      execArgv: true,
      removeAlias: true,
    };    
this.options = {
  typescript: {
       description: 'whether enable typescript support, will load `ts-node/register` etc',
        type: 'boolean',
        alias: 'ts', 
       default: undefined,
      },  
  };  
}
...

}

다음은 EggBin을 초기화하는 것입니다. load 방법에 초점을 두고 load 방법은 최고급 부류 CommonBin을 계승합니다.
class EggBin extends Command { 
 constructor(rawArgv) { 
   super(rawArgv); 
   this.load(path.join(__dirname, 'lib/cmd'));
  }
}

CommonBin 아래의load 방법을 보고lib/cmd 파일 디렉터리를 읽으며 위의 흐름도와 관련된 AutodCommand,CovCommand,DebugCommand,DevCommand,PkgfilesCommand,TestCommand는 Require를 사용하여 Map 집합에 불러오고 저장합니다
  load(fullPath) {
    const files = fs.readdirSync(fullPath);
    const names = []; 
   for (const file of files) { 
     if (path.extname(file) === '.js') { 
       const name = path.basename(file).replace(/\.js$/, '');
        names.push(name);
        this.add(name, path.join(fullPath, file));
      }    
    }  
}  


add(name, target) { 
   if (!(target.prototype instanceof CommonBin)) {
        target = require(target);
    }    
    this[COMMANDS].set(name, target); 
  }

이제 초기화가 완료되었으며 new Command()가 실행됩니다.start (), 의 start 방법, 상속 톱 부류 CommonBin 중 co는 제3자 모듈이Generator 함수의 자동 집행기
 start() {    
    co(function* () { 
     yield this[DISPATCH]();
    }.bind(this)).catch(this.errorHandler.bind(this));
  }

  * [DISPATCH]() { 
   const parsed = yield this[PARSE](this.rawArgv); 
   const commandName = parsed._[0];
   if (this[COMMANDS].has(commandName)) {
         const Command = this[COMMANDS].get(commandName); 
         const rawArgv = this.rawArgv.slice();
         rawArgv.splice(rawArgv.indexOf(commandName), 1);
         const command = new Command(rawArgv); 
         yield command[DISPATCH]();
         return;
    }    
    const context = this.context;
    yield this.helper.callFn(this.run, [ context ], this);
  }

DISPATCH 방법을 호출하여 명령줄이 전달하는 매개 변수 dev에 따라 이전에 Map 집합에 저장된 대응하는 모듈이 있는지 판단하고 DevCommand 모듈을 찾으며 DevCommand 모듈을 초기화하고 기본 포트 7001을 설정하여 진정한 시작 파일 서버 빈을 불러옵니다
class DevCommand extends Command {
  constructor(rawArgv) { 
   super(rawArgv);
   this.defaultPort = 7001; 
   this.serverBin = path.join(__dirname, '../start-cluster');
   };
  } 
...
}

DevCommand를 초기화하고 DISPATCH 방법을 사용했습니다. 이번에는command Name=undifind가 바로this로 갑니다.helper.callFn
* [DISPATCH]() {
    const parsed = yield this[PARSE](this.rawArgv);
    const commandName = parsed._[0];
    if (this[COMMANDS].has(commandName)) {
      const Command = this[COMMANDS].get(commandName); 
      const rawArgv = this.rawArgv.slice(); 
      rawArgv.splice(rawArgv.indexOf(commandName), 1); 
      const command = new Command(rawArgv);
      yield command[DISPATCH]();
      return;
    }    
    const context = this.context;
    yield this.helper.callFn(this.run, [ context ], this);
  }

callFn은 최고급 부류인 CommonBin 아래의 helper의 방법입니다.run 방법은generatorFunction이고,run을 실행합니다.
callFn = function* (fn, args = [], thisArg) {
      if (!is.function(fn)) return;

      if (is.generatorFunction(fn)) { 
           return yield fn.apply(thisArg, args);
      }  
     const r = fn.apply(thisArg, args); 
     if (is.promise(r)) {
        return yield r;
      }  
    return r;
};

여기서 매개 변수run 방법은 하위 클래스 DevCommand에서 왔고forkNode에서 하위 프로세스를 만들기 시작합니다
 * 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),
    };    
    yield this.helper.forkNode(this.serverBin, devArgs, options); 
 }

CommonBin 의 helper 메서드 forkNode 를 실행하여 하위 프로세스를 만듭니다./node_modules/egg-bin/lib/start-cluster"
forkNode = (modulePath, args = [], options = {}) => {
  const proc = cp.fork(modulePath, args, options);
  gracefull(proc);
};

fork 하위 프로세스./node_modules/egg-bin/lib/start-clusterrequire(options.framework)가egg를 불러옵니다./node_modules/egg"
const options = JSON.parse(process.argv[2]);
require(options.framework).startCluster(options);

Egg 보기
'use strict';
exports.startCluster = require('egg-cluster').startCluster;
exports.Application = require('./lib/application');
exports.Agent = require('./lib/agent');
exports.AppWorkerLoader = require('./lib/loader').AppWorkerLoader;
exports.AgentWorkerLoader = require('./lib/loader').AgentWorkerLoader;
exports.Controller = require('./lib/core/base_context_class');
exports.Service = require('./lib/core/base_context_class');
exports.Subscription = require('./lib/core/base_context_class');
exports.BaseContextClass = require('./lib/core/base_context_class');

startCluster(options) 방법은 Require('egg-cluster') 모듈에서 나온 것입니다. 보기
exports.startCluster = function(options, callback) {
  new Master(options).ready(callback);
};

전재 대상:https://juejin.im/post/5c80cc9de51d4539171254ce

좋은 웹페이지 즐겨찾기