看一下sails的特性
安装
npm install -g sails
很简单就可以安装了。
看一下它的帮助
sails --help
Usage: sails [command]
Commands:
version
lift [options]
new [options] [path_to_new_app]
generate
console
consle
consloe
c
www
debug
configure
help
*
Options:
-h, --help output usage information
-v, --version output the version number
--silent
--verbose
--silly
这是它的cli的全部功能
- new 是根据模板创建项目
- generate 是教授叫生成
- lift 是启动服务器
了解这3个基本上就可以了。
如果你想进一步了解,可以继续看help
sails lift --help
Usage: lift [options]
Options:
-h, --help output usage information
--prod
--port [port]
创建一个项目看看
sails new helloworld
cd helloworld
sails lift
我们需要看一下它的目录结构
➜ helloworld tree -L 2
.
├── Gruntfile.js
├── README.md
├── api
│ ├── controllers
│ ├── models
│ ├── policies
│ ├── responses
│ └── services
├── app.js
├── assets
│ ├── favicon.ico
│ ├── images
│ ├── js
│ ├── robots.txt
│ ├── styles
│ └── templates
├── config
│ ├── blueprints.js
│ ├── bootstrap.js
│ ├── connections.js
│ ├── cors.js
│ ├── csrf.js
│ ├── env
│ ├── globals.js
│ ├── http.js
│ ├── i18n.js
│ ├── local.js
│ ├── locales
│ ├── log.js
│ ├── models.js
│ ├── policies.js
│ ├── routes.js
│ ├── session.js
│ ├── sockets.js
│ └── views.js
├── node_modules
│ ├── ejs -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/ejs
│ ├── grunt -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt
│ ├── grunt-contrib-clean -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-clean
│ ├── grunt-contrib-coffee -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-coffee
│ ├── grunt-contrib-concat -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-concat
│ ├── grunt-contrib-copy -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-copy
│ ├── grunt-contrib-cssmin -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-cssmin
│ ├── grunt-contrib-jst -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-jst
│ ├── grunt-contrib-less -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-less
│ ├── grunt-contrib-uglify -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-uglify
│ ├── grunt-contrib-watch -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-contrib-watch
│ ├── grunt-sails-linker -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-sails-linker
│ ├── grunt-sync -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/grunt-sync
│ ├── include-all -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/include-all
│ ├── rc -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/rc
│ ├── sails -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails
│ └── sails-disk -> /Users/sang/.nvm/v0.10.38/lib/node_modules/sails/node_modules/sails-disk
├── package.json
├── tasks
│ ├── README.md
│ ├── config
│ ├── pipeline.js
│ └── register
└── views
├── 403.ejs
├── 404.ejs
├── 500.ejs
├── homepage.ejs
└── layout.ejs
36 directories, 29 files
目录说明
app.js是入口,和express类似,但你看不到任何express的影子,它把东西都抽象到module里了,一般人看起来是有点难于理解的。
自己的代码要写在api目录里
├── api
│ ├── controllers
│ ├── models
│ ├── policies
│ ├── responses
│ └── services
而rails是在app目录里。sails放到api里,可能是现在写api比较多,2点好处
- 前后端分离
- 为移动端提供api
这命名也是比较好理解的
- controllers和models是mvc里的m和c
- services 一般是多model相关的业务操作,它只在controller里调用
- responses比较有意思,它实际上是给res服务器响应对象增加方法,比如定义个aaa方法,你就可以res.aaa()了,对于扩展res是有好处的,算一个小亮点
- policies 是权限控制部分,说白了也还是中间件,config.policies.js里声明权限,相信会玩死很多人,简单的acl还不如自己写
至此,核心的特性已经从目录看的差不多了。
node_modules
一般项目里做模块依赖,很烦。
rails里的bundle install也很烦。。。
但是sails利用软连接,把依赖的模块放到自己的npm安装目录,然后创建软连接,这样就可以在sails new之后,里面启动服务器,无需安装任何模块,这一点还是值得借鉴的
views
目录和express一样,它的默认模板引擎是ejs
/**
* View Engine Configuration
* (sails.config.views)
*
* Server-sent views are a classic and effective way to get your app up
* and running. Views are normally served from controllers. Below, you can
* configure your templating language/framework of choice and configure
* Sails' layout support.
*
* For more information on views and layouts, check out:
* http://sailsjs.org/#!/documentation/concepts/Views
*/
module.exports.views = {
engine: 'ejs',
layout: 'layout',
partials: false
};
各取所需吧,爱用啥用啥,比如又要掀起一场口水打仗了。。。。
assets
asset pipeline其实最早也是rails里的概念,可以将JS和CSS合并和压缩
打开package.json
"grunt": "0.4.2",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-coffee": "~0.10.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-cssmin": "~0.9.0",
"grunt-contrib-jst": "~0.6.0",
"grunt-contrib-less": "0.11.1",
"grunt-contrib-uglify": "~0.4.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-sails-linker": "~0.9.5",
"grunt-sync": "~0.0.4",
从这里基本可以看出它的功能
- js支持coffeescript
- css支持less
- 常用grunt操作,clean是清理,concat是合并,copy是复制,cssmin是压缩css,uglify是压缩js,watch是检测文件变动,sync应该是类似livereload之类的模块
后来发现它的文档里也有
Here are a few things that the default Grunt configuration in Sails does to help you out:
- Automatic LESS compilation
- Automatic JST compilation
- Automatic Coffeescript compilation
- Optional automatic asset injection, minification, and concatenation
- Creation of a web ready public directory
- File watching and syncing
- Optimization of assets in production
多了一个jst编译,是grunt-contrib-jst
做的事儿,其他大致一样
默认它是没有grunt-cli模块的,需要自己安装
npm install -g grunt-cli
然后执行grunt命令
➜ helloworld grunt
Running "clean:dev" (clean) task
Cleaning .tmp/public...OK
Running "jst:dev" (jst) task
>> Destination not written because compiled files were empty.
Running "less:dev" (less) task
File .tmp/public/styles/importer.css created: 0 B → 619 B
Running "copy:dev" (copy) task
Copied 3 files
Running "coffee:dev" (coffee) task
Running "sails-linker:devJs" (sails-linker) task
padding length 4
File "views/layout.ejs" updated.
Running "sails-linker:devStyles" (sails-linker) task
padding length 4
File "views/layout.ejs" updated.
Running "sails-linker:devTpl" (sails-linker) task
padding length 4
File "views/layout.ejs" updated.
Running "sails-linker:devJsJade" (sails-linker) task
Running "sails-linker:devStylesJade" (sails-linker) task
Running "sails-linker:devTplJade" (sails-linker) task
Running "watch" task
Waiting...
这里就是grunt的tasks了,没有啥可说的,我不是很喜欢grunt,我更喜欢gulp,sails默认是grunt,但文档里有有gulp版本的,可以去试试
另外要说明的是上线的时候,静态资源处理
- 要么cdn
- 要么nginx反向代理
这东西的价值就非常好了。
config
太多了,蛋疼。。。。
console
sails console
是通过命令行来处理数据的,一般简单测试会用
测试模型以及orm方法还是很爽的
来个例子玩玩吧
生成controller玩玩
sails generate controller comment create destroy tag like
生成的代码
/**
* CommentController
*
* @description :: Server-side logic for managing comments
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
module.exports = {
/**
* `CommentController.create()`
*/
create: function (req, res) {
return res.json({
todo: 'create() is not implemented yet!'
});
},
/**
* `CommentController.destroy()`
*/
destroy: function (req, res) {
return res.json({
todo: 'destroy() is not implemented yet!'
});
},
/**
* `CommentController.tag()`
*/
tag: function (req, res) {
return res.json({
todo: 'tag() is not implemented yet!'
});
},
/**
* `CommentController.like()`
*/
like: function (req, res) {
return res.json({
todo: 'like() is not implemented yet!'
});
}
};
这种意义不是很大。。。
生成模型
sails generate model user name:string email:string password:string
基于Waterline的,除了可以适配多个db外,没看出啥特别的,写法一点也不好
如果直接生成api呢
➜ helloworld sails generate api sssd sdf jklsdf werjk jlksd sd
info: Created a new api!
擦,生成SssdController,每一个属性生成一个方法
Sssd model里只有属性对。。。。哭了
另外把路由配置在config.routes.js里,声明式做法也蛮蛋疼的,太麻烦了。。。。
另外说基于blueprints的restful api,恕我愚钝,没太看明白
难道
sails generate api dentist
所有的代码都隐掉,你无法做任何修改么?
orm
- 强大的关联
- console 调试
如果一个orm,在js的语法下,兼容Any database,你说能不恶心么?把nosql和rdbms搞到一起,Waterline也是醉了。。。
他们还自己吹牛
- activerecord
- hibernate
类的。。。
凑合用吧
总结
sails能做到这样已经很不错了,有很多点都是和rails概念类似,也很用心
但出于js语法以及各种db等,还是有很多难受的地方
项目选型思考
- 如果有熟悉rails思想的人可以考虑用
- 如果有大牛可以用
- 如果是新手或者无人解决框架问题,还是老老实实的express吧
全文完
欢迎关注我的公众号【node全栈】
sails 很不错啊~
@i5ting 这几点捣鼓sails 框架,发现还是很多蛋疼不灵活的地方,决定不用了,自己基于express搭一套简单的mvc框架。
因为后台项目中需要orbc 权限管理,用sailsjs 的话 有一个sails-permissions, 但是这个项目还不完善。自己集成node_acl到sailsjs里面又各种 不便,所以决定不用了~~~~(>_<)~~~~
@jerrywu55 分享一下 rbac
我之前也研究了一段时间这个框架,sailsjs应该是node.js的web server库里面包含最完整解决方案的一个框架。 基于blueprints的restful api 是sailsjs的一个最大特点,其实就是默认下,create的api里面,自动生成rest的crud的router,并且不需要写一句代码,酒会自动操作data(当然自己要写一些权限相关的policy),并且也支持rest的多表关联的数据,比如:post /model/:id/associationModel 假如body的id已存在,就保存关系,如果不存在,则创建associationModel数据后,再保存关系,这些都是现成的,不需要自己实现。
@hcnode 多表关联是亮点
但是自动生成rest的crud的router,并且不需要写一句代码
是有问题的,我不能一点也不该代码的,隐藏的东西(黑魔法)会让人很郁闷,新人更郁闷
@jerrywu55 我觉得还是挺灵活的,这个框架的机制尽量将所有功能都以config、或者hook等各种插件方式提供给开发者,权限管理就用它的polices方式就够用了,它的polices配置可以是多种形式配置,你想灵活一点,就用配置成一个controller的方法,运行时判断
@hcnode 恩,是的
我说的是,它一行代码不写就可以生成restful api(是在它的库里实现的),我如果想改里面的代码怎么办?
@i5ting 嗯,我说的是默认情况下,你可以有很多方式修改的,比如新建controller对应的方法,就会覆盖它的默认方法,或者在model的before、after注入事件中加入自己代码(比如注册用户时修改password属性对密码加密),或者也可以写自己的hook插件,覆盖它的router
@hcnode 哦,秒懂~~,哈哈,覆盖还是比较麻烦的,O(∩_∩)O谢谢
@i5ting 不客气哈,因为它的文档写的很好,我看得很舒服,所以我之前基本把它的文档看了一遍,然后自己试做了一个小应用。 另外我还写了一个叫deep-blueprint的hook,因为他的blueprint最多只能生成两层model的router,我改了一下,可以生成多级的router,比如:/users/:userid/projects/:projectid/todos/:todoid/comments/:commentid,并提供crud操作,并自动对层级关系验证。
为什么还能看到grunt,说好的gulp呢?
我不想用他的ORM 怎么破?
@hades 不想用就干脆用express或koa,sails 、django这类框架的重要价值(也是束缚)就是在他们的ORM上
@SoaringTiger 不喜欢他的ORM,自己弄express这类东西,又要作好多事。
Salils还算挺整体的
@hades thinkjs,值得你拥有
挺喜欢Sails,可能是过去有Rails背景吧。但是现在用了Mongoose,和Sails的ORM不兼容,所以一直也没用。Express挺好,多用一个框架,多很多学习和维护成本。
@hcnode post /model/:id/associationModel这种传参数是怎么搞的?
@shinygang 我写个简单的列子吧,创建sails app,然后按照这里上面的例子创建这两个api
sails new apptest
cd apptest
sails generate api user
sails generate api pet
分别修改/api/models/User.js 和/api/models/Pet.js替换成上面官方文档的的代码,然后执行
sails lift
1.创建一个pet:
2.创建一个user:
3.post /user/2创建的user返回的id/pets,参数id为1创建pet的id
4.或者你可以创建一个全新的pet
以上结果返回,会自动populate所有association的field,也就是会自动查询关联的表,并在结果里面返回。 sails的populate很方便,不需要自己查询关联表,并且支持传入关键字、分页的方式查询关联表。
@hcnode 谢谢指导,懂了,话说你这http请求工具可以分享下
@hcnode 老兄,再请教一下: 我想添加一个已经存在的photo到product上,这样操作怎么不行?数据库我用的mongo
@shinygang 我试过mongo可以,无论参数是id还是_id都可以
@hcnode 能把deep-blueprint分享出来学习学习不?
@cnwang sails-hook-deepblueprints 花了两天时间重新整理一下,并写了一个sample
用前想想怎么解决并发问题,没有提供数据锁,transaction
也难用的一逼, lock
数据也没有方法提供,感觉sails的model如果换成sequelize
用起来也许会好很多
@i5ting 厉害