├── .gitignore ├── 2016-01 ├── hackathon-starter.md ├── inflected.md └── micro.md ├── 2016-02 ├── how2.md └── orchestrator.md ├── 2016-04 ├── nodejs-6.md ├── pageres.md ├── screenshot-output.png ├── screenshot.png └── strman.md ├── LICENSE ├── README.md ├── Why I Love Node.js: Promises, Express, and the CLI.md ├── examples └── mygulp │ ├── index.js │ ├── package.json │ └── task.js └── img └── wechat.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | 36 | myproject 37 | -------------------------------------------------------------------------------- /2016-01/hackathon-starter.md: -------------------------------------------------------------------------------- 1 | # 开源Nodejs项目推荐【Node.js web模板】:hackathon-starter 2 | 3 | 4 | hackathon-starter是github上一个star过万的项目,技术栈 5 | 6 | 后端 7 | 8 | - node/express 9 | - mongodb(mongoose) 10 | - mocha 11 | 12 | 算典型的MEAN架构(少angularjs),技术栈整体是比较经典的。参加[Node.js最新Web技术栈(2015年5月)](https://cnodejs.org/topic/55651bf07d4c64752effb4b1) 13 | 14 | 前端是传统web框架 15 | 16 | - bootstrap 17 | - jquery 18 | - sass 19 | 20 | 除了sass稍高级点,基本没什么难度。 21 | 22 | ## 源码 23 | 24 | A boilerplate for Node.js web applications http://hackathonstarter.herokuapp.com 25 | 26 | https://github.com/sahat/hackathon-starter 27 | 28 | ## 前置条件 29 | 30 | 安装 31 | 32 | - MongoDB 稳定版 33 | - Node.js 稳定版 34 | - nrm 切换npm源,加速安装npm模块 35 | 36 | 推荐的2个教程 37 | 38 | - [Getting Started With Node.js, Express, MongoDB.](http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/) 39 | - [Node.js and Express 101需要翻墙](https://www.youtube.com/watch?v=BN0JlMZCtNU) 40 | 41 | ## 安装 42 | 43 | Install via npm: 44 | 45 | ```bash 46 | # Get the latest snapshot 47 | git clone --depth=1 https://github.com/sahat/hackathon-starter.git myproject 48 | 49 | # Change directory 50 | cd myproject 51 | 52 | # Use taobao as npm Registry 53 | nrm use taobao 54 | 55 | # Install NPM dependencies 56 | npm install 57 | 58 | node app.js 59 | ``` 60 | 61 | 62 | ## 功能点 63 | 64 | - **本地授权** using Email and Password 65 | - **OAuth 1.0a 授权** via Twitter 66 | - **OAuth 2.0 授权** via Facebook, Google, GitHub, LinkedIn, Instagram 67 | - Flash notifications 68 | - MVC项目结构 69 | - Node.js 集群支持 70 | - Sass stylesheets (通过中间件自动编译) 71 | - Bootstrap 3 + Extra Themes 72 | - Contact Form (powered by Mailgun, Sendgrid or Mandrill) 73 | - **Account Management** 74 | - Gravatar 75 | - Profile Details 76 | - 修改密码 77 | - 忘记密码 78 | - 重置密码 79 | - Link multiple OAuth strategies to one account 80 | - 账户删除 81 | - CSRF保护 82 | - **API Examples**: Facebook, Foursquare, Last.fm, Tumblr, Twitter, Stripe, LinkedIn and more. 83 | 84 | ## 本地授权 85 | 86 | 87 | ## mongoose技巧 88 | 89 | ## 测试技巧 90 | 91 | ## OAuth 2.0 授权(使用passpord) 92 | 93 | ## Flash notifications 94 | 95 | 96 | ## 所谓的mvc 97 | 98 | ## 集群支持 99 | 100 | 101 | ## Sass stylesheets (通过中间件自动编译) 102 | 103 | 104 | 105 | 106 | ## 点评 107 | 108 | - 技术栈比较经典,传统,是学习MEAN比较好的入门教程 109 | - 代码和目录结构也比较简单,没有特殊的技巧,比如用户密码加盐处理、测试等都是正规做法 110 | - mongoose只有1个user model,是比较好的入门教材 111 | - 集成passport.js做oauth授权 112 | - 一些比较好的技巧,比如session,flash,sass中间件等 113 | 114 | 整体来说,是学习MEAN比较好一个不错的选择。但它的代码和目录结构等还不是特别好,这也算美中不足吧,真实项目不推荐这样写。 115 | 116 | 117 | 全文完 118 | 119 | 欢迎关注我的公众号【node全栈】 120 | 121 | ![node全栈.png](//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC) 122 | 123 | 124 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 -------------------------------------------------------------------------------- /2016-01/inflected.md: -------------------------------------------------------------------------------- 1 | # 开源Nodejs项目推荐【单词处理】:inflected 2 | 3 | 开发中,我们对于单词的处理是非常常见的,尤其是在写一些scaffold(脚手架)的时候 4 | 5 | 举个例子 6 | 7 | ``` 8 | rails g scaffold user name:string password:string 9 | ``` 10 | 11 | 这里的user是类名,比如生成model为User.js 12 | 13 | 那么你如何把user变成User呢? 14 | 15 | inflected便是做这个的库,他是[rails基础ActiveSupport](https://ihower.tw/rails4/activesupport.html)的nodejs版本。支持对单词的各种变化处理。 16 | 17 | 主要特性 18 | 19 | - 单数和复数转换 20 | - 驼峰,下划线,减号等转换 21 | - 对数据库表,主键等支持 22 | - 还有其他特性,如人性化、翻译等 23 | 24 | ## 源码 25 | 26 | https://github.com/martinandert/inflected 27 | 28 | A port of ActiveSupport's inflector to Node.js. 29 | 30 | ## 安装 31 | 32 | Install via npm: 33 | 34 | ```bash 35 | % npm install inflected 36 | ``` 37 | 38 | 39 | ## 用法 40 | 41 | The module exports an object with several utility functions. 42 | 43 | ```js 44 | var Inflector = require('inflected'); 45 | 46 | Inflector.pluralize('Category') // => 'Categories' 47 | ``` 48 | 49 | Here is the complete API reference: 50 | 51 | 52 | ### Inflector.pluralize 复数 53 | 54 | ```js 55 | string pluralize(string word[, string locale]) 56 | ``` 57 | 58 | Returns the plural form of the word in the string. 59 | 60 | If passed an optional `locale` parameter, the word will be pluralized using rules defined for that language. By default, this parameter is set to "en". 61 | 62 | ```js 63 | Inflector.pluralize('post') // => 'posts' 64 | Inflector.pluralize('octopus') // => 'octopi' 65 | Inflector.pluralize('sheep') // => 'sheep' 66 | Inflector.pluralize('words') // => 'words' 67 | Inflector.pluralize('CamelOctopus') // => 'CamelOctopi' 68 | Inflector.pluralize('ley', 'es') // => 'leyes' 69 | ``` 70 | 71 | 72 | ### Inflector.singularize 单数 73 | 74 | ```js 75 | string singularize(string word[, string locale]) 76 | ``` 77 | 78 | The reverse of `pluralize`, returns the singular form of a word in a string. 79 | 80 | If passed an optional `locale` parameter, the word will be singularized using rules defined for that language. By default, this parameter is set to "en". 81 | 82 | ```js 83 | Inflector.singularize('posts') // => 'post' 84 | Inflector.singularize('octopi') // => 'octopus' 85 | Inflector.singularize('sheep') // => 'sheep' 86 | Inflector.singularize('word') // => 'word' 87 | Inflector.singularize('CamelOctopi') // => 'CamelOctopus' 88 | Inflector.singularize('leyes', 'es') // => 'ley' 89 | ``` 90 | 91 | 92 | ### Inflector.camelize 驼峰式 93 | 94 | ```js 95 | string camelize(string term[, boolean uppercaseFirstLetter]) 96 | ``` 97 | 98 | By default, `camelize` converts strings to UpperCamelCase. If the second argument is set to `false` then `camelize` produces lowerCamelCase. 99 | 100 | ```js 101 | Inflector.camelize('foo_bar') // => 'FooBar' 102 | Inflector.camelize('foo_bar', false) // => 'fooBar' 103 | ``` 104 | 105 | As a rule of thumb you can think of `camelize` as the inverse of `underscore`, though there are cases where that does not hold: 106 | 107 | ```js 108 | Inflector.camelize(Inflector.underscore('SSLError')) //=> 'SslError' 109 | ``` 110 | 111 | ### Inflector.underscore 下划线式 112 | 113 | ```js 114 | string underscore(string camelCasedWord) 115 | ``` 116 | 117 | Makes an underscored, lowercase form from the expression in the string. 118 | 119 | ```js 120 | Inflector.underscore('FooBar') // => 'foo_bar' 121 | ``` 122 | 123 | As a rule of thumb you can think of `underscore` as the inverse of `camelize`, though there are cases where that does not hold: 124 | 125 | ```js 126 | Inflector.camelize(Inflector.underscore('SSLError')) //=> 'SslError' 127 | ``` 128 | 129 | 130 | ### Inflector.humanize 131 | 132 | ```js 133 | string humanize(string lowerCaseAndUnderscoredWord[, object options]) 134 | ``` 135 | 136 | Capitalizes the first word, turns underscores into spaces, and strips a trailing "_id" if present. 137 | 138 | Like `titleize`, this is meant for creating pretty output. 139 | 140 | The capitalization of the first word can be turned off by setting the `capitalize` option key to `false`. By default, this option is `true`. 141 | 142 | ```js 143 | Inflector.humanize('employee_salary') // => 'Employee salary' 144 | Inflector.humanize('author_id') // => 'Author' 145 | Inflector.humanize('author_id', { capitalize: false }) // => 'author' 146 | ``` 147 | 148 | 149 | ### Inflector.titleize 标题化 150 | 151 | ```js 152 | string titleize(string sentence) 153 | ``` 154 | 155 | Capitalizes all the words and replaces some characters in the string to create a nicer looking title. `titleize` is meant for creating pretty output. 156 | 157 | ```js 158 | Inflector.titleize('man from the boondocks') // => 'Man From The Boondocks' 159 | Inflector.titleize('x-men: the last stand') // => 'X Men: The Last Stand' 160 | Inflector.titleize('TheManWithoutAPast') // => 'The Man Without A Past' 161 | Inflector.titleize('raiders_of_the_lost_ark') // => 'Raiders Of The Lost Ark' 162 | ``` 163 | 164 | 165 | ### Inflector.tableize 表化 166 | 167 | ```js 168 | string tableize(string className) 169 | ``` 170 | 171 | Create the name of a table like Rails does for models to table names. This method uses the `pluralize` method on the last word in the string. 172 | 173 | ```js 174 | Inflector.tableize('RawScaledScorer') // => 'raw_scaled_scorers' 175 | Inflector.tableize('egg_and_ham') // => 'egg_and_hams' 176 | Inflector.tableize('fancyCategory') // => 'fancy_categories' 177 | ``` 178 | 179 | 180 | ### Inflector.classify 类名 181 | 182 | ```js 183 | string classify(string tableName) 184 | ``` 185 | 186 | Create a class name from a plural table name like Rails does for table names to models. 187 | 188 | ```js 189 | Inflector.classify('egg_and_hams') // => 'EggAndHam' 190 | Inflector.classify('posts') // => 'Post' 191 | ``` 192 | 193 | Singular names are not handled correctly: 194 | 195 | ```js 196 | Inflector.classify('business') // => 'Busines' 197 | ``` 198 | 199 | 200 | ### Inflector.dasherize 长划(减号) 201 | 202 | ```js 203 | string dasherize(string underscoredWord) 204 | ``` 205 | 206 | Replaces underscores with dashes in the string. 207 | 208 | ```js 209 | Inflector.dasherize('puni_puni') // => 'puni-puni' 210 | ``` 211 | 212 | 213 | ### Inflector.foreignKey 外键 214 | 215 | ```js 216 | string foreignKey(string className[, boolean separateClassNameAndIdWithUnderscore]) 217 | ``` 218 | 219 | Creates a foreign key name from a class name. `separateClassNameAndIdWithUnderscore` sets whether the method should put "_" between the name and "id". 220 | 221 | ```js 222 | Inflector.foreignKey('Message') // => 'message_id' 223 | Inflector.foreignKey('Message', false) // => 'messageid' 224 | ``` 225 | 226 | 227 | ### Inflector.ordinal 序数 228 | 229 | ```js 230 | string ordinal(object number) 231 | ``` 232 | 233 | Returns the suffix that should be added to a number to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th. 234 | 235 | ```js 236 | Inflector.ordinal(1) // => 'st' 237 | Inflector.ordinal(2) // => 'nd' 238 | Inflector.ordinal(1002) // => 'nd' 239 | Inflector.ordinal(1003) // => 'rd' 240 | Inflector.ordinal(-11) // => 'th' 241 | Inflector.ordinal(-1021) // => 'st' 242 | ``` 243 | 244 | 245 | ### Inflector.ordinalize 序数化 246 | 247 | ```js 248 | string ordinalize(object number) 249 | ``` 250 | 251 | Turns a number into an ordinal string used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th. 252 | 253 | ```js 254 | Inflector.ordinalize(1) // => '1st' 255 | Inflector.ordinalize(2) // => '2nd' 256 | Inflector.ordinalize(1002) // => '1002nd' 257 | Inflector.ordinalize(1003) // => '1003rd' 258 | Inflector.ordinalize(-11) // => '-11th' 259 | Inflector.ordinalize(-1021) // => '-1021st' 260 | ``` 261 | 262 | 263 | ### Inflector.inflections 264 | 265 | ```js 266 | Inflections inflections([string locale]) 267 | inflections([string locale], [function(Inflections) fn]) 268 | ``` 269 | 270 | A singleton instance of the internal Inflections class is yielded by this function, which can then be used to specify additional inflection rules. If passed an optional locale, rules for other languages can be specified. The default locale is "en". Only rules for English are provided by this library. 271 | 272 | ```js 273 | Inflector.inflections('en', function(inflect) { 274 | inflect.plural(/^(ox)$/i, '$1$2en'); 275 | inflect.singular /^(ox)en/i, '$1'); 276 | 277 | inflect.irregular('octopus', 'octopi'); 278 | 279 | inflect.uncountable('equipment', 'snow'); 280 | }); 281 | ``` 282 | 283 | New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the pluralization and singularization rules that is run. This guarantees that your rules run before any of the rules that may already have been loaded. 284 | 285 | 286 | ### Inflector.transliterate 转译 287 | 288 | ```js 289 | string transliterate(string sentence[, object options]) 290 | ``` 291 | 292 | Replaces non-ASCII characters with an ASCII approximation, or if none exists, a replacement character which defaults to "?". 293 | 294 | ```js 295 | Inflector.transliterate('Ærøskøbing') // => 'AEroskobing' 296 | ``` 297 | 298 | Default approximations are provided for Western/Latin characters, 299 | e.g, "ø", "ñ", "é", "ß", etc. 300 | 301 | This method is I18n-aware, so you can set up custom approximations for a locale. This can be useful, for example, to transliterate German's "ü" and "ö" to "ue" and "oe", or to add support for transliterating Russian to ASCII. 302 | 303 | In order to make your custom transliterations available, you must set them using the `approximate` helper function: 304 | 305 | ```js 306 | Inflector.transliterations('de', function(t) { 307 | t.approximate('ü', 'ue'); 308 | t.approximate('ö', 'oe'); 309 | }); 310 | ``` 311 | 312 | Now you can have different transliterations for each locale: 313 | 314 | ```js 315 | Inflector.transliterate('Jürgen') // => 'Jurgen' 316 | Inflector.transliterate('Jürgen', { locale: 'de' }) // => 'Juergen' 317 | ``` 318 | 319 | 320 | ### Inflector.parameterize 参数化 321 | 322 | ```js 323 | string parameterize(string sentence[, object options]) 324 | ``` 325 | 326 | Replaces special characters in a string so that it may be used as part of a 'pretty' URL. 327 | 328 | ```js 329 | Inflector.parameterize('Donald E. Knuth') // => 'donald-e-knuth' 330 | Inflector.parameterize('Donald E. Knuth', { separator: '+' }) // => 'donald+e+knuth' 331 | ``` 332 | 333 | 334 | 335 | 点评 336 | 337 | - api接口足够丰富,和ActiveSupport是一样的,相对比较成熟、规范 338 | - 遵循node的小而美哲学 339 | - 有spec.js和相关测试用例,作者还是比较专业的 340 | - 代码相对比较老,1年没有更新,但整体比较稳定,推荐使用 341 | 342 | 在编写各种生成器的时候,是一个不错的选择 343 | 344 | 345 | 全文完 346 | 347 | 欢迎关注我的公众号【node全栈】 348 | 349 | ![node全栈.png](//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC) 350 | 351 | 352 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 -------------------------------------------------------------------------------- /2016-01/micro.md: -------------------------------------------------------------------------------- 1 | # 开源Nodejs微服务项目推荐:micro 2 | 3 | https://github.com/zeithq/micro 4 | 5 | _**Micro —** Async HTTP microservices_ 6 | 7 | 8 | ## Features 9 | 10 | * **Easy**. Designed for usage with `async` and `await` ([more](https://jakearchibald.com/2014/es7-async-functions/)) 11 | * **Fast**. Ultra high performance (even JSON parsing is opt-in). 12 | * **Micro**. The whole project is ~100 lines of code. 13 | * **Agile**. Super easy deployment and containerization. 14 | * **Simple**. Oriented for single purpose modules (function). 15 | * **Explicit**. No middleware. Modules declare all dependencies. 16 | * **Standard**. Just HTTP! 17 | 18 | ## Example 19 | 20 | The following example `sleep.js` will wait before responding (without blocking!) 21 | 22 | ```js 23 | import { send } from 'micro'; 24 | import sleep from 'then-sleep'; 25 | export default async function (req, res) { 26 | await sleep(500); 27 | send(res, 200, 'Ready!'); 28 | } 29 | ``` 30 | 31 | To run the microservice on port `3000`, use the `micro` command: 32 | 33 | ```bash 34 | $ micro -p 3000 sleep.js 35 | ``` 36 | 37 | 点评 38 | 39 | - 技术栈比较潮,es7的async/await,性能会很好 40 | - 遵循node的小而美哲学 41 | - 文档,测试,代码都比较规范 42 | 43 | 在微服务架构的潮流里,是一个不错的选择 44 | 45 | 46 | 全文完 47 | 48 | 欢迎关注我的公众号【node全栈】 49 | 50 | ![node全栈.png](//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC) 51 | 52 | 53 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 -------------------------------------------------------------------------------- /2016-02/how2.md: -------------------------------------------------------------------------------- 1 | # 开源Node.js项目推荐:how2 2 | 3 | stackoverflow是程序员最常用的网站之一,它上面有非常多的问题以及解决方案。基本上除了google和github就得算stackoverflow了。 4 | 5 | 所以善用stackoverflow是程序员的基本素质之一。 6 | 7 | 另外terminal终端也是程序员最常用的,那么能不能再终端里查stackoverflow里的问题呢? 8 | 9 | 本次推荐就是这样的软件 10 | 11 | Node.js写的stackoverflow from the terminal开源项目:how2 12 | 13 | https://github.com/santinic/how2 14 | 15 | 16 | 17 | ## 安装 18 | 19 | ``` 20 | npm install -g how2 21 | ``` 22 | 23 | ## Example 24 | 25 | The following example `sleep.js` will wait before responding (without blocking!) 26 | 27 | ```js 28 | import { send } from 'micro'; 29 | import sleep from 'then-sleep'; 30 | export default async function (req, res) { 31 | await sleep(500); 32 | send(res, 200, 'Ready!'); 33 | } 34 | ``` 35 | 36 | To run the microservice on port `3000`, use the `micro` command: 37 | 38 | ```bash 39 | $ micro -p 3000 sleep.js 40 | ``` 41 | 42 | 点评 43 | 44 | - 技术栈比较潮,es7的async/await,性能会很好 45 | - 遵循node的小而美哲学 46 | - 文档,测试,代码都比较规范 47 | 48 | 在微服务架构的潮流里,是一个不错的选择 49 | 50 | 51 | 全文完 52 | 53 | 欢迎关注我的公众号【node全栈】 54 | 55 | ![node全栈.png](//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC) 56 | 57 | 58 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 -------------------------------------------------------------------------------- /2016-02/orchestrator.md: -------------------------------------------------------------------------------- 1 | # 开源Nodejs项目推荐gulp核心模块:Orchestrator 2 | 3 | ## Content 4 | 5 | - 为什么要介绍这个模块? 6 | - 简介和基本用法 7 | - 它是如何做到以最大并发执行的? 8 | - 作业依赖链是如何计算的? 9 | - 事件回调 10 | - 如何实现一个简易gulp? 11 | - 最后点评一下 12 | 13 | ## Why? 14 | 15 | gulp已经是nodejs用的最多,排名前10的著名模块了,而Orchestrator模块是gulp的核心模块,如果你也是gulp使用者,那么你有必要了解一下gulp的实现原理,以及为什么它比较快 16 | 17 | 依赖 18 | 19 | https://github.com/gulpjs/gulp/blob/master/package.json#L36 20 | 21 | 22 | 代码 23 | 24 | https://github.com/gulpjs/gulp/blob/master/index.js 25 | 26 | ``` 27 | 'use strict'; 28 | 29 | var util = require('util'); 30 | var Orchestrator = require('orchestrator'); 31 | var gutil = require('gulp-util'); 32 | var deprecated = require('deprecated'); 33 | var vfs = require('vinyl-fs'); 34 | 35 | function Gulp() { 36 | Orchestrator.call(this); 37 | } 38 | util.inherits(Gulp, Orchestrator); 39 | 40 | Gulp.prototype.task = Gulp.prototype.add; 41 | Gulp.prototype.run = function() { 42 | // `run()` is deprecated as of 3.5 and will be removed in 4.0 43 | // Use task dependencies instead 44 | 45 | // Impose our opinion of "default" tasks onto orchestrator 46 | var tasks = arguments.length ? arguments : ['default']; 47 | 48 | this.start.apply(this, tasks); 49 | }; 50 | ``` 51 | 52 | 中 53 | 54 | ``` 55 | function Gulp() { 56 | Orchestrator.call(this); 57 | } 58 | util.inherits(Gulp, Orchestrator) 59 | ``` 60 | 61 | 这里说明Gulp继承自Orchestrator 62 | 63 | ``` 64 | Gulp.prototype.task = Gulp.prototype.add; 65 | ``` 66 | 67 | 这里很明显gulp里的task方法就是Orchestrator里的add方法的别名。其他依此类推,大家去源码里翻吧。 68 | 69 | so,我才说它是gulp核心模块的。 70 | 71 | ## Intro 72 | 73 | https://github.com/robrich/orchestrator 74 | 75 | A module for sequencing and executing tasks and dependencies in maximum concurrency 76 | 77 | 翻译过来的意思 78 | 79 | - sequencing 顺序 80 | - executing tasks 执行任务 81 | - dependencies 支持依赖任务 82 | 83 | 最后一句才是最牛最核心的的:in maximum concurrency即以最大的并发能力来执行 84 | 85 | ## Usage 86 | 87 | 1) Get a reference: 88 | 89 | ``` 90 | var Orchestrator = require('orchestrator'); 91 | var orchestrator = new Orchestrator(); 92 | ``` 93 | 94 | reference是对象引用,也就是实例化Orchestrator对象的方式。 95 | 96 | 2) Load it up with stuff to do: 97 | 98 | ``` 99 | orchestrator.add('thing1', function(){ 100 | // do stuff 101 | }); 102 | orchestrator.add('thing2', function(){ 103 | // do stuff 104 | }); 105 | ``` 106 | 107 | 给orchestrator实例增加要执行的task(任务),add方法就2个参数 108 | 109 | - 参数1:是任务名称 110 | - 参数2:是具体要做的事儿,即task具体内容 111 | 112 | 简而言之:作业定义 113 | 114 | stuff这个词的意思是: 填塞,填充;塞入 115 | 116 | 3) Run the tasks: 117 | 118 | ``` 119 | orchestrator.start('thing1', 'thing2', function (err) { 120 | // all done 121 | }); 122 | ``` 123 | 124 | 这个就没啥好说的,执行任务,上面定义了'thing1', 'thing2',需要在start里运行才可以执行。 125 | 126 | 另外api还有关于promise和stream的支持 127 | 128 | 129 | 130 | ## 它是如何做到以最大并发执行的? 131 | 132 | 看着挺吓唬人的,什么以最大并发,其实也很简单 133 | 134 | 见源码 135 | 136 | https://github.com/robrich/orchestrator/blob/master/index.js 137 | 138 | ``` 139 | var Orchestrator = function () { 140 | EventEmitter.call(this); 141 | 142 | // call this when all tasks in the queue are done 143 | this.doneCallback = undefined; 144 | 145 | // the order to run the tasks 146 | this.seq = []; 147 | 148 | // task objects: name, dep (list of names of dependencies), fn (the task to run) 149 | this.tasks = {}; 150 | 151 | // is the orchestrator running tasks? .start() to start, .stop() to stop 152 | this.isRunning = false; 153 | }; 154 | ``` 155 | 156 | 这里的this上定义的4个变量是最核心的,其实和并发执行有关的seq 157 | 158 | ``` 159 | // the order to run the tasks 160 | this.seq = []; 161 | ``` 162 | 163 | js的数组`[]`是非常灵活的数据结构,它既可以队列也可以栈,如果不明白,自己去补基础。 164 | 165 | 注释上说,用于保存执行task的顺序,为什么这么说呢? 166 | 167 | - task是通过this.tasks定义 168 | - start里会有多个task 169 | - 每个task又有可能有多个依赖 170 | - 每个依赖又可能有多个依赖 171 | 172 | 所以如果执行多个tasks,你肯定要把里面的所有tasks放到seq这个队列里。在队列里的好处是,如果计算机有能力执行,它就从队列里取走一个,如果还有能力就再取走一个,所以这其实是in maximum concurrency即以最大的并发能力来执行。 173 | 174 | 上面讲了各种作业和作业依赖的问题,那么如果依赖里还有依赖,依赖的依赖里还有依赖,那么这个执行链还怎么计算呢? 175 | 176 | ## 作业依赖链是如何计算的? 177 | 178 | 答案见sequencify模块,其实就是一个简单的递归 179 | 180 | 源码见 https://github.com/robrich/sequencify 181 | 182 | 183 | ## 事件回调 184 | 185 | ``` 186 | var events = ['start','stop','err','task_start','task_stop','task_err','task_not_found','task_recursion']; 187 | ``` 188 | 189 | 具体实现 190 | 191 | ``` 192 | var Orchestrator = function () { 193 | EventEmitter.call(this); 194 | 195 | // call this when all tasks in the queue are done 196 | this.doneCallback = undefined; 197 | 198 | // the order to run the tasks 199 | this.seq = []; 200 | 201 | // task objects: name, dep (list of names of dependencies), fn (the task to run) 202 | this.tasks = {}; 203 | 204 | // is the orchestrator running tasks? .start() to start, .stop() to stop 205 | this.isRunning = false; 206 | }; 207 | ``` 208 | 209 | 看这句 210 | 211 | ``` 212 | EventEmitter.call(this); 213 | ``` 214 | 215 | 此处比较简单,在nodejs这样是非常常见的处理方式。此处不细讲了,需要注意的是onAll的实现 216 | 217 | ``` 218 | // FRAGILE: ASSUME: this list is an exhaustive list of events emitted 219 | var events = ['start','stop','err','task_start','task_stop','task_err','task_not_found','task_recursion']; 220 | 221 | var listenToEvent = function (target, event, callback) { 222 | target.on(event, function (e) { 223 | e.src = event; 224 | callback(e); 225 | }); 226 | }; 227 | 228 | Orchestrator.prototype.onAll = function (callback) { 229 | var i; 230 | if (typeof callback !== 'function') { 231 | throw new Error('No callback specified'); 232 | } 233 | 234 | for (i = 0; i < events.length; i++) { 235 | listenToEvent(this, events[i], callback); 236 | } 237 | }; 238 | ``` 239 | 240 | - listenToEvent是监听某一个事件 241 | - onAll是不管events里的那个就监听 242 | 243 | ## 如何实现一个简易gulp? 244 | 245 | ``` 246 | gulp.task('default', function() { 247 | // place code for your default task here 248 | }); 249 | ``` 250 | 251 | 然后后执行`gulp default`就会调用default task。 252 | 253 | 如果换成是orchestrator呢? 254 | 255 | ``` 256 | var Orchestrator = require('orchestrator'); 257 | var orchestrator = new Orchestrator(); 258 | 259 | orchestrator.add('hello', function(){ 260 | // do stuff 261 | console.log('this is hello task...\n'); 262 | }); 263 | 264 | orchestrator.add('default', function(){ 265 | // do stuff 266 | console.log('this is default task...\n'); 267 | }); 268 | 269 | module.exports = orchestrator; 270 | ``` 271 | 272 | 然后写个命令行,解析里面的argv来执行 273 | 274 | ``` 275 | #!/usr/bin/env node 276 | // var argv = process.argv.slice(2, process.argv.length) 277 | var argv = process.argv; 278 | argv.shift(); 279 | argv.shift(); 280 | 281 | console.log(argv + '\n'); 282 | 283 | console.log('start\n'); 284 | 285 | var gulp = require('./task') 286 | 287 | gulp.start(argv, function(){ 288 | console.log('end'); 289 | }) 290 | ``` 291 | 292 | 然后测试 293 | 294 | ``` 295 | node index.js default 296 | ``` 297 | 298 | or 299 | 300 | ``` 301 | ➜ mygulp git:(master) ✗ node index.js default hello 302 | default,hello 303 | 304 | start 305 | 306 | this is default task... 307 | 308 | this is hello task... 309 | 310 | end 311 | 312 | ``` 313 | 314 | 剩下的就是通过npm实现cli功能处理了。 315 | 316 | 那么作业依赖呢? 317 | 318 | ``` 319 | gulp.task('images', ['clean'], function() { 320 | ... 321 | }); 322 | ``` 323 | 324 | 在task.js里 325 | 326 | ``` 327 | orchestrator.add('dep', ['hello'], function(){ 328 | // do stuff 329 | console.log('this is default task...\n'); 330 | }); 331 | ``` 332 | 333 | 然后执行 334 | 335 | ``` 336 | ➜ mygulp git:(master) ✗ node index.js dep 337 | dep 338 | 339 | start 340 | 341 | this is hello task... 342 | 343 | this is default task... 344 | 345 | end 346 | 347 | ``` 348 | 349 | 代码:https://github.com/i5ting/nodejs-open-source-recommendation/tree/master/examples/mygulp 350 | 351 | ## 点评 352 | 353 | - 代码不多,但东西比较多 354 | - 另外api还有关于event,promise和stream等的支持 355 | - 遵循node的小而美哲学 356 | - 测试mocha+should测试用例非常丰富 357 | - 文档,代码都比较规范 358 | 359 | 在某些依赖key:function的场景下,Orchestrator是一个非常的选择。另外以最大并发跑task的特性也是大的实用场景。 360 | 361 | 362 | 全文完 363 | 364 | 欢迎关注我的公众号【node全栈】 365 | 366 | ![node全栈.png](https://github.com/i5ting/nodejs-open-source-recommendation/raw/master/img/wechat.png) 367 | 368 | 369 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 -------------------------------------------------------------------------------- /2016-04/nodejs-6.md: -------------------------------------------------------------------------------- 1 | # 2016-04-26发布Node.js 6.0版本 2 | 3 | 在放出Node.js 5.0之后半年多时间,Node.js基金会于2016-04-26发布了Node.js 6.0版本,并对6.0版本提供长达2年的长期支持(LTS)的计划 4 | 5 | 根据Node.js基金会LTS计划, Node.js 6.x在2018年4月之前都会提供官方支持,并且2019年4月前还会维护更新的。 6 | 7 | ## 核心变化 8 | 9 | - v8 升级到 5.0.71.35 10 | - Node.js 6 covers 93% of all ES6 features 11 | - 新的模块加载系统比4.x快4倍 12 | - 建议抛弃0.10和0.12,切换到4.x 13 | - 如果喜欢尝鲜,可以使用6.x,产品环境应用,建议最好是等stable之后 14 | 15 | ## 如何看待Node.js v5? 16 | 17 | Node.js v5 在接下来的2个月还会继续支持的,这样就可以给当前使用v5开发者时间切换到Node.js v6版本上 18 | 19 | 温馨提示,可以尝鲜,但正式环境最好还是稍晚一点,这个更安全一些,2个月后就可以考虑了 20 | 21 | ## Current? What happened to Stable? 22 | 23 | 你可能会注意到v6发布使用的标签是Current,而不是Stable。这个名字变更是为了更好的区分当前活跃开发分支里的长期支持版本。 We will be using the Current label from here-on instead of Stable. 24 | 25 | 26 | ## 抛弃 Node.js v0.10 和 v0.12 27 | 28 | 如果当前你仍然在使用Node.js v0.10 或 v0.12,是时候转到v4 或 v6。v0.10 和 v0.12 版本会被考虑进入维护模式了。也就是说今年就会完全不提供支持计划了(Version 0.10 and 0.12 will only receive maintenance updates until October 2016, and December 2016 respectively, when they'll reach EoL (End of Life))。 29 | 30 | 尽快切换吧,好处非常多,内存,性能都有大幅度提升 31 | 32 | 伴随今天的发布,基金会已经停止了老的0.12的分支的长期支持计划。官方目前支持的是 4.x 和 6.x。之前声明5.x会当测试版本,合并到6.x特性里。 33 | 34 | Node.js 4.x的长期支持计划会在2017年4月终止,所以有足够时间用于切换到6.x版本。0.10和0.12版本仅维护更新到2016年10月份,并在2016年12月份分别走到他们生命的尽头EoL (End of Life)。 35 | 36 | 基金会专家说Node.js 4.x依然是产品阶段推荐的Node.js使用版本,而新近的Node.js 6.x版本应在stable版本的时候再考虑使用,但也会包含非常多的新的JavaScript特性,这些特性还没有完全在产品环境测试,无法保证他们完全程度。 37 | 38 | 站在此时此刻来看,Node.js开发者应该使用Node.js 4.x版本,如果他们需要的是稳定性和复杂产品环境考验过的话。使用Node.js 6.x的情况是如果他们有能力快速升级版本,并想要体验最新的特性。 39 | 40 | ## Node.js 6 covers 93% of all ES6 features 41 | 42 | Node.js组去年6月曾吹支持93%的ECMAScript 6 (JavaScript 2015) 规范,可Node.js 5.x只是支持56%的ES6 规范。 43 | 44 | 45 | 该组也确实以它们的新的模块加载系统为豪,因为它说它们现在比Node.js 4.x版本要快上4倍。 46 | 47 | 其他在Node.js 6的显著变化是切换到Google's V8 version 5.0 作为 Node的JavaScript引擎,这就导致了批量bug修复和性能提升。 48 | 49 | Node.js LTS plan 50 | 51 | ![](https://github.com/nodejs/LTS/raw/master/schedule.png) 52 | -------------------------------------------------------------------------------- /2016-04/pageres.md: -------------------------------------------------------------------------------- 1 | # 抓取网站截图 2 | 3 | 很多网页特别长,直接的电脑截图非常麻烦,用ps等工具也非常麻烦,所以很多人都问我有木有自动抓出截图的软件 4 | 5 | Node.js里是有的 6 | 7 | ## 推荐pageres 8 | 9 | 首先全局安装 10 | 11 | ``` 12 | $ PHANTOMJS_CDNURL=https://npm.taobao.org/dist/phantomjs npm install phantomjs --registry=https://registry.npm.taobao.org --no-proxy 13 | $ npm install --global pageres-cli 14 | ``` 15 | 16 | 执行 17 | 18 | ![Screenshot](screenshot.png) 19 | 20 | 效果如下 21 | 22 | ![Screenshot Output](screenshot-output.png) 23 | 24 | 说明:此模块依赖PhantomJS,请备好梯子或者用文中的国内镜像 25 | 26 | ## 嵌入代码中 27 | 28 | 通过shell是可以做,这是给其他语言调用的,对于Node.js,你可以使用对应模块就好了 29 | 30 | https://github.com/sindresorhus/pageres 31 | 32 | ``` 33 | $ npm install --save pageres 34 | ``` 35 | 36 | PhantomJS, which is used for generating the screenshots, is installed automagically, but in some rare cases it might fail to and you'll get an Error: spawn EACCES error. Download PhantomJS manually and reinstall pageres if that happens. 37 | 38 | 用法 39 | 40 | ``` 41 | const Pageres = require('pageres'); 42 | 43 | const pageres = new Pageres({delay: 2}) 44 | .src('yeoman.io', ['480x320', '1024x768', 'iphone 5s'], {crop: true}) 45 | .src('todomvc.com', ['1280x1024', '1920x1080']) 46 | .dest(__dirname) 47 | .run() 48 | .then(() => console.log('done')); 49 | ``` 50 | 51 | ## 原理 52 | 53 | 其实就是利用无头浏览器PhantomJS来实现的截图 54 | 55 | 剩下的就自己玩去吧 56 | 57 | 58 | 59 | 全文完 60 | 61 | 欢迎关注我的公众号【node全栈】 62 | 63 | ![node全栈.png](//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC) 64 | 65 | 66 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 67 | 68 | -------------------------------------------------------------------------------- /2016-04/screenshot-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i5ting/nodejs-open-source-recommendation/2f7b27cada9cd2109f50fcd4cda09f5085c02235/2016-04/screenshot-output.png -------------------------------------------------------------------------------- /2016-04/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i5ting/nodejs-open-source-recommendation/2f7b27cada9cd2109f50fcd4cda09f5085c02235/2016-04/screenshot.png -------------------------------------------------------------------------------- /2016-04/strman.md: -------------------------------------------------------------------------------- 1 | # 开源Nodejs项目推荐:无任何依赖的string操作库 2 | 3 | 4 | ![](https://github.com/dleitee/strman/raw/master/strman.png?raw=true) 5 | 6 | strman是无任何依赖的string操作库,前后端通用 7 | 8 | 9 | A Javascript string manipulation library without npm dependences. 10 | 11 | ## 安装 12 | 13 | ``` 14 | npm install strman --save 15 | ``` 16 | 17 | 或者 18 | 19 | ``` 20 | bower install strman 21 | ``` 22 | 23 | ## 用法 24 | 25 | With ES6/import 26 | 27 | 28 | ``` 29 | import {slugify} from 'strman'; 30 | 31 | let title = "A Javascript string manipulation library."; 32 | let result = slugify(title); 33 | // result => "a-javascript-string-manipulation-library" 34 | ``` 35 | 36 | 37 | With require 38 | 39 | ``` 40 | var slugify = require('strman').slugify; 41 | 42 | let title = "A Javascript string manipulation library."; 43 | let result = slugify(title); 44 | // result => "a-javascript-string-manipulation-library" 45 | ``` 46 | 47 | With Browser 48 | 49 | ``` 50 | 51 | var result = _s.isString('strman'); 52 | // result => true 53 | ``` 54 | 55 | Also available for AMD 56 | 57 | 58 | ## API 59 | 60 | - [x] [append](https://github.com/dleitee/strman#appendvalue-append) 61 | - [x] [appendArray](https://github.com/dleitee/strman#appendarrayvalue-append--) 62 | - [x] [at](https://github.com/dleitee/strman#atvalue-index) 63 | - [x] [between](https://github.com/dleitee/strman#betweenvalue-start-end) 64 | - [x] [chars](https://github.com/dleitee/strman#charsvalue) 65 | - [x] [collapseWhitespace](https://github.com/dleitee/strman#collapsewhitespacevalue) 66 | - [x] [contains](https://github.com/dleitee/strman#containsvalue-needle-casesensitive--true) 67 | - [x] [containsAll](https://github.com/dleitee/strman#containsallvalue-needles---casesensitive--true) 68 | - [x] [containsAny](https://github.com/dleitee/strman#containsanyvalue-needles---casesensitive--true) 69 | - [x] [countSubstr](https://github.com/dleitee/strman#countsubstrvalue-substr-casesensitive--true-allowoverlapping--false) 70 | - [x] [endsWith](https://github.com/dleitee/strman#endswithvalue-search-positionnull-casesensitivetrue) 71 | - [x] [ensureLeft](https://github.com/dleitee/strman#ensureleftvalue-substr-casesensitivetrue) 72 | - [x] [ensureRight](https://github.com/dleitee/strman#ensurerightvalue-substr-casesensitivetrue) 73 | - [x] [first](https://github.com/dleitee/strman#firstvalue-n) 74 | - [x] [indexOf](https://github.com/dleitee/strman#indexofvalue-needle-offset--0-casesensitivetrue) 75 | - [x] [insert](https://github.com/dleitee/strman#insertvalue-substr-index) 76 | - [x] [isLowerCase](https://github.com/dleitee/strman#islowercasevalue-n) 77 | - [x] [isString](https://github.com/dleitee/strman#isstringvalue) 78 | - [x] [isUpperCase](https://github.com/dleitee/strman#isuppercasevalue-n) 79 | - [x] [last](https://github.com/dleitee/strman#lastvalue-n) 80 | - [x] [lastIndexOf](https://github.com/dleitee/strman#lastindexofvalue-needle-offset--0-casesensitivetrue) 81 | - [x] [leftPad](https://github.com/dleitee/strman#leftpadvalue-length-char) 82 | - [x] [leftTrim](https://github.com/dleitee/strman#lefttrimvalue) 83 | - [x] [length](https://github.com/dleitee/strman#lengthvalue) 84 | - [x] [prepend](https://github.com/dleitee/strman#prependvalue-prepend) 85 | - [x] [prependArray](https://github.com/dleitee/strman#prependarrayvalue-prepend--) 86 | - [x] [removeLeft](https://github.com/dleitee/strman#removeleftvalue-prefix-casesensitivetrue) 87 | - [x] [removeNonChars](https://github.com/dleitee/strman#removenoncharsvalue) 88 | - [x] [removeNonWords](https://github.com/dleitee/strman#removenonwordsvalue-replace) 89 | - [x] [removeRight](https://github.com/dleitee/strman#removerightvalue-suffix-casesensitivetrue) 90 | - [x] [removeSpaces](https://github.com/dleitee/strman#removespacesvalue-replace) 91 | - [x] [repeat](https://github.com/dleitee/strman#repeatvalue-multiplier) 92 | - [x] [replace](https://github.com/dleitee/strman#replacevalue-search-newvalue-casesensitivetrue) 93 | - [x] [reverse](https://github.com/dleitee/strman#reversevalue) 94 | - [x] [rightPad](https://github.com/dleitee/strman#rightpadvalue-length-char) 95 | - [x] [rightTrim](https://github.com/dleitee/strman#righttrimvalue) 96 | - [x] [safeTruncate](https://github.com/dleitee/strman#safetruncatevalue-length-append) 97 | - [x] [shuffle](https://github.com/dleitee/strman#shufflevalue) 98 | - [x] [slice](https://github.com/dleitee/strman#slicevalue-beginslice-endslice) 99 | - [x] [slugify](https://github.com/dleitee/strman#slugifystring) 100 | - [x] [split](https://github.com/dleitee/strman#splitvalue-separator-limit) 101 | - [x] [startsWith](https://github.com/dleitee/strman#startswithvalue-search-position0) 102 | - [x] [substr](https://github.com/dleitee/strman#substrvalue-start-length) 103 | - [x] [surround](https://github.com/dleitee/strman#surroundvalue-substr) 104 | - [x] [toCamelCase](https://github.com/dleitee/strman#tocamelcasevalue) 105 | - [x] [toDecamelize](https://github.com/dleitee/strman#todecamelizevalue-chr) 106 | - [x] [toKebabCase](https://github.com/dleitee/strman#tokebabcasevalue) 107 | - [x] [toLowerCase](https://github.com/dleitee/strman#tolowercasevalue) 108 | - [x] [toSnakeCase](https://github.com/dleitee/strman#tosnakecasevalue) 109 | - [x] [toStudlyCaps](https://github.com/dleitee/strman#tostudlycapsvalue) 110 | - [x] [toUpperCase](https://github.com/dleitee/strman#touppercasevalue) 111 | - [x] [trim](https://github.com/dleitee/strman#trimvalue) 112 | - [x] [truncate](https://github.com/dleitee/strman#truncatevalue-length-append) 113 | 114 | ## 说明 115 | 116 | npm依赖分2种,常规依赖和dev依赖。 117 | 118 | strman没有任何常规依赖,也就是它自己说的:“without npm dependences”,但它是es 6语法,借助babel开发的,这是开发阶段使用的依赖 119 | 120 | 看一下它的package.json 121 | 122 | ``` 123 | "main": "dist/strman.js", 124 | ``` 125 | 126 | dist是压缩后的目录,也就是说它的模块主文件是压缩后的。 127 | 128 | 根目录里有一个gulpfile.babel.js用于压缩混淆,这就很明显了 129 | 130 | 131 | ``` 132 | gulp.task('browserify', () => { 133 | browserify({ 134 | entries: './src/strman.js', 135 | transform: [babelify, es6ify, deglobalify], 136 | 137 | // Generate a UMD bundle for the supplied export name. 138 | // This bundle works with other module systems and sets the name 139 | // given as a window global if no module system is found. 140 | standalone: '_s', 141 | 142 | // Enable source maps that allow you to debug your files 143 | // separately. 144 | debug: true 145 | }) 146 | .bundle() 147 | .pipe(source('strman.js')) 148 | .pipe(buffer()) 149 | .pipe(uglify()) 150 | .pipe(gulp.dest('dist')) 151 | .pipe(gulp.dest('public')); 152 | }); 153 | ``` 154 | 155 | ## 总结 156 | 157 | 目前看是基于mocha和chai的测试,基本ok,集成了travis-ci,但无测试覆盖率,无benchmark,性能如何还不好说 158 | 159 | 从开源到今天(4月24日),才12天,已经754个star,还算是不错的了,想参与的可以去贡献一下。另外要说的是它是学习es6的非常好的范例,推荐。 160 | 161 | 162 | 全文完 163 | 164 | 欢迎关注我的公众号【node全栈】 165 | 166 | ![node全栈.png](//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC) 167 | 168 | 169 | 如果想参与评论,请点击原文链接,进入国内最专业的cnode论坛 170 | 171 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 alfred sang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nodejs-open-source-recommendation 2 | 3 | 4 | ## 2016-01 5 | 6 | - [开源Nodejs微服务项目推荐:micro](2016-01/micro.md) 7 | - [开源Nodejs项目推荐【单词处理】:inflected](2016-01/inflected.md) 8 | - [hackathon-starter](https://github.com/sahat/hackathon-starter) 9 | 10 | ## 2016-02 11 | 12 | - [开源Nodejs项目推荐gulp核心模块:Orchestrator](2016-02/orchestrator.md) 13 | 14 | 15 | ## 2016-04 16 | 17 | - [开源Nodejs项目推荐:抓取网站截图](2016-04/pageres.md) 18 | - [开源Nodejs项目推荐:无任何依赖的string操作库](2016-04/strman.md) 19 | 20 | 21 | 22 | ## 欢迎关注我的公众号【node全栈】 23 | 24 | ![node全栈.png](img/wechat.png) 25 | 26 | 27 | 如果想参与评论,请进入国内最专业的cnode论坛 -------------------------------------------------------------------------------- /Why I Love Node.js: Promises, Express, and the CLI.md: -------------------------------------------------------------------------------- 1 | # Why I Love Node.js: Promises, Express, and the CLI 2 | 3 | https://dzone.com/articles/why-i-love-nodejs-part-2-adams-blog?edition=144259&utm_source=Spotlight&utm_medium=email&utm_content=queue&utm_campaign=web%20dev%202016-02-18 4 | 5 | ``` 6 | I published a [blog post about Node.js](http://adamfowler.org/2013/05/08/why-i-like-node-js/) a couple of years ago. After recently using it for some more crazy stuff, I thought I’d post more reasons I love [Node.js](http://www.nodejs.org/)! 7 | 8 | by Adam Fowler · Feb. 09, 16 · Web Dev Zone 9 | ``` 10 | 11 | I published a [blog post about Node.js](http://adamfowler.org/2013/05/08/why-i-like-node-js/) a couple of years ago. After recently using it for some more crazy stuff, I thought I’d post more reasons I love [Node.js](http://www.nodejs.org/)! 12 | 13 | 几年前我发布了一篇[关于Node.js的博文](http://adamfowler.org/2013/05/08/why-i-like-node-js/)。在最近做了几次对博文更加疯狂的填充之后,我想我写这篇文章更多的原因是因为我热爱[Node.js](http://www.nodejs.org/)! 14 | 15 | ## Promises, Promises 16 | 17 | I mentioned bracket hell in my previous post. Well, in the intervening period, I’ve started using Promises for a lot of things, especially the [Q promises library](https://www.npmjs.com/package/q) in npm. 18 | 19 | 在我之前的文章里我曾提到过“bracket hell”。当然,在介入一段时间后,我开始使用使用Promises做很多事儿,尤其是npm里的[Q promises 库]。 20 | 21 | Promises allow you to easily chain actions together. You can run things in parallel and wait for them to finish, or run things in sequence, or both! I’ve just used both in the last week to start 10 'threads' using [Q.all](https://www.npmjs.com/package/q#combination), with each thread running 1500 tasks in series using [promisesArray.reduce](https://www.npmjs.com/package/q#sequences). 22 | 23 | Promises允许你进行简单的链式操作。你可以并行执行代码,直到它们执行完成,或顺序执行,或者二者混用!我曾在上周使用过二者混用,使用[Q.all](https://www.npmjs.com/package/q#combination)来启动10个“线程”,每个线程使用[promisesArray.reduce](https://www.npmjs.com/package/q#sequences)顺序跑1500个任务。 24 | 25 | This allowed me to test a customer’s [Node.js](http://www.nodejs.org/) Express based web application at scale with just a few lines of code, which in turn tested high throughput ingest and query loads in [MarkLogic Server](http://developer.marklogic.com/). 26 | 27 | 这让我可以通过很少的几行代码,去大规模的测试客户的基于[Node.js](http://www.nodejs.org/) Express web框架的应用,在[MarkLogic Server](http://developer.marklogic.com/)里轮流测试高吞吐量和查询负载。 28 | 29 | ## Express Web Apps 30 | 31 | Creating a web server sounds scary, but with [Express](https://www.npmjs.com/package/express) is very, very easy. You just intercept the small number of routes (URL patterns) you need, and you’re away! 32 | 33 | 创建web server听起来挺吓人的,但使用[Express](https://www.npmjs.com/package/express)却非常非常的简单。你仅仅需要中间截取你需要的小量的路由(URL patterns),这样就完成了! 34 | 35 | You can even use the URL pattern itself to infer parameters. E.g. /get/fred/1 could be used to fetch the first document in the fred collection. Pretty cool, and reminiscent of Ruby on Rails. 36 | 37 | 你甚至可以使用URL pattern自身的推断参数。例如/get/fred/1 可以用于获取在fred集合里的第一个文档。相当酷吧,让人不禁想到Ruby on Rails。 38 | 39 | I’d definitely recommend learning Express first if developing a web application. 40 | 41 | 如果要是想开发web应用的话,无疑我会优先推荐学习Express。 42 | 43 | ## 命令行应用 Command Line Applications 44 | 45 | Did you know you can even use Node to create an NPM package that installs a global application on any platform? This is **awesome** in NPM form! 46 | 47 | 你知道可以使用Node创建一个可以在各个平台上全局安装的NPM包应用么?这就是NPM的**酷的**形式。 48 | 49 | I’ve used this to package up two tools I use on projects in to my [mlnodetools](https://github.com/adamfowleruk/mlnodetools) package. mljsadmin allows you to capture a MarkLogic application with all server settings and transfer it to another machine with just a couple of commands. mljsserve uses Express mentioned above to create a thin web server which also proxies MarkLogic REST API URLs directly to MarkLogic Server. 50 | 51 | 我把它用到我的[mlnodetools](https://github.com/adamfowleruk/mlnodetools)包里,把我在项目里的2个工具打包到里面。mljsadmin允许你捕获MarkLogic应用和所有服务器设置,并通过几个命令把它传送到另一个机器。mljsserve使用上文提到的Express来创建一个小web server,使用它代理MarkLogic REST API URLs直接代理到MarkLogic服务器。 52 | 53 | 54 | This is great for demonstration web apps at work in MarkLogic Sales Engineering (We’re hiring by the way, so please contact me if you’re interested!) 55 | 56 | 在MarkLogic销售引擎中做的事儿是阐述web应用非常棒的(顺便说一下,我们正在招聘,如果你们感兴趣的话请联系我)。 57 | 58 | I use a few NPM packages for mljsadmin:- 59 | 60 | 我在mljsadmin里使用的几个NPM包:- 61 | 62 | - [minimist](https://www.npmjs.com/package/minimist) is used to parse command line arguments. I can’t express my love for this capability enough! 63 | - [q](https://www.npmjs.com/package/q) again is used for promises when chaining complex functionality together (so 'install' runs about 9 sub-commands in series, which can also each be ran on their own from the command line) 64 | - [winston](https://www.npmjs.com/package/winston) is used for logging output and errors to both the command line (info level) and a file (debug level). I use this in my [mljs MarkLogic REST API wrapper](https://github.com/adamfowleruk/mljs) too. 65 | - [istextorbinary](https://www.npmjs.com/package/istextorbinary) allows me to test files to see if they are binaries. Useful as MarkLogic Server doesn’t hold every mime type in use. I use this to determine whether I need to do a binary upload or not, and what mime type to specify 66 | - [terminal-kit](https://www.npmjs.com/package/terminal-kit) is used to provide color coded and styled text on the command line output. Useful so that I can have green for successes, yellow for warnings, and red for major errors. 67 | 68 | - [minimist](https://www.npmjs.com/package/minimist)用于解析命令行参数。我无法表达我对它足够强大能力的热爱! 69 | - [q](https://www.npmjs.com/package/q)再次用于promises,把复杂函数链接一起(所以当'install'顺序执行9各子命令, runs about 9 sub-commands in series, which can also each be ran on their own from the command line) 70 | - [winston](https://www.npmjs.com/package/winston)用于在命令行(info level)或文件(debug level)里记录日志输出和错误。我也在我的 [mljs MarkLogic REST API wrapper](https://github.com/adamfowleruk/mljs) 里也用它了. 71 | - [istextorbinary](https://www.npmjs.com/package/istextorbinary) 让我可以测试文件,判断它们是不是二进制。在使用MarkLogic Server不掌握每一个mime类型的时候是非常有用的。我用它来决断,物流我需要一个上传二进制文件或者其他,或指定哪种mime类型。 72 | - [terminal-kit](https://www.npmjs.com/package/terminal-kit)用于提供命令行输出里的代码着色和样式文本。在我用绿色表示成功,黄色表示警告,红色代表主要错误的时候是非常有用的。 73 | 74 | 75 | ## 总结Summary 76 | 77 | I’m constantly and pleasantly surprised that for whatever little tool or demonstration I need, no matter how complex, Node.js greatly simplifies my life! 78 | 79 | 我经常愉快的因为他们而惊喜,无论小工具还是我需要阐述的那些,无论多复杂,Node.js极大的简化我的生活! 80 | 81 | Node.js' event driven nature and wide support for extension via [NPM](http://npmjs.com/) allows me to quickly find and make use of even the most esoteric functionality I need. I often have a choice of esoteric libraries! 82 | 83 | Node.js的事件驱动特性和通过扩展支持广泛的[NPM](http://npmjs.com/),让我可以快速的查找和使用我需要的最多神秘功能。我经常可以选择神密的库。 84 | 85 | I’d recommend learning Node.js to anyone working in IT today. Node.js can make your projects fly! 86 | 87 | 在IT今天,无论干什么工作,我都推荐你们学习Node.js。Node.js会让你的项目腾飞! -------------------------------------------------------------------------------- /examples/mygulp/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var argv = process.argv.slice(2, process.argv.length) 4 | 5 | console.log(argv + '\n'); 6 | 7 | console.log('start\n'); 8 | 9 | var gulp = require('./task') 10 | 11 | gulp.start(argv, function(){ 12 | console.log('end'); 13 | }) -------------------------------------------------------------------------------- /examples/mygulp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mygulp", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "preferGlobal": "true", 10 | "bin": { 11 | "mygulp": "index.js" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "orchestrator": "^0.3.7" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mygulp/task.js: -------------------------------------------------------------------------------- 1 | var Orchestrator = require('orchestrator'); 2 | var orchestrator = new Orchestrator(); 3 | 4 | orchestrator.add('hello', function(){ 5 | // do stuff 6 | console.log('this is hello task...\n'); 7 | }); 8 | 9 | orchestrator.add('default', function(){ 10 | // do stuff 11 | console.log('this is default task...\n'); 12 | }); 13 | 14 | 15 | orchestrator.add('dep', ['hello'], function(){ 16 | // do stuff 17 | console.log('this is default task...\n'); 18 | }); 19 | 20 | module.exports = orchestrator; 21 | -------------------------------------------------------------------------------- /img/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i5ting/nodejs-open-source-recommendation/2f7b27cada9cd2109f50fcd4cda09f5085c02235/img/wechat.png --------------------------------------------------------------------------------