pomelo源码解析--新建项目(cli工具: pomelo)

Posted 夜色魅影

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pomelo源码解析--新建项目(cli工具: pomelo)相关的知识,希望对你有一定的参考价值。

pomelo怎么新建项目

官方文档
1. 安装pomelo
2. 新建项目HelloWorld
我简单整理了下创建新项目关键步骤:

  1. 安装pomelo

方式一:
$ npm install pomelo -g
·
方式二:
$ git clone https://github.com/NetEase/pomelo.git
$ cd pomelo
$ npm install -g
·
注:如果npm安装特别慢,安装国内淘宝镜像cnpm,此后的命令我们可以用cnpm 来替代 npm。安装命令如下:
npm install -g cnpm --registry=https://registry.npm.taobao.org

  1. 新建项目HelloWorld

$ mkdir HelloWorld
$ cd HelloWorld
$ pomelo init

按照这些执行完我们最终成功创建了一个名叫HelloWorld的新项目:

npm下载安装、发布

为什么执行npm install pomelo -g就可以安装pomelo模块?为什么简单执行pomelo init就可以新建一个项目了? 这些命令怎么来的?内部做了什么操作?
要搞清这些疑问之前,我们要先了解下nodejs如何编写、发布cli命令行工具
参考:https://blog.csdn.net/weixin_43254265/article/details/84797130

了解完npm怎么发布、安装包后,下面我们来分析下pomelo init源码实现流程:
首先我们可以看到pomelo源码中package.json配置中bin键

"bin": {
    "pomelo": "./bin/pomelo"
  },

执行pomelo实际运行的是/bin/pomelo,然后看下里面的pomelo init命令

// program = require('commander');
program.command('init [path]')
  .description('create a new application')
  .action(function(path) {
     init(path || CUR_DIR);
});

最后执行的init函数

function init(path) {
  console.log(INIT_PROJ_NOTICE);
  connectorType(function(type) { // 交互式命令(可用inquirer),用户输入选择客户端使用的协议连接组件,然后回调返回
    emptyDirectory(path, function(empty) { // 判断path目录是否为空目录,默认命令执行的当前目录
      if(empty) {
        process.stdin.destroy();
        createApplicationAt(path, type);  // 这里创建项目了,做了一系列复制、删除、替换操作
      } else {
        confirm('Destination is not empty, continue? (y/n) [no] ', function(force) {
          process.stdin.destroy();
          if(force) {
            createApplicationAt(path, type);
          } else {
            abort('Fail to init a project'.red);
          }
        });
      }
    });
  });
}
/**
 * Create directory and files at the given directory `path`.
 *
 * @param {String} ph
 */
