因为我们要管理很多依赖,

最后我们选择使用autod来管理,

autod:一个自动分析项目所有的文件,获取所有的项目依赖和它们的版本的工具。

autod 同时可以根据我们传递的一些选项和参数,来直接更新 package.json 文件:

通过这个工具,我们可以很轻松的跟踪到所有依赖的最新版本,同时可以自动更新我们的 package.json 文件,新引入的模块也不需要手动去更新 package.json 文件了,一切都可以交给 autod 来完成。

通常,我们会在 Makefile 中加入 autod 相关的配置项,来自动化完成这个过程:

比如我想完成这个任务:

autod:
	@autod -w
	@npm install

但是一直报错*** missing separator.  Stop.

因为是makefile的命令行,开头必须用tab键,目前没有发现tabstop的设定值的不同,会引起error,但是我已经换成tab键开头了还是一直报这个错。最后才发现原来是webstrom文档的tab键不行,后来换成是文本用tab键才行。真是坑啊。

最后执行代码我们看到了:

zewdeMacBook-Pro:bin zew$ make autod

[DEPENDENCIES]

  "dependencies": {
    "colors": "1.3.2",
    "commander": "2.19.0",
    "minimatch": "3.0.4",
    "printable": "0.0.3"
  }
nothing to update in Dependencies

nothing to update in DevDependencies

[INFO] Write dependencies into package.jso

ok,执行成功了。

nodejs的部署的问题

可以看出来都下载完成了,可以看出我们通过MakeFile+autod自动化帮package.json里的依赖都下载完,

我们那么我现在如果通过改变package.json里的依赖的版本号可以帮我们动态控制吗?

首先我们执行autod -f获取到版本号:

zewdeMacBook-Pro:bin zew$ autod -f

[DEPENDENCIES]

  "dependencies": {
    "colors": "~1.3.2",
    "commander": "~2.19.0",
    "minimatch": "~3.0.4",
    "printable": "~0.0.3"
  }

好了,下面我来修改一下。把printable修改为0.0.4,再执行一遍脚本

 

下面我们安装stf

brew install rethinkdb graphicsmagick zeromq protobuf yasm pkg-config
npm install -g stf

再启动:

rethinkdb

新开个窗口启动stf

 

 

后来装stf也遇到了一堆的问题,结果是因为nodejs版本太高,我用的是10.x的后来换成8.2的就好了。但是还遇到了权限问题后来修改

sudo chown -R [owner] /usr/local/lib/node_modules

总是安装成功了

打印记过是:

#pragma message("Warning: zmq_utils.h is deprecated. All its functionali...
        ^
3 warnings generated.
  SOLINK_MODULE(target) Release/zmq.node
+ [email protected]
added 755 packages from 681 contributors in 47.692s

就好了。

然后启动一下

rethinkdb

nodejs的部署的问题

新开个窗口启动stf

 

