Python 2.7;.Net Framework 2 或 3;Visual Studio 2005 或更高。
按照 redis 官网相关页面 里的说明下载、安装、运行。
安装运行之。
使用命令行或图形界面软件打开 mysql ,在里面建立数据库名为 ReactWebNative8Koa 。
将记录着各种密码、端口等信息的文件从 instances/config.example.js
复制为 instances/config.js
中,并根据自己实际的密码、端口号等信息进行修改。
从 nodejs 官网 下载安装。
如果是 Linux 用户,需要手动将 node 安装位置的 bin
目录添加到 $PATH
中。
为避免后续执行 npm install
时因网络问题导致的下载失败,最好是配置一下镜像:
npm config set registry https://registry.npm.taobao.org
在项目根目录中运行如下命令会把包安装到 node_modules/
中:
npm install
有些 nodejs 版本可能需要这样才能顺利安装:
npm install --legacy-peer-deps
npm install -g supervisor
目前上传图片生成缩略图,需要依赖 imagemagick 和 ffmpeg
如果是阿里服务器 ubuntu 版本的话,需要先增加更新源
sudo apt-add-repository ppa:mc3man/trusty-media
sudo apt-get update
sudo apt-get install ffmpeg
imagemagick 安装步骤:
sudo apt-get install imagemagick
ffmpeg 安装步骤:
sudo apt-get install ffmpeg
执行 convert -v 和 ffmpeg -v,确认是否安装成功。
npm install react-native-cli -g
创建数据库登录mysql,使用命令行创建数据库
CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
根据实际情况修改 models/migrate.js
文件内最后一个 co()
调用函数中的内容,开发阶段默认为调用 development()
函数,然后运行如下命令:
models/migrate.js
如果是开发阶段需要一个崭新的数据库或是产品阶段,则使用如下命令
models/migrate.js -p
-p
参数会删除原有的数据库并建立一个新的。
后续代码修改,如与数据库中具体数据相关,则需相应修改 models/migrate.js
。
现在 ACL 已经全局保护 router 下面的所有 URL ,当新增一个 URL 时需要做如下操作,否则会被ACL拦截而出现 403 错误:
- 情况1. 若一个 URL ,有的 role 可以访问,有的禁止,请添加入 b_module ,并在 b_role_module 里把这些 URL 的权限赋 值给有权限的 role
- 情况2. 个别 URL 比如登陆功能,根路径等,无需 ACL 保护的,请把代码移至 router-noAcl 目录内
- 情况3. 个别 URL 比如后台测试接口等,为调试方便,希望 curl 可以直接访问,可以先加入 b_module 数据表内, name 取名 为 public ,则所有用户(包括未登录)都可以访问
如还是无法访问,可能需要在浏览器中清除下 cookie 。
在项目根目录中简单使用如下命令即可运行:
DEBUG=true node index.js
或是使用 package.json 中的 start 脚本启动:
npm start
这里的 start 脚本实际上就是 DEBUG=true FLUSHCACHE=N ALIPAY=N supervisor -i app,web,index.web.js,build index.js
,也就是用 supervisor 监控着,一旦有某个源代码修改了,会自动重启后端,这样就很方便于我们修改调试代码了。 DEBUG=true
的调试方式详见 debug 模块的介绍。这里直接让 start 脚本作为调试用途,是因为真正的发布版本我们会用下面提到的 pm2 来启动。
注: package.json 中的脚本,除了 start 和 test 可以直接加 npm
前缀来启动,其它脚本需要加 npm run
前缀。
在 http://0.0.0.0:8765 上注册登录 。
支持 android 、 ios 、 web 三种 APP 。
web 应用的调试用 npm run web
然后在浏览器中进入 http://localhost:3000 ,如果访问后端的话会产生跨域问题(因为 3000 和 8765 是不同的端口号,就被认为是不同的域),此时要么使用带有 DEBUG
环境变量比如 npm start
那样的脚本启动后端以便让 kcors
模块来开放跨域权限,要么(待想办法)在浏览器中进入 http://0.0.0.0:8765/ ;发布用 npm run build-web
生成 build/
中的文件,可以使用 npx http-server build
命令并用浏览器 http://127.0.0.1:8080 进行简单测试。
android 需提前按照 React 使用详解 “配置 Android 开发环境”, android 应用的调试用 npm run android
,如果运行后安装完 APK 就自动退出 npm run android
进程的,则还需手动运行 npm run rn
; 发布用 npm run build-android
生成 android/app/build/outputs/apk/
中的文件,发布用的签名方法详见 React 使用详解 中的“ release 离线打包 ”小节。
ios 需提前在 macOS 上按照 React 使用详解 “配置 iOS 开发环境”及参考“使用 Cocoapods 安装 iOS 第三方库”,先进入 ios/
目录运行 pod install
, ios 应用的调试用 Xcode 打开 ios/ 目录中的 .xcworkspace
而非 .xcodeproj
。
代码默认情况下:
- debug 等级之上 log 的输出同步输出到文件和命令行窗口;
- debug 等级之上 log 的输出到文件 access.log ;
- error 等级之上 log 的输出到文件 error.log ;
大家可以用 logger.debug( … ) , logger.info( … ) , logger.error( … ) ,等方便调用; Bunyun 的调试等级从低到高依次为 trace(10) , debug(20) , info(30) , warn(40) , error(50) , fatal(60) ;
安装 bunyan
npm install -g bunyan
然后使用 npm start | bunyan
, 可以格式化输出 log ;
npm start | bunyan -L 按北京时间显示
npm start | bunyan -c 'this.phone == 13900000001' 按条件搜索
- 调试时,为了避免终端调试打印过多,可以用
npm start | bunyan –l ${level}
(终端只打印 ${level} 等级之上的信息); - 调试时,支持使用
GET '/api/v0001/control/dbglevel'
获得当前调试等级;支持POST /api/v0001/control/dbglevel [{ "dbgLevel" :${level}}]
动态调整 log 等级; - 发布时,只有把上述第一条规则改为
error
等级以上终端输出即可;
注: ${level} 为 trace|debug|info|warn|error|fatal;
trace:最低等级的调试打印,用于高频,冗余,内部的打印调试信息,默认关闭; debug:普通调试打印(建议少用),稳定发布版本后续也可能关闭; info:需要记录的调试打印,表达有完整的意义; warn:警告打印; error:错误打印; fatal:非常严重的错误打印; debug和info使用容易混淆,调试打印主要用trace,info,而建议debug少用; 判断debug与trace的区别大致是,debug不影响系统性能,可以跟踪问题持续打开一段时间,而trace可能引起大量的打印,而不建议长时间开启,会影响系统性能
KOA架构下引入koa-bunyan-logger, 每个网络请求有request日志包含用户名,手机号码和req-id,返回值400-499,打印等级为warn,500以上为error, 400以下为info;
若在router接口内打印请使用this.log.{dbgLevel}(...)
,log内将自动添加req-id(同一请求值唯一),若需添加用户信息可使用this.log.{dbgLevel}({user: this}, ...)
;
若在router接口外,可以使用log.{dbgLevel}(...)
;
除了用 console.log()
这种打印方式来进行调试外,也存在许多图形界面单步调试的方法,典型的是 node-inspector,首先用如下命令安装:
npm install -g node-inspector
然后先使用如下命令启动后端:
node --debug index.js
接着使用如下命令启动 node-inspector:
node-inspector --web-port 8081
事务处理回调函数成功结束,自动执行commit,执行报错则自动执行rollback; 需要人为rollback的情况下,throw new Error(‘ ErrorInfo ...’); 注意:为避免死锁,回调函数内的所有数据库操作,请带上{transaction: t}
yield sequelize.transaction(function (t) {
// chain all your queries here. make sure you return them.
// 或使用 return co(function * () { ... }) 或async function(){ await ...}
return User.create({
firstName: 'Abraham',
lastName: 'Lincoln'
}, {
transaction: t
})
.then(function (user) {
return user.setShooter({
firstName: 'John',
lastName: 'Boothe'
}, {
transaction: t
});
});
}).then(function (result) {
// Transaction has been committed
// result is whatever the result of the promise chain returned to the transaction callback
}).catch(function (err) {
// Transaction has been rolled back
// err is whatever rejected the promise chain returned to the transaction callback
});
需要人为根据逻辑,执行commit或rollback; 注意:使用try..catch...,捕获错误,程序执行结束不能遗漏执行rollback或commit;
var t = yield sequelize.transaction();
try{
var user = yield User.create({
firstName: 'Abraham',
lastName: 'Lincoln'
}, {
transaction: t
});
...
if (error) {
yield t.rollback();
return ;
}
yield t.commit();
}
catch(e) {
log.error(e);
yield t.rollback();
return;
}
结合以下命令提供的信息和general log和代码分析原因;
查看process:
show processlist\G;
查看process间等待关系:
SELECT r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id\G;
查看锁表情况:
select * from information_schema.INNODB_LOCKS\G
检查Innodb_row_lock状态变量来分析系统上的行锁的争夺情况
mysql> show global status like '%innodb%row%lock%';
参考http://blog.itpub.net/26506993/viewspace-2124488/
此时会打印出一个 URL 比如 http://127.0.0.1:8081/?port=5858 ,最后就是使用 Chrome 浏览器打开该 URL 就可以在一个功能强大、使用方便的网页界面中进行加断点、单步运行等常用调试方法了。
这里参考了 用node-inspector调试Node.js 一文。
参考 Chrome developer tool介绍(javascript调试) 一文即可。
基本操作是把 node.js 转换成系统启动时的服务,崩溃后也可以重新开始继续服务,这个可以使用 npm 包 pm2 来实现,详见 How To Set Up a Node.js Application for Production on Ubuntu 14.04 。简单来说,就是使用如下命令代替 npm start
来启动 app 服务器:
pm2 start index.js
使用 nginx 做为 web 服务器反向代理到 app 服务器,这样可以减轻 node.js 的负担,而且也方便做负载均衡。
参考了如下两篇文档
How To Set Up a Node.js Application for Production on Ubuntu 14.04
HARDENING NODE.JS FOR PRODUCTION PART 2: USING NGINX TO AVOID NODE.JS LOAD
以及其它一些网文,这里以 Ubuntu 为例进行部署说明。
在使用 sudo apt-get install nginx
命令安装好 nginx 后,首先使用 sudo rm /etc/nginx/sites-enabled/default
命令把原先这个软链接到 /etc/nginx/sites-available/default
文件从而占用着 80 端口的 nginx 示例网站的配置删除,这样释放出来的 80 端口就能用于我们实际的网站了。
然后在项目根目录下使用如下命令
sudo ln -s `readlink -f scripts/nginx.conf` /etc/nginx/sites-enabled/ReactWebNative8Koa
sudo mkdir -p /var/www/ReactWebNative8Koa/
sudo ln -s `readlink -f build/` /var/www/ReactWebNative8Koa/
来让我们的 scripts/nginx.conf
成为系统的 /etc/nginx/nginx.conf
所 include 的一部分。
最后使用如下命令重启 nginx 即可使用 scripts/nginx.conf
中 server_name
所示的网址进行访问了:
sudo service nginx restart
注:后续如果发现 nginx 真如 /etc/nginx/sites-available/default
里的注释所说无法在 https 情况下开启 gzip ,则可能需要关闭 /etc/nginx/nginx.conf
中的 gzip 及开启 index.js
中的 koa-compress
,但貌似 nginx 会自动忽视 koa-compress
的压缩成果,也许要用 gzip_static on;
并预先提供好 .gz
文件才行?
安装 eslint
npm install -g eslint
然后配合 .eslintrc.js
文件及下面提到的 Sublime Text 编辑器的 SublimeLinter-eslint 和 JsPrettier 插件,可以非常方便地避免一些常见 BUG。
最好的 javascript 的编辑器,收费的要数 webstorm 第一,免费的则是开源世界普遍使用的 Sublime Text 最强, 虽然 Sublime Text 能编辑的并不仅仅是 javascript 源代码。
具体 Sublime Text 及其强大插件比如 SublimeLinter-eslint 的安装方法,详见 Sublime Text 使用详解 。
- 普通文件权限为 644 ,可执行文件权限为 755 。
- 字符编码为 UTF-8。
- 换行符为 LF。 应用 Sublime Text 来保证,详见 Sublime Text 使用详解 中的“ 设置换行符为 LF ”小节。
- 行尾不要留有空白字符。应用 Sublime Text 来保证,详见 Sublime Text 使用详解 中的“自动删除行尾的空白字符(空格或制表符)”小节。
- 缩进为 4 个空格。应用 Sublime Text 来保证,详见 Sublime Text 使用详解 中的“ 转换 tab 为 space ”小节。
- 应用上文提到的 SublimeLinter-eslint 插件,这样除了可以自动提示比如忘了加逗号的错误,也可以自动提示 JavaScript 秘密花园 中提到的警告比如用
===
代替==
、绝对不要省略分号、绝对不要使用 eval 等等。 - 应用上文提到的 JsPrettier 插件,这样不用再争论哪种代码规范更合适了,直接用 prettier 格式化代码即可。
.eslintrc.js
未能覆盖的,详见 JavaScript编码规范 。- git 提交时的描述请参考 Commit message 和 Change log 编写指南 一文。
- 后端代码即使没有数据要返回,比如许多 POST 或 PUT 的 API ,也要在返回前赋值
this.body = {};
,否则有些浏览器会因为无法按照 JSON 格式去解析 body 而返回Uncaught (in promise) SyntaxError: Unexpected token O
的错误。 - 后端向前端错误提示: 偶尔会有在 errCode 所表示的国际化提示文字中添加变量的需求,此时需要添加一个与 errCode 平级的 keyWord 来表示变量,格式参照 keyWord: [['节目1', '节目2', '节目3'], ['屏幕1', '屏幕2', '屏幕3']] ,然后在
locale/zh-CN.js
中就可以用比如 x[1][0] 来代表 '屏幕1' 这个字符串变量,或是直接用 x[0] 来代表 '节目1, 节目2, 节目3' 这一整个字符串变量了。 - 生产环境的数据库字段操作,尽量规避字段的删除和重命名操作
对于 html 和 css 文件,参照原有代码的格式即可。
1.使用mysqldump 来备份数据和结构到sql文件(非必须,为安全起见),如下;
mysqldump -uroot -p123 -h 123.7.8.9 -P 8787 --routines --complete-insert=true --default-character-set=utf8 ReactWebNative8Koa_develop01 > ReactWebNative8Koa_develop01.sql
2.确保instance/config.js数据库配置正确,执行migrate.js;
node models/migrate.js
migrate.js将执行如下工作:
1)增加,删除表,同步表结构到最新; 2)增加记录和更改记录; 3}清空redis涉及ACL的KEY
3.若需要手动清空redis
默认本地执行:
redis-cli del `redis-cli keys "ReactWebNative8Koa//[0-9]*/[0-9]*"`
远端带密码执行:
redis-cli -h 127.0.0.1 -p 6379 -a '' del `redis-cli -h 127.0.0.1 -p 6379 -a '' -n 0 keys "ReactWebNative8Koa//[0-9]*/[0-9]*"`
-h: host
-p: port
-a: password
-n:database num