function createApplicationAt(ph, type) {
  var name = path.basename(path.resolve(CUR_DIR, ph));
  copy(path.join(__dirname, '../template/'), ph);
  mkdir(path.join(ph, 'game-server/logs'));
  mkdir(path.join(ph, 'shared'));
  // rmdir -r
  var rmdir = function(dir) {
    var list = fs.readdirSync(dir);
    for(var i = 0; i < list.length; i++) {
      var filename = path.join(dir, list[i]);
      var stat = fs.statSync(filename);
      if(filename === "." || filename === "..") {
      } else if(stat.isDirectory()) {
        rmdir(filename);
      } else {
        fs.unlinkSync(filename);
      }
    }
    fs.rmdirSync(dir);
  };
  setTimeout(function() {
    switch(type) {
      case '1':
         // use websocket
         var unlinkFiles = ['game-server/app.js.sio',
         'game-server/app.js.wss',
         'game-server/app.js.mqtt',
         'game-server/app.js.sio.wss',
         'game-server/app.js.udp',
         'web-server/app.js.https',
         'web-server/public/index.html.sio',
         'web-server/public/js/lib/pomeloclient.js',
         'web-server/public/js/lib/pomeloclient.js.wss',
         'web-server/public/js/lib/build/build.js.wss',
         'web-server/public/js/lib/socket.io.js'];
         for(var i = 0; i < unlinkFiles.length; ++i) {
            fs.unlinkSync(path.resolve(ph, unlinkFiles[i]));
         }
        break;
        case '2':
          // use socket.io
          var unlinkFiles = ['game-server/app.js',
          'game-server/app.js.wss',
          'game-server/app.js.udp',
          'game-server/app.js.mqtt',
          'game-server/app.js.sio.wss',
          'web-server/app.js.https',
          'web-server/public/index.html',
          'web-server/public/js/lib/component.json',
          'web-server/public/js/lib/pomeloclient.js.wss'];
          for(var i = 0; i < unlinkFiles.length; ++i) {
            fs.unlinkSync(path.resolve(ph, unlinkFiles[i]));
          }

          fs.renameSync(path.resolve(ph, 'game-server/app.js.sio'), path.resolve(ph, 'game-server/app.js'));
          fs.renameSync(path.resolve(ph, 'web-server/public/index.html.sio'), path.resolve(ph, 'web-server/public/index.html'));

          rmdir(path.resolve(ph, 'web-server/public/js/lib/build'));
          rmdir(path.resolve(ph, 'web-server/public/js/lib/local'));
          break;
        case '3':
          // use websocket wss
          var unlinkFiles = ['game-server/app.js.sio',
          'game-server/app.js',
          'game-server/app.js.udp',
          'game-server/app.js.sio.wss',
          'game-server/app.js.mqtt',
          'web-server/app.js',
          'web-server/public/index.html.sio',
          'web-server/public/js/lib/pomeloclient.js',
          'web-server/public/js/lib/pomeloclient.js.wss',
          'web-server/public/js/lib/build/build.js',
          'web-server/public/js/lib/socket.io.js'];
          for(var i = 0; i < unlinkFiles.length; ++i) {
            fs.unlinkSync(path.resolve(ph, unlinkFiles[i]));
          }

          fs.renameSync(path.resolve(ph, 'game-server/app.js.wss'), path.resolve(ph, 'game-server/app.js'));
          fs.renameSync(path.resolve(ph, 'web-server/app.js.https'), path.resolve(ph, 'web-server/app.js'));
          fs.renameSync(path.resolve(ph, 'web-server/public/js/lib/build/build.js.wss'), path.resolve(ph, 'web-server/public/js/lib/build/build.js'));
          break;
        case '4':
          // use socket.io wss
           var unlinkFiles = ['game-server/app.js.sio',
          'game-server/app.js',
          'game-server/app.js.udp',
          'game-server/app.js.wss',
          'game-server/app.js.mqtt',
          'web-server/app.js',
          'web-server/public/index.html',
          'web-server/public/js/lib/pomeloclient.js'];
          for(var i = 0; i < unlinkFiles.length; ++i) {
            fs.unlinkSync(path.resolve(ph, unlinkFiles[i]));
          }

          fs.renameSync(path.resolve(ph, 'game-server/app.js.sio.wss'), path.resolve(ph, 'game-server/app.js'));
          fs.renameSync(path.resolve(ph, 'web-server/app.js.https'), path.resolve(ph, 'web-server/app.js'));
          fs.renameSync(path.resolve(ph, 'web-server/public/index.html.sio'), path.resolve(ph, 'web-server/public/index.html'));
          fs.renameSync(path.resolve(ph, 'web-server/public/js/lib/pomeloclient.js.wss'), path.resolve(ph, 'web-server/public/js/lib/pomeloclient.js'));

          rmdir(path.resolve(ph, 'web-server/public/js/lib/build'));
          rmdir(path.resolve(ph, 'web-server/public/js/lib/local'));
          fs.unlinkSync(path.resolve(ph, 'web-server/public/js/lib/component.json'));
          break;
        case '5':
          // use socket.io wss
           var unlinkFiles = ['game-server/app.js.sio',
          'game-server/app.js',
          'game-server/app.js.wss',
          'game-server/app.js.mqtt',
          'game-server/app.js.sio.wss',
          'web-server/app.js.https',
          'web-server/public/index.html',
          'web-server/public/js/lib/component.json',
          'web-server/public/js/lib/pomeloclient.js.wss'];
          for(var i = 0; i < unlinkFiles.length; ++i) {
            fs.unlinkSync(path.resolve(ph, unlinkFiles[i]));
          }
          
          fs.renameSync(path.resolve(ph, 'game-server/app.js.udp'), path.resolve(ph, 'game-server/app.js'));
          rmdir(path.resolve(ph, 'web-server/public/js/lib/build'));
          rmdir(path.resolve(ph, 'web-server/public/js/lib/local'));
          break;
        case '6':
          // use socket.io
          var unlinkFiles = ['game-server/app.js',
          'game-server/app.js.wss',
          'game-server/app.js.udp',
          'game-server/app.js.sio',
          'game-server/app.js.sio.wss',
          'web-server/app.js.https',
          'web-server/public/index.html',
          'web-server/public/js/lib/component.json',
          'web-server/public/js/lib/pomeloclient.js.wss'];
          for(var i = 0; i < unlinkFiles.length; ++i) {
            fs.unlinkSync(path.resolve(ph, unlinkFiles[i]));
          }

          fs.renameSync(path.resolve(ph, 'game-server/app.js.mqtt'), path.resolve(ph, 'game-server/app.js'));
          fs.renameSync(path.resolve(ph, 'web-server/public/index.html.sio'), path.resolve(ph, 'web-server/public/index.html'));

          rmdir(path.resolve(ph, 'web-server/public/js/lib/build'));
          rmdir(path.resolve(ph, 'web-server/public/js/lib/local'));
          break;
        }
        var replaceFiles = ['game-server/app.js',
        'game-server/package.json',
        'web-server/package.json'];
        for(var j = 0; j < replaceFiles.length; j++) {
          var str = fs.readFileSync(path.resolve(ph, replaceFiles[j])).toString();
          fs.writeFileSync(path.resolve(ph, replaceFiles[j]), str.replace('$', name));
        }
        var f = path.resolve(ph, 'game-server/package.json');
        var content = fs.readFileSync(f).toString();
        fs.writeFileSync(f, content.replace('#', version));
      }, TIME_INIT);
}

这样就生成了我们上面截图的HelloWorld项目了!至于其它pomelo stop、list、add、kill、restart、masterha等命令原理一样,可自行了解下。

以上是关于pomelo源码解析--新建项目(cli工具: pomelo)的主要内容,如果未能解决你的问题,请参考以下文章

pomelo源码解析--新建项目(cli工具: pomelo)

pomelo源码解析--新建项目(cli工具: pomelo)

工具和库的使用--pomelo-cli

pomelo源码解析--启动项目(pomelo start)

工具和库的使用--pomelo-robot

源码分析系列之PomeloForEgret