zewdeMacBook-Pro:~ zew$ stf local
2018-10-10T05:12:18.271Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli migrate"
2018-10-10T05:12:18.503Z INF/db 48059 [*] Connecting to 127.0.0.1:28015
2018-10-10T05:12:18.535Z INF/db:setup 48059 [*] Database "stf" created
2018-10-10T05:12:20.444Z INF/db:setup 48059 [*] Table "devices" created
2018-10-10T05:12:20.472Z INF/db:setup 48059 [*] Table "logs" created
2018-10-10T05:12:20.528Z INF/db:setup 48059 [*] Index "devices"."owner" created
2018-10-10T05:12:20.528Z INF/db:setup 48059 [*] Waiting for index "devices"."owner"
2018-10-10T05:12:20.621Z INF/db:setup 48059 [*] Index "devices"."present" created
2018-10-10T05:12:20.621Z INF/db:setup 48059 [*] Waiting for index "devices"."present"
2018-10-10T05:12:20.713Z INF/db:setup 48059 [*] Index "devices"."providerChannel" created
2018-10-10T05:12:20.713Z INF/db:setup 48059 [*] Waiting for index "devices"."providerChannel"
2018-10-10T05:12:20.916Z INF/db:setup 48059 [*] Table "accessTokens" created
2018-10-10T05:12:20.962Z INF/db:setup 48059 [*] Table "vncauth" created
2018-10-10T05:12:21.097Z INF/db:setup 48059 [*] Table "users" created
2018-10-10T05:12:21.098Z INF/db:setup 48059 [*] Index "accessTokens"."email" created
2018-10-10T05:12:21.098Z INF/db:setup 48059 [*] Waiting for index "accessTokens"."email"
2018-10-10T05:12:21.152Z INF/db:setup 48059 [*] Index "vncauth"."response" created
2018-10-10T05:12:21.152Z INF/db:setup 48059 [*] Waiting for index "vncauth"."response"
2018-10-10T05:12:21.347Z INF/db:setup 48059 [*] Index "devices"."owner" is ready
2018-10-10T05:12:21.352Z INF/db:setup 48059 [*] Index "users"."adbKeys" created
2018-10-10T05:12:21.353Z INF/db:setup 48059 [*] Waiting for index "users"."adbKeys"
2018-10-10T05:12:21.465Z INF/db:setup 48059 [*] Index "vncauth"."responsePerDevice" created
2018-10-10T05:12:21.465Z INF/db:setup 48059 [*] Waiting for index "vncauth"."responsePerDevice"
2018-10-10T05:12:22.660Z INF/db:setup 48059 [*] Index "accessTokens"."email" is ready
2018-10-10T05:12:22.759Z INF/db:setup 48059 [*] Index "vncauth"."response" is ready
2018-10-10T05:12:22.924Z INF/db:setup 48059 [*] Index "users"."adbKeys" is ready
2018-10-10T05:12:23.033Z INF/db:setup 48059 [*] Index "vncauth"."responsePerDevice" is ready
2018-10-10T05:12:23.796Z INF/db:setup 48059 [*] Index "devices"."present" is ready
2018-10-10T05:12:23.889Z INF/db:setup 48059 [*] Index "devices"."providerChannel" is ready
2018-10-10T05:12:23.896Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli triproxy app001 --bind-pub tcp://127.0.0.1:7111 --bind-dealer tcp://127.0.0.1:7112 --bind-pull tcp://127.0.0.1:7113"
2018-10-10T05:12:23.898Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli triproxy dev001 --bind-pub tcp://127.0.0.1:7114 --bind-dealer tcp://127.0.0.1:7115 --bind-pull tcp://127.0.0.1:7116"
2018-10-10T05:12:23.900Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli processor proc001 --connect-app-dealer tcp://127.0.0.1:7112 --connect-dev-dealer tcp://127.0.0.1:7115"
2018-10-10T05:12:23.902Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli processor proc002 --connect-app-dealer tcp://127.0.0.1:7112 --connect-dev-dealer tcp://127.0.0.1:7115"
2018-10-10T05:12:23.905Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli reaper reaper001 --connect-push tcp://127.0.0.1:7116 --connect-sub tcp://127.0.0.1:7111"
2018-10-10T05:12:23.917Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli provider --name zewdeMacBook-Pro.local --min-port 7400 --max-port 7700 --connect-sub tcp://127.0.0.1:7114 --connect-push tcp://127.0.0.1:7116 --group-timeout 900 --public-ip localhost --storage-url http://localhost:7100/ --adb-host 127.0.0.1 --adb-port 5037 --vnc-initial-size 600x800 --mute-master never"
2018-10-10T05:12:23.941Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli auth-mock --port 7120 --secret kute kittykat --app-url http://localhost:7100/"
2018-10-10T05:12:23.976Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli app --port 7105 --secret kute kittykat --auth-url http://localhost:7100/auth/mock/ --websocket-url http://localhost:7110/"
2018-10-10T05:12:24.034Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli api --port 7106 --secret kute kittykat --connect-push tcp://127.0.0.1:7113 --connect-sub tcp://127.0.0.1:7111"
2018-10-10T05:12:24.039Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli websocket --port 7110 --secret kute kittykat --storage-url http://localhost:7100/ --connect-sub tcp://127.0.0.1:7111 --connect-push tcp://127.0.0.1:7113"
2018-10-10T05:12:24.044Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli storage-temp --port 7102"
2018-10-10T05:12:24.053Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli storage-plugin-image --port 7103 --storage-url http://localhost:7100/"
2018-10-10T05:12:24.063Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli storage-plugin-apk --port 7104 --storage-url http://localhost:7100/"
2018-10-10T05:12:24.068Z INF/util:procutil 48057 [*] Forking "/usr/local/lib/node_modules/stf/lib/cli poorxy --port 7100 --app-url http://localhost:7105/ --auth-url http://localhost:7120/ --api-url http://localhost:7106/ --websocket-url http://localhost:7110/ --storage-url http://localhost:7102/ --storage-plugin-image-url http://localhost:7103/ --storage-plugin-apk-url http://localhost:7104/"
2018-10-10T05:12:25.152Z INF/triproxy 48060 [app001] PUB socket bound on tcp://127.0.0.1:7111
2018-10-10T05:12:25.156Z INF/triproxy 48060 [app001] DEALER socket bound on tcp://127.0.0.1:7112
2018-10-10T05:12:25.157Z INF/triproxy 48060 [app001] PULL socket bound on tcp://127.0.0.1:7113
2018-10-10T05:12:25.162Z INF/triproxy 48061 [dev001] PUB socket bound on tcp://127.0.0.1:7114
2018-10-10T05:12:25.165Z INF/triproxy 48061 [dev001] DEALER socket bound on tcp://127.0.0.1:7115
2018-10-10T05:12:25.166Z INF/triproxy 48061 [dev001] PULL socket bound on tcp://127.0.0.1:7116
2018-10-10T05:12:25.678Z INF/poorxy 48073 [*] Listening on port 7100
2018-10-10T05:12:25.659Z INF/reaper 48064 [reaper001] Subscribing to permanent channel "*ALL"
2018-10-10T05:12:25.738Z INF/reaper 48064 [reaper001] Reaping devices with no heartbeat
2018-10-10T05:12:25.747Z INF/db 48063 [*] Connecting to 127.0.0.1:28015
2018-10-10T05:12:25.761Z INF/db 48064 [reaper001] Connecting to 127.0.0.1:28015
2018-10-10T05:12:25.771Z INF/reaper 48064 [reaper001] Receiving input from "tcp://127.0.0.1:7111"
2018-10-10T05:12:25.773Z INF/reaper 48064 [reaper001] Sending output to "tcp://127.0.0.1:7116"
2018-10-10T05:12:25.819Z INF/db 48062 [*] Connecting to 127.0.0.1:28015
2018-10-10T05:12:25.867Z INF/processor 48063 [proc002] App dealer connected to "tcp://127.0.0.1:7112"
2018-10-10T05:12:25.869Z INF/processor 48063 [proc002] Device dealer connected to "tcp://127.0.0.1:7115"
2018-10-10T05:12:25.923Z INF/processor 48062 [proc001] App dealer connected to "tcp://127.0.0.1:7112"
2018-10-10T05:12:25.926Z INF/processor 48062 [proc001] Device dealer connected to "tcp://127.0.0.1:7115"
2018-10-10T05:12:26.213Z INF/provider 48065 [*] Subscribing to permanent channel "8jpbUM0ETfG4xGk5QWGySQ=="
2018-10-10T05:12:26.286Z INF/provider 48065 [*] Sending output to "tcp://127.0.0.1:7116"
2018-10-10T05:12:26.289Z INF/provider 48065 [*] Receiving input from "tcp://127.0.0.1:7114"
2018-10-10T05:12:26.305Z INF/provider 48065 [*] Tracking devices
2018-10-10T05:12:26.247Z INF/storage:plugins:apk 48072 [*] Listening on port 7104
2018-10-10T05:12:26.320Z INF/provider 48065 [*] Found device "emulator-5554" (device)
2018-10-10T05:12:26.343Z INF/storage:plugins:image 48071 [*] Listening on port 7103
2018-10-10T05:12:26.362Z INF/auth-mock 48066 [*] Listening on port 7120
2018-10-10T05:12:26.425Z INF/provider 48065 [*] Registered device "emulator-5554"
2018-10-10T05:12:26.426Z INF/reaper 48064 [reaper001] Device "emulator-5554" is present
2018-10-10T05:12:26.512Z INF/storage:temp 48070 [*] Listening on port 7102
2018-10-10T05:12:26.810Z INF/app 48067 [*] Using pre-built resources
2018-10-10T05:12:26.833Z INF/app 48067 [*] Listening on port 7105
2018-10-10T05:12:26.836Z INF/db 48067 [*] Connecting to 127.0.0.1:28015
2018-10-10T05:12:26.902Z INF/websocket 48069 [*] Subscribing to permanent channel "*ALL"
2018-10-10T05:12:26.908Z INF/websocket 48069 [*] Listening on port 7110
2018-10-10T05:12:26.921Z INF/db 48069 [*] Connecting to 127.0.0.1:28015
2018-10-10T05:12:26.927Z INF/websocket 48069 [*] Sending output to "tcp://127.0.0.1:7113"
2018-10-10T05:12:26.928Z INF/websocket 48069 [*] Receiving input from "tcp://127.0.0.1:7111"
2018-10-10T05:12:27.048Z INF/device:support:push 48074 [emulator-5554] Sending output to "tcp://127.0.0.1:7116"
2018-10-10T05:12:27.054Z INF/device 48074 [emulator-5554] Preparing device
2018-10-10T05:12:27.470Z INF/device:support:sub 48074 [emulator-5554] Receiving input from "tcp://127.0.0.1:7114"
2018-10-10T05:12:27.473Z INF/device:support:sub 48074 [emulator-5554] Subscribing to permanent channel "*ALL"
2018-10-10T05:12:27.494Z INF/device:support:properties 48074 [emulator-5554] Loading properties
2018-10-10T05:12:27.494Z INF/api 48068 [*] Subscribing to permanent channel "*ALL"
2018-10-10T05:12:27.505Z INF/device:support:sdk 48074 [emulator-5554] Supports SDK 23
2018-10-10T05:12:27.505Z INF/device:support:abi 48074 [emulator-5554] Supports ABIs x86
2018-10-10T05:12:27.533Z INF/device:resources:minicap 48074 [emulator-5554] Installing "/usr/local/lib/node_modules/stf/node_modules/minicap-prebuilt/prebuilt/x86/bin/minicap" as "/data/local/tmp/minicap"
2018-10-10T05:12:27.534Z INF/device:resources:minicap 48074 [emulator-5554] Installing "/usr/local/lib/node_modules/stf/node_modules/minicap-prebuilt/prebuilt/x86/lib/android-23/minicap.so" as "/data/local/tmp/minicap.so"
2018-10-10T05:12:27.583Z INF/api 48068 [*] Listening on port 7106
2018-10-10T05:12:27.603Z INF/device:resources:service 48074 [emulator-5554] Checking whether we need to install STFService
2018-10-10T05:12:27.635Z INF/api 48068 [*] Sending output to "tcp://127.0.0.1:7113"
2018-10-10T05:12:27.637Z INF/api 48068 [*] Receiving input from "tcp://127.0.0.1:7111"
2018-10-10T05:12:27.793Z INF/db 48068 [*] Connecting to 127.0.0.1:28015
2018-10-10T05:12:27.818Z INF/device:resources:service 48074 [emulator-5554] Running version check
2018-10-10T05:12:28.194Z INF/device:resources:service 48074 [emulator-5554] STFService up to date
2018-10-10T05:12:28.196Z INF/device:plugins:service 48074 [emulator-5554] Launching agent
2018-10-10T05:12:28.388Z INF/device:plugins:service 48074 [emulator-5554] Agent says: "Listening on @stfagent"
2018-10-10T05:12:28.428Z INF/device:plugins:service 48074 [emulator-5554] Launching service
2018-10-10T05:12:28.429Z INF/device:plugins:service 48074 [emulator-5554] Agent says: "InputClient started"
2018-10-10T05:12:28.839Z INF/device:plugins:display 48074 [emulator-5554] Reading display info
2018-10-10T05:12:28.853Z INF/device:plugins:phone 48074 [emulator-5554] Fetching phone info
2018-10-10T05:12:28.866Z INF/device:plugins:identity 48074 [emulator-5554] Solving identity
2018-10-10T05:12:28.867Z INF/device:plugins:solo 48074 [emulator-5554] Subscribing to permanent channel "+dMhGpFI28OEk/LJBQj8PqTFjWQ="
2018-10-10T05:12:28.869Z INF/device:plugins:screen:stream 48074 [emulator-5554] Starting WebSocket server on port 7400
2018-10-10T05:12:28.890Z INF/device:resources:minitouch 48074 [emulator-5554] Installing "/usr/local/lib/node_modules/stf/node_modules/minitouch-prebuilt/prebuilt/x86/bin/minitouch" as "/data/local/tmp/minitouch"
2018-10-10T05:12:28.910Z WRN/device:plugins:data 48074 [emulator-5554] Unable to find device data { serial: 'emulator-5554',
  platform: 'Android',
  manufacturer: 'UNKNOWN',
  operator: 'Android',
  model: ' SDK built for x86',
  version: '6.0',
  abi: 'x86',
  sdk: '23',
  product: 'sdk_phone_x86',
  cpuPlatform: '',
  openGLESVersion: '2.0',
  display: 
   { id: 0,
     width: 1080,
     height: 1920,
     xdpi: 480,
     ydpi: 480,
     fps: 60.000003814697266,
     density: 3,
     rotation: 0,
     secure: true,
     size: 4.589389937671455,
     url: 'ws://localhost:7400' },
  phone: 
   { imei: '358240051111110',
     imsi: '310260000000000',
     phoneNumber: '+15555215554',
     iccid: '89014103211118510720',
     network: 'LTE' } }
