- 6.3.x
# 通过brew 安装
$ brew install redis
# 或者
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make
千万记住要配置redis本地访问
npm install -g gulp bower
npm install
bower install
注意:
- 执行npm install时,如果node-canvas安装失败,执行
xcode-select --install
export PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig
更多信息:
- 请安装 https://github.com/Automattic/node-canvas
- EI Capitan 下需要查看这条issue(Automattic/node-canvas#649)
$ sudo apt-get update
$ sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
# 默认开启 8000 端口
$ gulp
sudo apt-get update
sudo apt-get install imagemagick --fix-missing
cd $HOME/.ssh/
openssl genrsa -out server.pem 2048
openssl rsa -in server.pem -pubout -out server.pub
NODE_ENV=test gulp build --release # 测试环境编译
NODE_ENV=test pm2 start build/app.js --name "imota-test"
NODE_ENV=production gulp build --release # 发布环境编译
NODE_ENV=production pm2 start build/app.js --name "imota-prod"
或者
sh deploy/prod.sh
npm install -g commitizen
git message必须符合规范, 使用ghook限制,初次提交代码前,执行chmod +x validate-commit-msg.js
使用git commit
的地方用git cz
代替。
在app/views/
目录下新增一个ejs文件
app/views/new.ejs
<% layout('layout') -%>
<% title = 'new' %>
<% stylesheet('/css/new.css') -%>
<% script('/js/new.js') -%>
<div class="new">
<div class="content">
<h4>
This is new
</h4>
</div>
</div>
如果需要使用父模版,ejs文件头部加:<% layout('layout') -%>
如果有js文件,或者css文件,ejs文件头部加:<% script('/js/new.js') -%>
, <% stylesheet('/css/new.css') -%>
,同时,在public/js/
, public/css/
下创建js文件,和less文件。
为什么引用处使用css,而原文件是less?gulpfile中有一个task会把less文件编译为css放入项目运行目录下 build/public/css/
如果添加js文件,除了在public/js/
下创建js文件,还需要在gulpfile中定义js入口文件。
创建完页面后,需要加上对应的路由才可以访问到页面
两种方式:
- 在已有的路由文件中添加子路由,比如在
app/controllers/home.js
中添加一个url为/home/new/
,http method 为get
的路由,
router.get('/new/', async (req, res) => {
try {
const local = {message: 'new'};
res.render('new', local);
} catch (err) {
next(err);
}
});
在app/api/
目录下创建api文件,然后在app/config/express.js
中引用
import homeViewState from './homeViewState';
import user from './user';
import updateMobileState from './updateMobileState';
import updateEmailState from './updateEmailState';
import {combineReducers} from 'redux';
import newReducer from './new'; // 这里引入文件
export default combineReducers({
homeViewState, user, updateMobileState, updateEmailState,
newReducer: newReducer // 这里给reducer分配一个key,这个key之后可以在整个state中访问
});
这个时候,已经可以在整个app的state中访问到这个reducer了
- 在
public/views/
目录下创建一个view
import React, {Component, PropTypes} from 'react';
import { connect } from 'react-redux';
import {actions} from '../redux/newReducer';
const mapStateToProps = ({newReducer}) => ({
newReducer,
});
class NewView extends Component {
static propTypes = {
newEvent: PropTypes.func, // 可以在props中调用newReducer中的action
newReducer: PropTypes.object, // 可以在props中取到newReducer
};
render() {
return (
<div className="new-view">
{this.props.newReducer}
</div>
);
}
}
export default connect(
mapStateToProps,
actions,
)(NewView); // 这一步实现了view和reducer的绑定。
- 暴露路由,创建好了页面和reducer,还需要设置路由才能访问该页面
在public/js/routes/home.js
中设置路由
<Route path="/" component={CoreLayout}>
...
<Route path="/home/new" component={NewView} />
...
</Route>
注意,此处的路由都是在#后面的(.com/#/home/new),之所以这样是因为安卓微信不支持h5 history api,如果使用h5路由(.com/home/new)的话,需要在服务器端也做相应配置,
router.get('/home/*', async (req, res) => {
try {
res.render('index', {});
} catch (err) {
res.redirect('/login/');
}
});
这里,所有home开头的路由都会指向这个react-redux app入口页面。
参数:
- audios array 音频文件路径列表,例如:['1.mp3', '1.ogg', 'backup/1.mp3', 'backup/1.ogg']
- autoplay boolean 是否自动播放
- children jsx array 播放状态/非播放/错误状态的样子 可不填,不填则使用默认样式
示例: 使用默认样式
<AudioPlayer audios={audios} autoplay key={audios[0]}>
</AudioPlayer>
改变不同状态下的样式,这个时候播放器的样式完全取决于内容
<AudioPlayer audios={audios} autoplay key={audios[0]}>
<div className="sentence-text">
播放
</div>
<div className="sentence-text">
暂停
</div>
<div className="sentence-text">
出错啦!
</div>
</AudioPlayer>
参数:
- videos array 视频文件路径列表,例如:['1.mp4', '1.webm', 'backup/1.mp4', 'backup/1.webm']
- playing boolean 播放中
- onEnded func 播放结束的callback
示例:
<VideoPlayer playing={playing} videos={videos} onEnded={() => {console.log('ended')}} />
这个是用来获取微信签名的,把它作为一个reducer来使用
- 需要调用微信sdk的页面引入这个reducer,
- 在view constructor中调用fetchSignatureAsync
- 当wxsdk.signature有值的时候,即可调用微信sdk,使用全局变量
wx
调用微信sdk - 如果
wxsdk.noWechat
为true,则不在微信浏览器中,页面也要作出相应改动 - 获取签名失败的时候,
wxsdk.errMsg
有值,页面要作出相应改动
为了安全起见,只允许使用ssh tunnel,需要给我public key
ssh \
-L 27017:localhost:27017 \
-i ~/.ssh/id_rsa \
dbuser@121.201.28.101
ssh \
-L 6379:localhost:6379 \
-i ~/.ssh/id_rsa \
dbuser@121.201.28.101
测试环境连接localhost:27018/imota-cms-dev
该文档用于imota-cms
- node // 我们使用nvm来管理node版本
- mongo // 绑定到本地端口访问,提高安全性
- ffmpeg // https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
npm install gulp bower -g
npm install
- 创建.env文件
COOKIE_SECRET=c0272b28ce1b4de1d48898cf8eccd2dcca24c4adb5657edcabedfd6d32df667ec4cfe4b67447976a75cb0c45c0ce7f31ecf40a44226b9f6e3645188f545d8d4d
CLOUDINARY_URL=cloudinary://333779167276662:_8jbSi9FB3sWYrfimcl8VKh34rI@keystone-demo
npm start
(function() {
var cdnPath = 'http://7xrwtt.com1.z0.glb.clouddn.com';
var length = document.styleSheets.length;
var i = 0;
var sheet;
for (i = 0; i < length; i++) {
sheet = document.styleSheets[i];
if (sheet.href && sheet.href.indexOf('http://7xrwtt.com1.z0.glb.clouddn.com') === 0) {
var rules = sheet.rules ? sheet.rules : sheet.cssRules;
if (!rules) {
var link = document.createElement('LINK');
link.href = sheet.href.replace('http://7xrwtt.com1.z0.glb.clouddn.com', '');
link.type = 'text/css';
link.rel = 'stylesheet';
document.head.appendChild(link);
}
}
if (sheet.href && sheet.href.indexOf('https://o43236zpa.qnssl.com') === 0) {
var rules = sheet.rules ? sheet.rules : sheet.cssRules;
if (!rules) {
var link = document.createElement('LINK');
link.href = sheet.href.replace('https://o43236zpa.qnssl.com', '');
link.type = 'text/css';
link.rel = 'stylesheet';
document.head.appendChild(link);
}
}
}
})();
正式: learnwithimota.com 注意,正式和测试使用的都是真实数据库,本地开发使用的是测试数据库。
tailf /data/log/airlog.client.log-2016-05-22
weixin: {
appid: 'wx453346560ed6a84e',
secret: '2e1364c00766952f641b197b67dd3b9c',
},
http://tech.marry-me.today/wei-xin-ye-mian-kai-fa-de-na-xie-keng/