2018-10-10T05:12:28.928Z INF/device:plugins:touch 48074 [emulator-5554] Touch origin is top left
2018-10-10T05:12:28.929Z INF/device:plugins:touch 48074 [emulator-5554] Requesting touch consumer to start
2018-10-10T05:12:28.930Z INF/device:plugins:touch 48074 [emulator-5554] Launching touch service
2018-10-10T05:12:28.938Z INF/device:plugins:touch 48074 [emulator-5554] Connecting to minitouch service
2018-10-10T05:12:29.014Z INF/device:plugins:touch 48074 [emulator-5554] minitouch says: "Note: device /dev/input/mice is not supported by libevdev"
2018-10-10T05:12:29.073Z INF/device:plugins:touch 48074 [emulator-5554] minitouch says: "Type B touch device qwerty2 (32767x32767 with 10 contacts) detected on /dev/input/event1 (score 43776)"
2018-10-10T05:12:29.262Z INF/device:plugins:touch 48074 [emulator-5554] minitouch says: "Connection established"
2018-10-10T05:12:29.264Z INF/device:plugins:touch 48074 [emulator-5554] Reading minitouch banner
2018-10-10T05:12:29.269Z INF/device:plugins:vnc 48074 [emulator-5554] Starting VNC server on port 7402
2018-10-10T05:12:29.271Z INF/device:plugins:browser 48074 [emulator-5554] Loading browser list
2018-10-10T05:12:29.274Z INF/device:plugins:browser 48074 [emulator-5554] Updating browser list
2018-10-10T05:12:29.276Z INF/device:plugins:mute 48074 [emulator-5554] Will not mute master volume
2018-10-10T05:12:29.291Z INF/device:resources:minirev 48074 [emulator-5554] Installing "/usr/local/lib/node_modules/stf/vendor/minirev/x86/minirev" as "/data/local/tmp/minirev"
2018-10-10T05:12:29.319Z INF/device:plugins:forward 48074 [emulator-5554] Launching reverse port forwarding service
2018-10-10T05:12:29.323Z INF/device:plugins:forward 48074 [emulator-5554] Connecting to reverse port forwarding service
2018-10-10T05:12:29.611Z INF/device:plugins:connect 48074 [emulator-5554] Listening on port 7401
2018-10-10T05:12:29.614Z INF/device 48074 [emulator-5554] Fully operational
2018-10-10T05:12:36.338Z INF/provider 48065 [*] Providing all 1 device(s)

 

rethinkdb的日志

zewdeMacBook-Pro:~ zew$ cd /usr/local/Cellar/rethinkdb/2.3.6/bin
zewdeMacBook-Pro:bin zew$ rethinkdb
Recursively removing directory /usr/local/Cellar/rethinkdb/2.3.6/bin/rethinkdb_data/tmp
Initializing directory /usr/local/Cellar/rethinkdb/2.3.6/bin/rethinkdb_data
Running rethinkdb 2.3.6 (CLANG 8.0.0 (clang-800.0.42.1))...
Running on Darwin 15.6.0 x86_64
Loading data from directory /usr/local/Cellar/rethinkdb/2.3.6/bin/rethinkdb_data
warn: Cache size does not leave much memory for server and query overhead (available memory: 1053 MB).
warn: Cache size is very low and may impact performance.
Listening for intracluster connections on port 29015
Listening for client driver connections on port 28015
Listening for administrative HTTP connections on port 8080
Listening on cluster addresses: 127.0.0.1, ::1
Listening on driver addresses: 127.0.0.1, ::1
Listening on http addresses: 127.0.0.1, ::1
To fully expose RethinkDB on the network, bind to all addresses by running rethinkdb with the `--bind all` command line option.
Server ready, "zewdeMacBook_Pro_local_0ez" 5a3dd5c0-0f4e-40bb-83cb-8a94f989852c

 

一切都准备好了,我们来看看stf的运行原理是什么?

require('../lib/cli/please') //很多人会好奇,nodejs上来就这么一出是什么意思呢?
  • 模块是什么,为什么要用模块
  • 那么模块的查找流程是怎么样的?

1:其实这个就是nodejs模块机制,学习一门语言我们首先要思考的是为什么要引入模块机制,是为了解决哪些问题才这么设计的,如果是你你要怎么优化呢?带着这个问题我们想下模块是为了让开发边的简单将一些独立的逻辑封装成一个模块可以复用。

2:开发的过程中我们经常使用到require方法,但是可能会忽略它的内部细节,到底require是怎么查找到对应的模块的呢?其实require的时候node面对不同的路径标识会有不同的处理细节,下面我们分别来说明,1:内置模块,像http, net, stream 这样的模块,node早已经将这样的模块编译成二进制模块,在Node启动的时候就已经常驻内存中了,所以就省略了(1):查找定位文件,(2):编译文件的步骤,同时这样的文件加载也是最快的,用数据结构的思维就是空间换时间嘛,2:绝对路径或者相对路径模块,在标识路径符的时候如果标识符前面有 ./ 或 .. 或者 / 这样的字符,那么就会被当作相对路径或者是绝对路径,Node.js对原生模块和文件模块都进行了缓存,于是在第二次require时,是不会有重复开销的。其中原生模块都被定义在lib这个目录下面,文件模块则不定性。

比如说我们定义一个circle.js

var PI = Math.PI;
exports.area = function (r) {
    return PI * r * r;
};
exports.circumference = function (r) {
    return 2 * PI * r;
};

然后在再相同文件夹的express.js中引用并且打印一下,就会看到

var circle = require('./circle.js');
console.log('The area of a circle of radius 4 is ' + circle.area(4));

打印结果

The area of a circle of radius 4 is 50.26548245743669
可以看出这个路径是相对的路径,那么如果我们在这个目录下没有这个js文件呢

如果我把circle.js文件放到同目录test文件夹下呢,执行命令报错是:

Error: Cannot find module './circle.js'
    at Function.Module._resolveFilename (module.js:548:15)
    at Function.Module._load (module.js:475:25)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/zew/mygit/minicap/example/express.js:16:14)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)

如果换成require('./test/circle.js')就执行成功了

var circle = require('./test/circle.js');
console.log('The area of a circle of radius 4 is ' + circle.area(4));

The area of a circle of radius 4 is 50.26548245743669

如果这些都清楚了那么下面这个带便什么意思呢?

var circle = require('./');
console.log('The area of a circle of radius 4 is ' + circle.area(4));

执行一遍:

Error: Cannot find module './'
    at Function.Module._resolveFilename (module.js:548:15)
    at Function.Module._load (module.js:475:25)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/zew/mygit/minicap/example/express.js:16:14)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)

如果我们在同目录下放一个index.js文件,且文件内容如下的话

nodejs的部署的问题

打印结果:The area of a circle of radius 4 is 51.26548245743669

由此我们可以看出如果require('./'),则表示在同目录下寻找一个index.js文件模块,加载进来,否则就报错。

 

知道了这个模块的机制以后我们就知道stf在模块里加载了please模块

require('../lib/cli/please')

nodejs的部署的问题

那么please.js做了什么呢?其实他也是加载了另外两个模块,上面那个方式相对路径加载很容易理解,下面看到了require('./'),其实就是把同目录那个index.js加载进去,由上图可以看出旁边恰好就有一个index.js文件。

 

下面我们来讲讲yargs模块是干什么的, 介绍这个之前我们先只管的感受一下脚本的书写。

比如我写了一个mytest1文件,内容:

如果内容是:
#!/usr/bin/env node
console.log('hello world');

输入mytest1
打印结果是:hello world

#!/usr/bin/env node
console.log('hello ', process.argv);

输入:mytest1
打印结果是:
hello  [ '/usr/local/bin/node', '/Users/zew/mygit/autod/bin/mytest1' ]

那么这个process.argv的参数是[x,x]格式的

如果在命令输入
mytest1 ew

则打印的是:

hello  [ '/usr/local/bin/node',
  '/Users/zew/mygit/autod/bin/mytest1',
  'ew' ]

如果在命令输入
mytest1 ew ew2

则打印:
 hello  [ '/usr/local/bin/node',
  '/Users/zew/mygit/autod/bin/mytest1',
  'ew',
  'ew2' ]



而 yargs 模块能够解决如何处理命令行参数。它也需要安装。

yargs 模块提供 argv 对象,用来读取命令行参数。请看改写后的 hello 。

如果是
#!/usr/bin/env node
var argv = require('yargs').argv;

console.log('hello ', argv);

命令:mytest1
打印结果:
hello  { _: [], '$0': 'mytest1' }

如果是命令:mytest1 --name=tom
打印结果:hello  { _: [], name: 'tom', '$0': 'mytest1' }

如果是命令是:mytest1  --name tom
打印结果是:hello  { _: [], name: 'tom', '$0': 'mytest1' }






从上面两个操作可以看出yargs 可以上面的结果改为一个对象,每个参数项就是一个键值对。

可以使用 alias 方法,指定 name 是 n 的别名。

比如说刚刚

#!/usr/bin/env node
var argv = require('yargs').alias('name', 'zew').argv;

console.log('hello ', argv);

命令:mytest1  --name tom


打印结果:hello  { _: [], name: 'tom', zew: 'tom', '$0': 'mytest1' }
可以看出这里面有两个都是tom的,其实意思就是制定“zew”这个键值对是“name”的别名,那么我们打印一下这两个结果试试:

代码
#!/usr/bin/env node
var argv = require('yargs').alias('name', 'zew').argv;

console.log('hello ', argv);
console.log('hello ', argv.name);
console.log('hello ', argv.zew);


执行命令:mytest1  --name tom

打印结果:
hello  { _: [], name: 'tom', zew: 'tom', '$0': 'mytest1' }
hello  tom
hello  tom






如果将 argv.name 改成 argv.n,就可以使用一个字母的短参数形式了。

#!/usr/bin/env node
var argv = require('yargs').argv;

console.log('hello ', argv);

命令: mytest1  -n tom

打印结果:
hello  { _: [], n: 'tom', '$0': 'mytest1' }

那么有的人会好奇难道就只能是n或者name吗,其实当然不是他的意思就是如果是超过一个字符的话就用--x,如果是一个字符的话可以用-x或者--x,这里的n就是一个,name就是多个。

那么我们换一个试试

#!/usr/bin/env node
var argv = require('yargs')
  .argv;

console.log('hello ', argv);

命令:mytest1  --adsd tom
打印结果是:
hello  { _: [], adsd: 'tom', '$0': 'mytest1' }

如果是随便起的一个a呢
比如命令: mytest1  -a tom
打印结果:hello  { _: [], a: 'tom', '$0': 'mytest1' }

如果是命令:mytest1  --a tom

打印结果是:hello  { _: [], a: 'tom', '$0': 'mytest1' }


那么命令如果是:mytest1  -sdfsdf tom
打印结果:
hello  { _: [],
  s: [ true, true ],
  d: [ true, true ],
  f: [ true, 'tom' ],
  '$0': 'mytest1' }

argv 对象有一个下划线(_)属性,可以获取非连词线开头的参数。

yargs 模块还提供3个方法,用来配置命令行参数。

  • demand:是否必选
  • default:默认值
  • describe:提示

这三个参数是什么意思呢?

#!/usr/bin/env node
var argv = require('yargs')
  .demand(['n'])
  .default({n: 'tom'})
  .describe({n: 'your name'})
  .argv;

console.log('hello ', argv.n);

命令:mytest1
打印:
hello  tom

意思就是上面代码指定 n 参数不可省略,默认值为 tom,并给出一行提示,而不是像以前那种mytest1 -n tom

options 方法允许将所有这些配置写进一个对象。这个是什么意思呢?

#!/usr/bin/env node
var argv = require('yargs')
  .option('n', {
    alias : 'name',
    demand: true,
    default: 'tom',
    describe: 'your name',
    type: 'string'
  })
  .argv;

console.log('hello ', argv);

命令:mytest1
打印:hello  { _: [], n: 'tom', name: 'tom', '$0': 'mytest1' }
它的意思就是把多个参数配置到一个对象里。

有时,某些参数不需要值,只起到一个开关作用,这时可以用 boolean 方法指定这些参数返回布尔值。

#!/usr/bin/env node
var argv = require('yargs')
  .boolean(['n'])
  .argv;

console.log('hello ', argv);

命令:
mytest1

打印结果:
hello  { _: [], n: false, '$0': 'mytest1' }
可以看出n参数这里就是一个默认的false值

如果命令是:mytest1 -n
打印结果:hello  { _: [], n: true, '$0': 'mytest1' }//n参数为true


如果命令是:mytest1 -n ded
打印结果是:hello  { _: [ 'ded' ], n: true, '$0': 'mytest1' }//n参数也为true

可以看出只要命令中包含了-n参数为true啦


boolean 方法也可以作为属性,写入 option 对象。

#!/usr/bin/env node
var argv = require('yargs')
  .option('n', {
    boolean: true
  })
  .argv;

console.log('hello ', argv.n);

命令:mytest1
打印结果:
hello  { _: [], n: false, '$0': 'mytest1' }

另外yargs 模块提供以下方法,生成帮助信息

  • usage:用法格式
  • example:提供例子
  • help:显示帮助信息
  • epilog:出现在帮助信息的结尾
#!/usr/bin/env node
var argv = require('yargs')
  .option('f', {
    alias : 'name',
    demand: true,
    default: 'tom',
    describe: 'your name',
    type: 'string'
  })
  .usage('Usage: hello [options]')
  .example('hello -n tom', 'say hello to Tom')
  .help('h')//显示帮助信息
  .alias('h', 'help')//这个就是输入mytest1 h和mytest1  help效果是一样的
  .epilog('copyright 2015')//出现在帮助信息的结尾
  .argv;

console.log('hello ', argv.n);



命令:mytest1 -h
打印结果:
Usage: hello [options]

Options:
  -f, --name  your name                     [string] [required] [default: "tom"]
  -h, --help  Show help                                                [boolean]

Examples:
  hello -n tom  say hello to Tom

copyright 2015

yargs 模块还允许通过 command 方法,设置 Git 风格的子命令。

#!/usr/bin/env node
var argv = require('yargs')
  .command("morning", "good morning", function (yargs) {
    console.log("Good Morning");
  })
  .command("evening", "good evening", function (yargs) {
    console.log("Good Evening");
  })
  .argv;

console.log('hello ', argv.n);

命令:
 mytest1 morning

打印:
Good Morning
hello  undefined

命令:mytest1 morning -n tom

打印:Good Morning
hello  tom

命令: mytest1 evening

打印:Good Evening
hello  undefined

可以看出我们可以自定义一些命令名称进行输出

 

好啦,基本语法我们讲完了,接着看

var yargs = require('yargs')
var Promise = require('bluebird')

Promise.longStackTraces()

var _argv = yargs.usage('Usage: $0 <command> [options]')
  .strict()
  .command(require('./api'))
  .command(require('./app'))
  .command(require('./auth-ldap'))
  .command(require('./auth-mock'))
  .command(require('./auth-oauth2'))
  .command(require('./auth-openid'))
  .command(require('./auth-saml2'))
  .command(require('./device'))
  .command(require('./doctor'))
  .command(require('./generate-fake-device'))
  .command(require('./local'))
  .command(require('./log-rethinkdb'))
  .command(require('./migrate'))
  .command(require('./notify-hipchat'))
  .command(require('./notify-slack'))
  .command(require('./poorxy'))
  .command(require('./processor'))
  .command(require('./provider'))
  .command(require('./reaper'))
  .command(require('./storage-plugin-apk'))
  .command(require('./storage-plugin-image'))
  .command(require('./storage-s3'))
  .command(require('./storage-temp'))
  .command(require('./triproxy'))
  .command(require('./websocket'))
  .demandCommand(1, 'Must provide a valid command.')
  .help('h', 'Show help.')
  .alias('h', 'help')
  .version('V', 'Show version.', function() {
    return require('../../package').version
  })
  .alias('V', 'version')
  .argv

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章: