diff --git a/README.chinese.md b/README.chinese.md
new file mode 100644
index 000000000..84f75b8e4
--- /dev/null
+++ b/README.chinese.md
@@ -0,0 +1,732 @@
+[✔]: assets/images/checkbox-small-blue.png
+
+# Node.js 最佳实践
+
+
+
+
+
+
+
+
+
+
+
+ [![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
+
+
+# 欢迎! 首先您应该知道的三件事情:
+**1. 当您读到这里,实际上您读了很多关于Node.js的优秀文章 -** 这是对Node JS 最佳实践中排名最高的内容的总结和分享
+
+**2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。每天都有新的issue和PR被创建,以使这本在线书籍不断更新。我们很乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是提出绝妙的新想法。请查看我们的[milestones](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open)
+
+**3. 大部分的条目包含额外的信息 -** 大部分的最佳实践条目的旁边,您将发现 **🔗Read More** 链接,它将呈现给您示例代码,博客引用和更多信息
+
+
+
+## 目录
+1. [项目结构实践 (5) ](#1-project-structure-practices)
+2. [异常处理实践 (11) ](#2-error-handling-practices)
+3. [编码规范实践 (12) ](#3-code-style-practices)
+4. [测试和总体质量实践 (8) ](#4-testing-and-overall-quality-practices)
+5. [进入生产实践 (16) ](#5-going-to-production-practices)
+6. Security Practices ([coming soon](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open))
+7. Performance Practices ([coming soon](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open))
+
+
+
+# `1. 项目结构实践`
+
+## ![✔] 1.1 组件式构建你的解决方案
+
+ **TL;DR:** 最坏的大型项目的隐患就是维护一个庞大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。
+
+**否则:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展
+
+🔗 [**更多: 组件结构**](/sections/projectstructre/breakintcomponents.chinese.md)
+
+
+
+## ![✔] 1.2 分层设计组件,保持Express在特定的区域
+
+**TL;DR:** 每一个组件都应该包含'层级' - 一个专注的用于接入网络,逻辑,数据的概念。这样不仅获得一个清晰的分离考量,而且使仿真和测试系统变得异常容易。尽管这是一个普通的模式,但接口开发者易于混淆层级关系,比如把网络层的对象(Express req, res)传给业务逻辑和数据层 - 这会令您的应用彼此依赖,并且只能通过Express使用。
+
+**否则:** 对于混淆了网络层和其它层的应用,将不易于测试,执行CRON的任务,其它非-Express的调用者无法使用
+
+🔗 [**更多: 应用分层**](/sections/projectstructre/createlayers.chinese.md)
+
+
+
+## ![✔] 1.3 封装公共模块成为NPM的包
+
+**TL;DR:** 由大量代码构成的一个大型应用中,贯彻全局的,比如日志,加密和其它类似的公共组件,应该进行封装,并暴露成一个私有的NPM包。这将使其在更多的代码库和项目中被使用变成了可能。
+
+**否则:** 您将不得不重造部署和依赖的轮子
+
+🔗 [**更多: 通过需求构建**](/sections/projectstructre/wraputilities.chinese.md)
+
+
+
+## ![✔] 1.4 分离 Express 'app' and 'server'
+
+**TL;DR:** 避免定义整个[Express](https://expressjs.com/)应用在一个单独的大文件里, 这是一个不好的习惯 - 分离您的 'Express' 定义至少在两个文件中: API声明(app.js) 和 网络相关(WWW)。对于更好的结构,是把你的API声明放在组件中。
+
+**否则:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。
+
+🔗 [**更多: 分离 Express 'app' and 'server'**](/sections/projectstructre/separateexpress.chinese.md)
+
+
+
+## ![✔] 1.5 使用易于设置环境变量,安全和分级的配置
+
+
+**TL;DR:** 一个完美无瑕的配置安装应该确保 (a) 元素可以从文件中,也可以从环境变量中读取 (b) 密码排除在提交的代码之外 (c) 为了易于检索,配置是分级的。仅有几个包可以满足这样的条件,比如[nconf](https://www.npmjs.com/package/nconf) 和 [config](https://www.npmjs.com/package/config)。
+
+**否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。
+
+🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.chinese.md)
+
+
+
+⬆ 返回顶部
+
+# `2. 错误处理最佳实践`
+
+## ![✔] 2.1 使用 Async-Await 和 promises 用于异步错误处理
+
+**TL;DR:** 使用回调的方式处理异步错误可能是导致灾难的最快的方式(a.k.a the pyramid of doom)。对您的代码来说,最好的礼物就是使用规范的promise库或async-await来替代,这会使其像try-catch一样更加简洁,具有熟悉的代码结构。
+
+**否则:** Node.js 回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。
+
+🔗 [**更多: 避免回调**](/sections/errorhandling/asyncerrorhandling.chinese.md)
+
+
+
+## ![✔] 2.2 仅使用内建的错误对象
+
+**TL;DR:** 很多人抛出异常使用字符串类型或一些自定义类型 - 这会导致错误处理逻辑和模块间的调用复杂化。是否您reject一个promise,抛出异常或发出(emit)错误 - 使用内建的错误对象将会增加设计一致性,并防止信息的丢失。
+
+
+**否则:** 调用某些模块,将不确定哪种错误类型会返回 - 这将会使恰当的错误处理更加困难。更坏的情况是,使用特定的类型描述错误,会导致重要的错误信息缺失,比如stack trace!
+
+🔗 [**更多: 使用内建错误对象**](/sections/errorhandling/useonlythebuiltinerror.chinese.md)
+
+
+
+## ![✔] 2.3 区分运行错误和程序设计错误
+
+**TL;DR:** 运行错误(例如, API接受到一个无效的输入)指的是一些已知场景下的错误,这类错误的影响已经完全被理解,并能被考虑周全的处理掉。同时,程序设计错误(例如,尝试读取未定义的变量)指的是未知的编码问题,影响到应用得当的重启。
+
+**否则:** 当一个错误产生的时候,您总是得重启应用,但为什么要让 ~5000 个在线用户不能访问,仅仅是因为一个细微的,可以预测的,运行时错误?相反的方案,也不完美 – 当未知的问题(程序问题)产生的时候,使应用依旧可以访问,可能导致不可预测行为。区分两者会使处理更有技巧,并在给定的上下文下给出一个平衡的对策。
+
+🔗 [**更多: 运行错误和程序设计错误**](/sections/errorhandling/operationalvsprogrammererror.chinese.md)
+
+
+
+## ![✔] 2.4 集中处理错误,不要在Express中间件中处理错误
+
+**TL;DR:** 错误处理逻辑,比如给管理员发送邮件,日志应该封装在一个特定的,集中的对象当中,这样当错误产生的时候,所有的终端(例如 Express中间件,cron任务,单元测试)都可以调用。
+
+**否则:** 错误处理的逻辑不放在一起将会导致代码重复和非常可能不恰当的错误处理。
+
+🔗 [**更多: 集中处理错误**](/sections/errorhandling/centralizedhandling.chinese.md)
+
+
+
+## ![✔] 2.5 对API错误使用Swagger文档化
+
+**TL;DR:** 让你的API调用者知道哪种错误会返回,这样他们就能完全的处理这些错误,而不至于系统崩溃。Swagger,REST API的文档框架,通常处理这类问题。
+
+**否则:** 任何API的客户端可能决定崩溃并重启,仅仅因为它收到一个不能处理的错误。注意:API的调用者可能是你(在微服务环境中非常典型)。
+
+
+🔗 [**更多: 使用Swagger记录错误**](/sections/errorhandling/documentingusingswagger.chinese.md)
+
+
+
+## ![✔] 2.6 当一个特殊的情况产生,停掉服务是得体的
+
+**TL;DR:** 当一个不确定错误产生(一个开发错误,最佳实践条款#3) - 这就意味着对应用运转健全的不确定。一个普通的实践将是建议仔细地重启进程,并使用一些‘启动器’工具,比如Forever和PM2。
+
+**否则:** 当一个未知的异常被抛出,意味着某些对象包含错误的状态(例如某个全局事件发生器由于某些内在的错误,不在产生事件),未来的请求可能失败或者行为异常。
+
+🔗 [**更多: 停掉服务**](/sections/errorhandling/shuttingtheprocess.chinese.md)
+
+
+
+
+
+## ![✔] 2.7 使用一个成熟的日志工具提高错误的可见性
+
+**TL;DR:** 一系列成熟的日志工具,比如Winston,Bunyan和Log4J,会加速错误的发现和理解。忘记console.log吧。
+
+**否则:** 浏览console的log,和不通过查询工具或者一个好的日志查看器,手动浏览繁琐的文本文件,会使你忙于工作到很晚。
+
+🔗 [**更多: 使用好用的日志工具**](/sections/errorhandling/usematurelogger.chinese.md)
+
+
+
+
+
+## ![✔] 2.8 使用你最喜欢的测试框架测试错误流
+
+**TL;DR:** 无论专业的自动化测试或者简单的手动开发测试 - 确保您的代码不仅满足正常的场景,而且处理并且返回正确的错误。测试框架,比如Mocha & Chai可以非常容易的处理这些问题(在"Gist popup"中查看代码实例) 。
+
+**否则:** 没有测试,不管自动还是手动,您不可能依赖代码去返回正确的错误。而没有可以理解的错误,那将毫无错误处理可言。
+
+
+🔗 [**更多: 测试错误流向**](/sections/errorhandling/testingerrorflows.chinese.md)
+
+
+
+## ![✔] 2.9 使用APM产品发现错误和宕机时间
+
+**TL;DR:** 监控和性能产品 (别名 APM) 先前一步的检测您的代码库和API,这样他们能自动的,像使用魔法一样的强调错误,宕机和您忽略的性能慢的部分。
+
+**否则:** 您花了很多的力气在测量API的性能和错误,但可能您从来没有意识到真实场景下您最慢的代码块和他们对UX的影响。
+
+
+🔗 [**更多: 使用APM产品**](/sections/errorhandling/apmproducts.chinese.md)
+
+
+
+
+## ![✔] 2.10 捕获未处理的promise rejections
+
+**TL;DR:** 任何在promise中被抛出的异常将被收回和遗弃,除非开发者没有忘记去明确的处理。即使您的代码调用的是process.uncaughtException!解决这个问题可以注册到事件process.unhandledRejection。
+
+**否则:** 您的错误将被回收,无踪迹可循。没有什么可以需要考虑。
+
+
+🔗 [**更多: 捕获未处理的promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.chinese.md)
+
+
+
+## ![✔] 2.11 快速查错,验证参数使用一个专门的库Fail fast, validate arguments using a dedicated library
+
+**TL;DR:** 这应该是您的Express最佳实践中的一部分 – assert API输入避免难以理解的漏洞,这类漏洞以后会非常难以追踪。而验证代码通常是一件乏味的事情,除非使用一些非常炫酷的帮助库比如Joi。
+
+**否则:** 考虑这种情况 – 您的功能期望一个数字参数 “Discount” ,然而调用者忘记传值,之后在您的代码中检查是否 Discount!=0 (允许的折扣值大于零),这样它将允许用户使用一个折扣。OMG,多么不爽的一个漏洞。你能明白吗?
+
+🔗 [**更多: 快速查错**](/sections/errorhandling/failfast.chinese.md)
+
+
+
+⬆ 返回顶部
+
+# `3. 编码风格实践`
+
+## ![✔] 3.1 使用ESLint
+
+**TL;DR:** ESLint是检查代码风格的事实上的标准,不仅要查明实际的间距问题,也要检测严重的反模式问题,像开发者没有分类的抛出异常。使用ESLint及下面列出的其他的代码风格实践,意味着和社区里的其他人保持同一种风格,以及用在核心产品本身相同的代码风格。
+
+**否则:** 开发者必须专注于单调的间距和线宽的问题上。
+
+
+
+## ![✔] 3.2 Node.js 特定的插件
+
+**TL;DR:** 除了仅仅涉及 vanilla JS 的 ESLint 标准规则,添加 Node 相关的插件,比如[eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security)
+
+**否则:** 许多错误的Node.js代码模式可能在检测下逃生。例如,开发人员可能需要某些文件,把一个变量作为路径名 (variableAsPath) ,这会导致攻击者可以执行任何JS脚本。Node.JS linters可以检测这类模式,并及早预警。
+
+
+
+## ![✔] 3.3 在同一行开始一个代码块的大括号
+
+**TL;DR:** 代码块的第一个大括号应该和声明的起始保持在同一行中。
+
+### 代码示例
+```javascript
+ // 建议
+ function someFunction() {
+ // 代码块
+ }
+
+ // 避免
+ function someFunction
+ {
+ // 代码块
+ }
+```
+
+**否则:** 不遵守这项最佳实践可能导致意外的结果,在Stackoverflow的帖子中可以查看到,如下:
+
+🔗 [**更多:** "Why does a results vary based on curly brace placement?" (Stackoverflow)](https://stackoverflow.com/questions/3641519/why-does-a-results-vary-based-on-curly-brace-placement)
+
+
+
+## ![✔] 3.4 不要忘记分号
+
+**TL;DR:** 即使没有获得一致的认同,但在每一个表达式后面放置分号还是值得推荐的。这将使您的代码, 对于其他阅读代码的开发者来说,可读性,明确性更强。
+
+**否则:** 在前面的章节里面已经提到,如果表达式的末尾没有添加分号,JavaScript的解释器会在自动添加一个,这可能会导致一些意想不到的结果。
+
+
+
+## ![✔] 3.5 命名您的方法
+
+**TL;DR:** 命名所有的方法,包含闭包和回调, 避免匿名方法。当剖析一个node应用的时候,这是特别有用的。命名所有的方法将会使您非常容易的理解内存快照中您正在查看的内容。
+
+**否则:** 使用一个核心dump(内存快照)调试线上问题,会是一项非常挑战的事项,因为你注意到的严重内存泄漏问题极有可能产生于匿名的方法。
+
+
+
+## ![✔] 3.6 变量、常量、函数和类的命名约定
+
+**TL;DR:** 当命名变量和方法的时候,使用 ***lowerCamelCase*** ,当命名类的时候,使用 ***UpperCamelCase*** (首字母大写),对于常量,则 ***UPPERCASE*** 。这将帮助您轻松地区分普通变量/函数和需要实例化的类。使用描述性名称,但使它们尽量简短。
+
+**否则:** JavaScript是世界上唯一一门不需要实例化,就可以直接调用构造函数("Class")的编码语言。因此,类和函数的构造函数由采用UpperCamelCase开始区分。
+
+### 代码示例 ###
+```javascript
+ // 使用UpperCamelCase命名类名
+ class SomeClassExample () {
+
+ // 常量使用UPPERCASE
+ const CONFIG = {
+ key: 'value'
+ };
+
+ // 变量和方法使用lowerCamelCase
+ let someVariableExample = 'value';
+ function doSomething() {
+
+ }
+
+ }
+```
+
+
+
+## ![✔] 3.7 使用const优于let,废弃var
+
+**TL;DR:** 使用` const `意味着一旦一个变量被分配,它不能被重新分配。使用const将帮助您免于使用相同的变量用于不同的用途,并使你的代码更清晰。如果一个变量需要被重新分配,以在一个循环为例,使用 `let` 声明它。let的另一个重要方面是,使用let声明的变量只在定义它的块作用域中可用。 `var` 是函数作用域,不是块级作用域,既然您有const和let让您随意使用,那么[不应该在ES6中使用var](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70)。
+
+**否则:** 当经常更改变量时,调试变得更麻烦了。
+
+🔗 [**更多: JavaScript ES6+: var, let, or const?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75)
+
+
+
+## ![✔] 3.8 先require, 而不是在方法内部
+
+**TL;DR:** 在每个文件的起始位置,在任何函数的前面和外部 require 模块。这种简单的最佳实践,不仅能帮助您轻松快速地在文件顶部辨别出依赖关系,而且避免了一些潜在的问题。
+
+**否则:** 在 NodeJs 中,require 是同步运行的。如果从函数中调用它们,它可能会阻塞其他请求,在更关键的时间得到处理。另外,如果所 require 的模块或它自己的任何依赖项抛出错误并使服务器崩溃,最好尽快查明它,如果该模块在函数中 require 的,则可能不是这样的情况。
+
+
+
+## ![✔] 3.9 在文件夹上 require ,而不是直接在文件上
+
+**TL;DR:** 当在一个文件夹中开发库/模块,放置一个文件index.js暴露模块的
+内部,这样每个消费者都会通过它。这将作为您模块的一个接口,并使未来的变化简单而不违反规则。
+
+**否则:** 更改文件内部结构或签名可能会破坏与客户端的接口。
+
+### 代码示例
+```javascript
+ // 建议
+ module.exports.SMSProvider = require('./SMSProvider');
+ module.exports.SMSNumberResolver = require('./SMSNumberResolver');
+
+ // 避免
+ module.exports.SMSProvider = require('./SMSProvider/SMSProvider.js');
+ module.exports.SMSNumberResolver = require('./SMSNumberResolver/SMSNumberResolver.js');
+```
+
+
+
+
+## ![✔] 3.10 使用 `===` 操作符
+
+**TL;DR:** 对比弱等于 `==`,优先使用严格的全等于 `===` 。`==`将在它们转换为普通类型后比较两个变量。在 `===` 中没有类型转换,并且两个变量必须是相同的类型。
+
+**否则:** 与 `==` 操作符比较,不相等的变量可能会返回true。
+
+### 代码示例
+```javascript
+'' == '0' // false
+0 == '' // true
+0 == '0' // true
+
+false == 'false' // false
+false == '0' // true
+
+false == undefined // false
+false == null // false
+null == undefined // true
+
+' \t\r\n ' == 0 // true
+```
+如果使用`===`, 上面所有语句都将返回 false。
+
+
+
+## ![✔] 3.11 使用 Async Await, 避免回调
+
+**TL;DR:** Node 8 LTS现已全面支持异步等待。这是一种新的方式处理异步请求,取代回调和promise。Async-await是非阻塞的,它使异步代码看起来像是同步的。您可以给你的代码的最好的礼物是用async-await提供了一个更紧凑的,熟悉的,类似try catch的代码语法。
+
+**否则:** 使用回调的方式处理异步错误可能是陷入困境最快的方式 - 这种方式必须面对不停地检测错误,处理别扭的代码内嵌,难以推理编码流。
+
+🔗[**更多:** async await 1.0 引导](https://github.com/yortus/asyncawait)
+
+
+
+## ![✔] 3.12 使用 (=>) 箭头函数
+
+**TL;DR:** 尽管使用 async-await 和避免方法作为参数是被推荐的, 但当处理那些接受promise和回调的老的API的时候 - 箭头函数使代码结构更加紧凑,并保持了根方法上的语义上下文 (例如 'this')。
+
+**否则:** 更长的代码(在ES5方法中)更易于产生缺陷,并读起来很是笨重。
+
+🔗 [**更多: 这是拥抱箭头函数的时刻**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75)
+
+
+
+
+⬆ 返回顶部
+
+
+# `4. 测试和总体的质量实践`
+
+## ![✔] 4.1 至少,编写API(组件)测试
+
+**TL;DR:** 大多数项目只是因为时间表太短而没有进行任何自动化测试,或者测试项目失控而正被遗弃。因此,优先从API测试开始,这是最简单的编写和提供比单元测试更多覆盖率的事情(你甚至可能不需要编码而进行API测试,像[Postman](https://www.getpostman.com/)。之后,如果您有更多的资源和时间,继续使用高级测试类型,如单元测试、DB测试、性能测试等。
+
+**否则:** 您可能需要花很长时间编写单元测试,才发现只有20%的系统覆盖率。
+
+
+
+## ![✔] 4.2 使用一个linter检测代码问题
+
+**TL;DR:** 使用代码linter检查基本质量并及早检测反模式。在任何测试之前运行它, 并将其添加为预提交的git钩子, 以最小化审查和更正任何问题所需的时间。也可在[Section 3](https://github.com/i0natan/nodebestpractices#3-code-style-practices)中查阅编码样式实践
+
+**否则:** 您可能让一些反模式和易受攻击的代码传递到您的生产环境中。
+
+
+
+
+## ![✔] 4.3 仔细挑选您的持续集成(CI)平台
+
+**TL;DR:** 您的持续集成平台(cicd)将集成各种质量工具(如测试、lint),所以它应该是一个充满活力的生态系统,包含各种插件。[jenkins](https://jenkins.io/)曾经是许多项目的默认选项,因为它有最大的社区,同时也是一个非常强大的平台,这样的代价是要求一个陡峭的学习曲线。如今,使用SaaS工具,比如[CircleCI](https://circleci.com)及其他,安装一套CI解决方案,相对是一件容易的事情。这些工具允许构建灵活的CI管道,而无需管理整个基础设施。最终,这是一个鲁棒性和速度之间的权衡 - 仔细选择您支持的方案。
+
+**否则:** 一旦您需要一些高级定制,选择一些细分市场供应商可能会让您停滞不前。另一方面,伴随着jenkins,可能会在基础设施设置上浪费宝贵的时间。
+
+🔗 [**更多: 挑选 CI 平台**](/sections/testingandquality/citools.chinese.md)
+
+
+
+## ![✔] 4.4 经常检查易受攻击的依赖
+
+**TL;DR:** 即使是那些最有名的依赖模块,比如Express,也有已知的漏洞。使用社区和商业工具,比如 🔗 [nsp](https://github.com/nodesecurity/nsp) ,集成在您的CI平台上,在每一次构建的时候都会被调用,这样可以很容易地解决漏洞问题。
+
+**否则:** 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物,相当繁琐。
+
+
+
+## ![✔] 4.5 测试标签化
+
+**TL;DR:** 不同的测试必须运行在不同的情景:quick smoke,IO-less,当开发者保存或提交一个文件,测试应该启动;完整的端到端的测试通常运行在一个新的pull request被提交之后,等等。这可以通过对测试用例设置标签,比如关键字像#cold #api #sanity,来完成。这样您可以对您的测试集进行grep,调用需要的子集。例如,这就是您通过[Mocha](https://mochajs.org/)仅仅调用sanity测试集所需要做的:mocha --grep 'sanity'。
+
+**否则:** 运行所有的测试,包括执行数据库查询的几十个测试,任何时候开发者进行小的改动都可能很慢,这使得开发者不愿意运行测试。
+
+
+
+## ![✔] 4.6 检查测试覆盖率,它有助于识别错误的测试模式
+
+**TL;DR:** 代码覆盖工具比如[Istanbul/NYC ](https://github.com/gotwarlost/istanbul),很好用有3个原因:它是免费的(获得这份报告不需要任何开销),它有助于确定测试覆盖率降低的部分,以及最后但非最不重要的是它指出了测试中的不匹配:通过查看颜色标记的代码覆盖报告您可以注意到,例如,从来不会被测到的代码片段像catch语句(即测试只是调用正确的路径,而不调用应用程序发生错误时的行为)。如果覆盖率低于某个阈值,则将其设置为失败的构建。
+
+**否则:** 当你的大部分代码没有被测试覆盖时,就不会有任何自动化的度量指标告诉你了。
+
+
+
+
+
+## ![✔] 4.7 检查过期的依赖包
+
+**TL;DR:** 使用您的首选工具 (例如 “npm outdated” or [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) 来检测已安装的过期依赖包, 将此检查注入您的 CI 管道, 甚至在严重的情况下使构建失败。例如, 当一个已安装的依赖包滞后5个补丁时 (例如:本地版本是1.3.1 的, 存储库版本是1.3.8 的), 或者它被其作者标记为已弃用, 可能会出现严重的情况 - 停掉这次构建并防止部署此版本。
+
+**否则:** 您的生产环境将运行已被其作者明确标记为有风险的依赖包
+
+
+
+## ![✔] 4.8 对于 e2e testing,使用 docker-compose
+
+**TL;DR:** 端对端(e2e)测试包含现场数据,由于它依赖于很多重型服务如数据库,习惯被认为是CI过程中最薄弱的环节。Docker-compose通过制定类似生产的环境,并使用一个简单的文本文件和简单的命令,轻松化解了这个问题。它为了e2e测试,允许制作所有相关服务,数据库和隔离网络。最后但并非最不重要的一点是,它可以保持一个无状态环境,该环境在每个测试套件之前被调用,然后立即消失。
+
+
+**否则:** 没有docker-compose,团队必须维护一个测试数据库在每一个测试环境上,包含开发机器,保持所有数据同步,这样测试结果不会因环境不同而不同。
+
+
+
+
+⬆ 返回顶部
+
+# `5. 上线实践`
+## ![✔] 5.1. 监控!
+
+**TL;DR:** 监控是一种在顾客之前发现问题的游戏 – 显然这应该被赋予前所未有的重要性。考虑从定义你必须遵循的基本度量标准开始(我的建议在里面),到检查附加的花哨特性并选择解决所有问题的解决方案。市场已经淹没其中。点击下面的 ‘The Gist’ ,了解解决方案的概述。
+
+**否则:** 错误 === 失望的客户. 非常简单.
+
+
+🔗 [**更多: 监控!**](/sections/production/monitoring.chinese.md)
+
+
+
+## ![✔] 5.2. 使用智能日志增加透明度
+
+**TL;DR:** 日志可以是调试语句的一个不能说话的仓库,或者表述应用运行过程的一个漂亮仪表板的驱动。从第1天计划您的日志平台:如何收集、存储和分析日志,以确保所需信息(例如,错误率、通过服务和服务器等完成整个事务)都能被提取出来。
+
+**否则:** 您最终像是面对一个黑盒,不知道发生了什么事情,然后你开始重新写日志语句添加额外的信息。
+
+
+🔗 [**更多: 使用智能日志增加透明度**](/sections/production/smartlogging.chinese.md)
+
+
+
+## ![✔] 5.3. 委托一切可能的(例如:gzip,SSL)给反向代理
+
+**TL;DR:** node处理CPU密集型任务,如gzipping,SSL termination等,表现糟糕。相反,使用一个 ‘真正’ 的中间件服务像Nginx,HAProxy或者云供应商的服务。
+
+**否则:** 单线程的node服务器将不幸地忙于处理网络任务,而不是处理应用程序核心,性能会相应降低。
+
+
+🔗 [**更多: 委托一切可能的(例如:gzip,SSL)给反向代理**](/sections/production/delegatetoproxy.chinese.md)
+
+
+
+## ![✔] 5.4. 锁住依赖
+
+**TL;DR:** 您的代码必须在所有的环境中是相同的,但是令人惊讶的是,NPM默认情况下会让依赖在不同环境下发生偏移 – 当在不同的环境中安装包的时候,它试图拿包的最新版本。克服这种问题可以利用NPM配置文件, .npmrc,告诉每个环境保存准确的(不是最新的)包的版本。另外,对于更精细的控制,使用NPM “shrinkwrap”。*更新:作为NPM5,依赖默认锁定。新的包管理工具,Yarn,也默认锁定。
+
+**否则:** QA测试通过的代码和批准的版本,在生产中表现不一致。更糟糕的是,同一生产集群中的不同服务器可能运行不同的代码。
+
+
+🔗 [**更多: 锁住依赖**](/sections/production/lockdependencies.chinese.md)
+
+
+
+## ![✔] 5.5. 使用正确的工具保护进程正常运行
+
+**TL;DR:** 进程必须继续运行,并在失败时重新启动。对于简单的情况下,“重启”工具如PM2可能足够,但在今天的“Dockerized”世界 – 集群管理工具也值得考虑
+
+**否则:** 运行几十个实例没有明确的战略和太多的工具(集群管理,docker,PM2)可能导致一个DevOps混乱
+
+
+🔗 [**更多: 使用正确的工具保护进程正常运行**](/sections/production/guardprocess.chinese.md)
+
+
+
+
+## ![✔] 5.6. 利用CPU多核
+
+**TL;DR:** 在基本形式上,node应用程序运行在单个CPU核心上,而其他都处于空闲状态。复制node进程和利用多核,这是您的职责 – 对于中小应用,您可以使用Node Cluster和PM2. 对于一个大的应用,可以考虑使用一些Docker cluster(例如k8s,ECS)复制进程或基于Linux init system(例如systemd)的部署脚本
+
+**否则:** 您的应用可能只是使用了其可用资源中的25% (!),甚至更少。注意,一台典型的服务器有4个或更多的CPU,默认的Node.js部署仅仅用了一个CPU(甚至使用PaaS服务,比如AWS beanstalk,也一样)。
+
+
+🔗 [**更多: 利用所有的CPU**](/sections/production/utilizecpu.chinese.md)
+
+
+
+## ![✔] 5.7. 创建一个“维护端点”
+
+**TL;DR:** 在一个安全的API中暴露一组系统相关的信息,比如内存使用情况和REPL等等。尽管这里强烈建议依赖标准和作战测试工具,但一些有价值的信息和操作更容易使用代码完成。
+
+**否则:** 您会发现,您正在执行许多“诊断部署” – 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。
+
+
+🔗 [**更多: 创建一个 '维护端点'**](/sections/production/createmaintenanceendpoint.chinese.md)
+
+
+
+## ![✔] 5.8. 使用APM产品发现错误和宕机时间
+
+**TL;DR:** 监控和性能的产品(即APM)先前一步地评估代码库和API,自动的超过传统的监测,并测量在服务和层级上的整体用户体验。例如,一些APM产品可以突显导致最终用户负载过慢的事务,同时指出根本原因。
+
+**否则:** 你可能会花大力气测量API性能和停机时间,也许你永远不会知道,真实场景下哪个是你最慢的代码部分,这些怎么影响用户体验。
+
+
+🔗 [**更多: 使用APM产品发现错误和宕机时间**](/sections/production/apmproducts.chinese.md)
+
+
+
+
+
+## ![✔] 5.9. 使您的代码保持生产环境就绪
+
+**TL;DR:** 在意识中抱着最终上线的想法进行编码,从第1天开始计划上线。这听起来有点模糊,所以我编写了一些与生产维护密切相关的开发技巧(点击下面的要点)
+
+**否则:** 一个世界冠军级别的IT/运维人员也不能拯救一个编码低劣的系统。
+
+
+🔗 [**更多: 使您的代码保持生产环境就绪**](/sections/production/productoncode.chinese.md)
+
+
+
+## ![✔] 5.10. 测量和保护内存使用
+
+**TL;DR:** Node.js和内存有引起争论的联系:V8引擎对内存的使用有稍微的限制(1.4GB),在node的代码里面有内存泄漏的很多途径 – 因此监视node的进程内存是必须的。在小应用程序中,你可以使用shell命令周期性地测量内存,但在中等规模的应用程序中,考虑把内存监控建成一个健壮的监控系统。
+
+**否则:** 您的内存可能一天泄漏一百兆,就像曾发生在沃尔玛的一样。
+
+
+🔗 [**更多: 测量和保护内存使用**](/sections/production/measurememory.chinese.md)
+
+
+
+
+## ![✔] 5.11. Node外管理您的前端资源
+
+**TL;DR:** 使用专门的中间件(nginx,S3,CDN)服务前端内容,这是因为在处理大量静态文件的时候,由于node的单线程模型,它的性能很受影响。
+
+**否则:** 您的单个node线程将忙于传输成百上千的html/图片/angular/react文件,而不是分配其所有的资源为了其擅长的任务 – 服务动态内容
+
+
+🔗 [**更多: Node外管理您的前端资源**](/sections/production/frontendout.chinese.md)
+
+
+
+
+## ![✔] 5.12. 保持无状态,几乎每天都要停下服务器
+
+**TL;DR:** 在外部数据存储上,存储任意类型数据(例如用户会话,缓存,上传文件)。考虑间隔地停掉您的服务器或者使用 ‘serverless’ 平台(例如 AWS Lambda),这是一个明确的强化无状态的行为。
+
+**否则:** 某个服务器上的故障将导致应用程序宕机,而不仅仅是停用故障机器。此外,由于依赖特定服务器,伸缩弹性会变得更具挑战性。
+
+
+🔗 [**更多: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.chinese.md)
+
+
+
+
+
+## ![✔] 5.13. 使用自动检测漏洞的工具
+
+**TL;DR:** 即使是最有信誉的依赖项,比如Express,会有使系统处于危险境地的已知漏洞(随着时间推移)。通过使用社区的或者商业工具,不时的检查漏洞和警告(本地或者Github上),这类问题很容易被抑制,有些问题甚至可以立即修补。
+
+**否则:** 否则: 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物。相当繁琐。
+
+
+🔗 [**更多: 使用自动检测漏洞的工具**](/sections/production/detectvulnerabilities.chinese.md)
+
+
+
+
+## ![✔] 5.14. 在每一个log语句中指明 ‘TransactionId’
+
+**TL;DR:** 在每一个请求的每一条log入口,指明同一个标识符,transaction-id: {某些值}。然后在检查日志中的错误时,很容易总结出前后发生的事情。不幸的是,由于Node异步的天性自然,这是不容易办到的,看下代码里面的例子
+
+**否则:** 在没有上下文的情况下查看生产错误日志,这会使问题变得更加困难和缓慢去解决。
+
+
+🔗 [**更多: 在每一个log语句中指明 ‘TransactionId’**](/sections/production/assigntransactionid.chinese.md)
+
+
+
+
+## ![✔] 5.15. 设置NODE_ENV=production
+
+**TL;DR:** 设置环境变量NODE_ENV为‘production’ 或者 ‘development’,这是一个是否激活上线优化的标志 - 很多NPM的包通过它来判断当前的环境,据此优化生产环境代码。
+
+**否则:** 遗漏这个简单的属性可能大幅减弱性能。例如,在使用Express作为服务端渲染页面的时候,如果未设置NODE_ENV,性能将会减慢大概三分之一!
+
+
+🔗 [**更多: 设置NODE_ENV=production**](/sections/production/setnodeenv.chinese.md)
+
+
+
+
+
+## ![✔] 5.16. 设计自动化、原子化和零停机时间部署
+
+**TL;DR:** 研究表明,执行许多部署的团队降低了严重上线问题的可能性。不需要危险的手动步骤和服务停机时间的快速和自动化部署大大改善了部署过程。你应该达到使用Docker结合CI工具,使他们成为简化部署的行业标准。
+
+**否则:** 长时间部署 -> 线上宕机 & 和人相关的错误 -> 团队部署时不自信 -> 更少的部署和需求
+
+
+
+⬆ 返回顶部
+
+# `Security Practices`
+
+## Our contributors are working on this section. Would you like to join?
+
+
+# `Performance Practices`
+
+## Our contributors are working on this section. Would you like to join?
+
+
+
+
+# Milestones
+To maintain this guide and keep it up to date, we are constantly updating and improving the guidelines and best practices with the help of the community. You can follow our [milestones](https://github.com/i0natan/nodebestpractices/milestones) and join the working groups if you want to contribute to this project.
+
+
+
+# Contributors
+## `Yoni Goldberg`
+Independent Node.js consultant who works with customers at USA, Europe and Israel on building large-scale scalable Node applications. Many of the best practices above were first published on his blog post at [http://www.goldbergyoni.com](http://www.goldbergyoni.com). Reach Yoni at @goldbergyoni or me@goldbergyoni.com
+
+## `Ido Richter`
+👨💻 Software engineer, 🌐 web developer, 🤖 emojis enthusiast.
+
+## `Refael Ackermann` [@refack](https://github.com/refack) <refack@gmail.com> (he/him)
+Node.js Core Collaborator, been noding since 0.4, and have noded in multiple production sites. Founded `node4good` home of [`lodash-contrib`](https://github.com/node4good/lodash-contrib), [`formage`](https://github.com/node4good/formage), and [`asynctrace`](https://github.com/node4good/asynctrace).
+`refack` on freenode, Twitter, GitHub, GMail, and many other platforms. DMs are open, happy to help.
+
+## `Bruno Scheufler`
+💻 full-stack web developer and Node.js enthusiast.
+
+
+
+
+# Thank You Notes
+
+This repository is being kept up to date thanks to the help from the community. We appreciate any contribution, from a single word fix to a new best practice. Below is a list of everyone who contributed to this project. A :sunflower: marks a successful pull request and a :star: marks an approved new best practice.
+
+🌻 [Kevin Rambaud](https://github.com/kevinrambaud),
+🌻 [Michael Fine](https://github.com/mfine15),
+🌻 [Shreya Dahal](https://github.com/squgeim),
+🌻 [ChangJoo Park](https://github.com/ChangJoo-Park),
+🌻 [Matheus Cruz Rocha](https://github.com/matheusrocha89),
+🌻 [Yog Mehta](https://github.com/BitYog),
+🌻 [Kudakwashe Paradzayi](https://github.com/kudapara),
+🌻 [t1st3](https://github.com/t1st3),
+🌻 [mulijordan1976](https://github.com/mulijordan1976),
+🌻 [Matan Kushner](https://github.com/matchai),
+🌻 [Fabio Hiroki](https://github.com/fabiothiroki),
+🌻 [James Sumners](https://github.com/jsumners),
+🌻 [Chandan Rai](https://github.com/crowchirp),
+🌻 [Dan Gamble](https://github.com/dan-gamble),
+🌻 [PJ Trainor](https://github.com/trainorpj),
+🌻 [Remek Ambroziak](https://github.com/reod),
+🌻 [Yoni Jah](https://github.com/yonjah),
+🌻 [Misha Khokhlov](https://github.com/hazolsky),
+🌻 [Evgeny Orekhov](https://github.com/EvgenyOrekhov),
+🌻 [Gediminas Petrikas](https://github.com/gediminasml),
+🌻 [Isaac Halvorson](https://github.com/hisaac),
+🌻 [Vedran Karačić](https://github.com/vkaracic),
+🌻 [lallenlowe](https://github.com/lallenlowe),
+🌻 [Nathan Wells](https://github.com/nwwells),
+🌻 [Paulo Vítor S Reis](https://github.com/paulovitin),
+🌻 [syzer](https://github.com/syzer),
+🌻 [David Sancho](https://github.com/davesnx),
+🌻 [Robert Manolea](https://github.com/pupix),
+🌻 [Xavier Ho](https://github.com/spaxe),
+🌻 [Aaron Arney](https://github.com/ocularrhythm),
+🌻 [Jan Charles Maghirang Adona](https://github.com/septa97),
+🌻 [Allen Fang](https://github.com/AllenFang),
+🌻 [Leonardo Villela](https://github.com/leonardovillela),
+🌻 [Michal Zalecki](https://github.com/MichalZalecki)
+🌻 [Chris Nicola](https://github.com/chrisnicola)
+
+
+
+
+
+## :star: No Stars Yet, Waiting For The First To Suggest a New Bullet
diff --git a/sections/codestylepractices/eslint_prettier.chinese.md b/sections/codestylepractices/eslint_prettier.chinese.md
new file mode 100644
index 000000000..c8f32b8f5
--- /dev/null
+++ b/sections/codestylepractices/eslint_prettier.chinese.md
@@ -0,0 +1,26 @@
+# 使用 ESLint 和 Prettier
+
+
+### 比较 ESLint 和 Prettier
+
+如果你使用ESLint格式化代码,它只是给你一个警告,比如这一行太宽(取决于你的`最大长度`设置)。Prettier会自动为你格式化。
+
+```javascript
+foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe());
+```
+
+```javascript
+foo(
+ reallyLongArg(),
+ omgSoManyParameters(),
+ IShouldRefactorThis(),
+ isThereSeriouslyAnotherOne(),
+ noWayYouGottaBeKiddingMe()
+);
+```
+
+Source: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101)
+
+### Integrating ESLint and Prettier
+
+ESLint和Prettier在代码格式化功能上有重叠, 但它可以很容易通过其他的包来解决,比如 [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), and [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)。 有关他们的差异的更多信息,您可以查看链接 [here](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint).
diff --git a/sections/errorhandling/apmproducts.chinese.md b/sections/errorhandling/apmproducts.chinese.md
new file mode 100644
index 000000000..50441b732
--- /dev/null
+++ b/sections/errorhandling/apmproducts.chinese.md
@@ -0,0 +1,27 @@
+# 使用 APM 产品发现错误和宕机时间
+
+
+### 一段解释
+
+异常 != 错误。传统的错误处理假定存在异常,但应用程序错误可能以代码路径慢,API停机,缺少计算资源等形式出现。因为APM产品允许使用最小的设置来先前一步地检测各种各样 "深埋" 的问题,这是运用它们方便的地方。APM产品的常见功能包括: 当HTTP API返回错误时报警, 在API响应时间低于某个阈值时能被检测, 觉察到‘code smells’,监视服务器资源,包含IT度量的操作型智能仪表板以及其他许多有用的功能。大多数供应商提供免费方案。
+
+### 关于 APM 的维基百科
+
+在信息技术和系统管理领域, 应用程序性能管理(APM)是对软件应用程序的性能和可用性的监视和管理。APM努力检测和诊断复杂的应用程序性能问题, 以维护预期的服务级别。APM是"将IT度量标准转换为业务含义"
+
+### 了解 APM 市场
+
+APM 产品由3个主要部分构成:
+
+1. 网站或API监控 – 通过HTTP请求不断监视正常运行时间和性能的外部服务。可以在几分钟内安装。以下是少数选定的竞争者: [Pingdom](https://www.pingdom.com/), [Uptime Robot](https://uptimerobot.com/), 和[New Relic](https://newrelic.com/application-monitoring);
+
+2. 代码检测 – 这类产品需要在应用程序中嵌入代理, 以实现如检测运行缓慢的代码、异常统计、性能监视等功能。以下是少数选定的竞争者: New Relic, App Dynamics;
+
+3. 操作型智能仪表板 – 这些产品系列侧重于为ops团队提供度量和管理内容, 帮助他们轻松地保持应用程序性能维持在最佳状态。这通常涉及聚合多个信息源 (应用程序日志、DB日志、服务器日志等) 和前期仪表板设计工作。以下是少数选定的竞争者: [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/);
+
+
+ ### 示例: UpTimeRobot.Com – 网站监控仪表板
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard")
+
+ ### 示例: AppDynamics.Com – 与代码检测结合的端到端监视
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation")
diff --git a/sections/errorhandling/asyncerrorhandling.chinese.md b/sections/errorhandling/asyncerrorhandling.chinese.md
new file mode 100644
index 000000000..f168a4500
--- /dev/null
+++ b/sections/errorhandling/asyncerrorhandling.chinese.md
@@ -0,0 +1,56 @@
+# 对于异步的错误处理,请使用Async-Await或者promise
+
+
+### 一段解释
+
+由于回调对于大多数的程序员来说不熟悉,被迫随处检测错误,让人不快的代码内嵌和难以理解的代码流程,它没有形成一定规模。promise的库,比如BlueBird,async,和Q封装了一种标准的代码风格, 它通过使用return和throw来控制程序流程。具体来说,它们支持最受欢迎的try-catch错误处理风格,这使得主流程代码从在每一个方法中处理错误的方式中解放出来。
+
+
+### 代码示例 – 使用promise捕获错误
+
+
+```javascript
+doWork()
+ .then(doWork)
+ .then(doOtherWork)
+ .then((result) => doWork)
+ .catch((error) => {throw error;})
+ .then(verify);
+```
+
+### 代码示例 反模式 – 回调方式的错误处理
+
+```javascript
+getData(someParameter, function(err, result){
+ if(err != null)
+ //做一些事情类似于调用给定的回调函数并传递错误
+ getMoreData(a, function(err, result){
+ if(err != null)
+ //做一些事情类似于调用给定的回调函数并传递错误
+ getMoreData(b, function(c){
+ getMoreData(d, function(e){
+ if(err != null)
+ //你有什么想法?
+ });
+});
+```
+
+### 博客引用: "我们使用promise有一个问题"
+ 摘自博客pouchdb.com
+
+ > ……实际上, 回调会做一些更险恶的事情: 他们剥夺了我们的stack, 这是我们通常在编程语言中想当然的事情。编写没有堆栈的代码很像驾驶一辆没有刹车踏板的汽车: 你没有意识到你有多么需要它, 直到你伸手去找它, 而它不在那里。promise的全部目的是让我们回到我们在异步时丢失的语言基础: return,throw和stack。但你必须知道如何正确使用promise, 以便利用他们。
+
+### 博客引用: "promise方法更加紧凑"
+ 摘自博客gosquared.com
+
+ > ………promise的方法更紧凑, 更清晰, 写起来更快速。如果在任何ops中发生错误或异常,则由单个.catch()处理程序处理。有这个单一的地方来处理所有的错误意味着你不需要为每个阶段的工作写错误检查。
+
+### 博客引用: "原生ES6支持promise,可以和generator一起使用"
+ 摘自博客StrongLoop
+
+ > ….回调有一个糟糕的错误处理的报道。promise更好。将express内置的错误处理与promise结合起来, 大大降低了uncaught exception的几率。原生ES6支持promise, 通过编译器babel,它可以与generator,ES7提议的技术(比如async/await)一起使用。
+
+### 博客引用: "所有那些您所习惯的常规的流量控制结构, 完全被打破"
+ 摘自博客Benno’s
+
+ > ……关于基于异步、回调编程的最好的事情之一是, 基本上所有那些您习惯的常规流量控制结构, 完全被打破。然而, 我发现最易打破的是处理异常。Javascript提供了一个相当熟悉的try...catch结构来处理异常。异常的问题是, 它们提供了在一个调用堆栈上 short-cutting错误的很好的方法, 但最终由于不同堆栈上发生的错误导致完全无用…
diff --git a/sections/errorhandling/catchunhandledpromiserejection.chinese.md b/sections/errorhandling/catchunhandledpromiserejection.chinese.md
new file mode 100644
index 000000000..830d4bbd0
--- /dev/null
+++ b/sections/errorhandling/catchunhandledpromiserejection.chinese.md
@@ -0,0 +1,58 @@
+# 捕获未处理的promise rejections
+
+
+
+### 一段解释
+
+通常,大部分的现代node.js/express应用代码运行在promise里 – 或者是在.then里处理,一个回调函数中,或者在一个catch块中。令人惊讶的是,除非开发者记得添加.catch语句,在这些地方抛出的错误都不会被uncaughtException事件处理程序来处理,然后消失掉。当未处理的rejection出现,node最近的版本增加了一个警告消息,尽管当事情出错的时候这可能有助于发现问题,但这显然不是一个适当的错误处理方法。简单明了的解决方案是永远不要忘记在每个promise链式调用中添加.catch语句,并重定向到一个集中的错误处理程序。然而,只在开发人员的规程上构建错误处理策略是有些脆弱的。因此,使用一个优雅的回调并订阅到process.on('unhandledrejection',callback)是高度推荐的 – 这将确保任何promise错误,如果不是本地处理,将在这处理。
+
+
+
+### 代码示例: 这些错误将不会得到任何错误处理程序捕获(除unhandledrejection)
+
+```javascript
+DAL.getUserById(1).then((johnSnow) =>
+{
+ //this error will just vanish
+ if(johnSnow.isAlive == false)
+ throw new Error('ahhhh');
+});
+
+```
+
+### 代码示例: 捕获 unresolved 和 rejected 的 promise
+
+```javascript
+process.on('unhandledRejection', (reason, p) => {
+ //我刚刚捕获了一个未处理的promise rejection, 因为我们已经有了对于未处理错误的后备的处理机制(见下面), 直接抛出,让它来处理
+ throw reason;
+});
+process.on('uncaughtException', (error) => {
+ //我刚收到一个从未被处理的错误,现在处理它,并决定是否需要重启应用
+ errorManagement.handler.handleError(error);
+ if (!errorManagement.handler.isTrustedError(error))
+ process.exit(1);
+});
+
+```
+
+### 博客引用: "如果你犯了错误,在某个时候你就会犯错误。"
+ 摘自 James Nelson 的博客
+
+ > 让我们测试一下您的理解。下列哪一项是您期望错误将会打印到控制台的?
+
+```javascript
+Promise.resolve(‘promised value’).then(() => {
+ throw new Error(‘error’);
+});
+
+Promise.reject(‘error value’).catch(() => {
+ throw new Error(‘error’);
+});
+
+new Promise((resolve, reject) => {
+ throw new Error(‘error’);
+});
+```
+
+> 我不知道您的情况,但我的回答是我希望它们所有都能打印出一个错误。然而,现实是许多现代JavaScript环境不会为其中任何一个打印错误。做为人的问题是,如果你犯了错误,在某个时候你就会犯错误。记住这一点,很显然,我们应该设计这样一种方式,使错误尽可能少创造伤害,这意味着默认地处理错误,而不是丢弃错误。
diff --git a/sections/errorhandling/centralizedhandling.chinese.md b/sections/errorhandling/centralizedhandling.chinese.md
new file mode 100644
index 000000000..1f7d4214d
--- /dev/null
+++ b/sections/errorhandling/centralizedhandling.chinese.md
@@ -0,0 +1,83 @@
+# 集中处理错误,通过但不是在中间件里处理错误
+
+
+### 一段解释
+
+如果没有一个专用的错误处理对象,那么由于操作不当,在雷达下重要错误被隐藏的可能性就会更大。错误处理对象负责使错误可见,例如通过写入一个格式化良好的logger,通过电子邮件将事件发送到某个监控产品或管理员。一个典型的错误处理流程可能是:一些模块抛出一个错误 -> API路由器捕获错误 -> 它传播错误给负责捕获错误的中间件(如Express,KOA)-> 集中式错误处理程序被调用 -> 中间件正在被告之这个错误是否是一个不可信的错误(不是操作型错误),这样可以优雅的重新启动应用程序。注意,在Express中间件中处理错误是一种常见但又错误的做法,这样做不会覆盖在非Web接口中抛出的错误。
+
+
+
+### 代码示例 – 一个典型错误流
+
+```javascript
+//DAL层, 在这里我们不处理错误
+DB.addDocument(newCustomer, (error, result) => {
+ if (error)
+ throw new Error("Great error explanation comes here", other useful parameters)
+});
+
+//API路由代码, 我们同时捕获异步和同步错误,并转到中间件
+try {
+ customerService.addNew(req.body).then(function (result) {
+ res.status(200).json(result);
+ }).catch((error) => {
+ next(error)
+ });
+}
+catch (error) {
+ next(error);
+}
+
+//错误处理中间件,我们委托集中式错误处理程序处理错误
+app.use(function (err, req, res, next) {
+ errorHandler.handleError(err).then((isOperationalError) => {
+ if (!isOperationalError)
+ next(err);
+ });
+});
+
+```
+
+### 代码示例 – 在一个专门的对象里面处理错误
+
+```javascript
+module.exports.handler = new errorHandler();
+
+function errorHandler(){
+ this.handleError = function (error) {
+ return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError);
+ }
+
+```
+
+### 代码示例 – 反模式:在中间件内处理错误
+
+```javascript
+//中间件直接处理错误,那谁将处理Cron任务和测试错误呢?
+app.use(function (err, req, res, next) {
+ logger.logError(err);
+ if(err.severity == errors.high)
+ mailer.sendMail(configuration.adminMail, "Critical error occured", err);
+ if(!err.isOperational)
+ next(err);
+});
+
+```
+
+### 博客引用: "有时较低的级别不能做任何有用的事情, 除非将错误传播给他们的调用者"
+ 摘自博客 Joyent, 对应关键字 “Node.JS error handling” 排名第一
+
+ > …您可能会在stack的多个级别上处理相同的错误。这发生在当较低级别不能执行任何有用的操作,除了将错误传播给它们的调用方, 从而将错误传播到其调用方, 等等。通常, 只有top-level调用方知道适当的响应是什么, 无论是重试操作、向用户报告错误还是其他事情。但这并不意味着您应该尝试将所有错误报告给单个top-level回调, 因为该回调本身无法知道错误发生在什么上下文中…
+
+
+### 博客引用: "单独处理每个错误将导致大量的重复"
+ 摘自博客 JS Recipes, 对应关键字 “Node.JS error handling” 排名17
+
+ > ……仅仅在Hackathon启动api.js控制器中, 有超过79处重复的错误对象。单独处理每个错误将导致大量的代码重复。您可以做的下一个最好的事情是将所有错误处理逻辑委派给一个express中间件…
+
+
+### 博客引用: "HTTP错误不会在数据库代码中出现"
+ 摘自博客 Daily JS, 对应关键字 “Node.JS error handling” 排名14
+
+ > ……您应该在error对象中设置有用的属性, 但使用此类属性时应保持一致。而且, 不要越过流: HTTP错误不会在数据库代码中出现。或者对于浏览器开发人员来说, Ajax 错误在与服务器交互的代码中有一席之地, 而不是处理Mustache模板的代码…
+
diff --git a/sections/errorhandling/documentingusingswagger.chinese.md b/sections/errorhandling/documentingusingswagger.chinese.md
new file mode 100644
index 000000000..57db0bcf5
--- /dev/null
+++ b/sections/errorhandling/documentingusingswagger.chinese.md
@@ -0,0 +1,16 @@
+# 使用Swagger对API错误文档化
+
+
+### 一段解释
+
+REST API使用HTTP代码返回结果, API用户不仅绝对需要了解API schema, 而且还要注意潜在错误 – 调用方可能会捕获错误并巧妙地处理它。例如, 您的api文档可能提前指出, 当客户名称已经存在时, HTTP状态409将返回 (假设api注册新用户), 因此调用方可以相应地呈现给定情况下的最佳UX。Swagger是一个标准, 它定义了 API 文档的schema, 提供了一个生态系统的工具, 允许在线轻松创建文档, 请参阅下面的打印屏幕。
+
+### 博客引用: "您必须告诉您的调用者什么错误可能发生"
+ 摘自博客 Joyent, 对于关键字 “Node.JS logging” , 排名第一
+
+ > 我们已经讨论了如何处理错误, 但是在编写新函数时, 如何将错误传递给调用您的函数的代码?
+...如果你不知道会发生什么错误或者不知道他们的意思, 那么你的程序就不可能是正确的, 除非是偶然的。所以, 如果你正在写一个新的函数, 你必须告诉你的调用者什么错误可以发生, 它们的意思是什么…
+
+
+ ### 有用的工具: Swagger 在线文档创建工具
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling")
\ No newline at end of file
diff --git a/sections/errorhandling/failfast.chinese.md b/sections/errorhandling/failfast.chinese.md
new file mode 100644
index 000000000..5055d1ad5
--- /dev/null
+++ b/sections/errorhandling/failfast.chinese.md
@@ -0,0 +1,50 @@
+# 快速报错,使用专用库验证参数
+
+
+### 一段解释
+
+我们都知道如何检查参数和快速报错对于避免隐藏的错误很重要(见下面的反模式代码示例)。如果没有,请阅读显式编程和防御性编程。在现实中,由于对其编码是件恼人的事情(比如考虑验证分层的JSON对象,它包含像email和日期这样的字段),我们倾向于避免做这样的事情 – 像Joi这样的库和验证器轻而易举的处理这个乏味的任务。
+
+### 维基百科: 防御性编程
+
+防御性编程是一种改进软件和源代码的方法, 在以下方面: 一般质量 – 减少软件 bug 和问题的数量。使源代码可理解 – 源代码应该是可读的和可理解的, 以便在代码审核中得到批准。尽管会有意外输入或用户操作, 但使软件的行为具有可预知的方式。
+
+
+
+### 代码示例: 使用‘Joi’验证复杂的JSON输入
+
+```javascript
+var memberSchema = Joi.object().keys({
+ password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
+ birthyear: Joi.number().integer().min(1900).max(2013),
+ email: Joi.string().email()
+});
+
+function addNewMember(newMember)
+{
+ //assertions come first
+ Joi.assert(newMember, memberSchema); //throws if validation fails
+ //other logic here
+}
+
+```
+
+### 反模式: 没有验证会产生令人讨厌的错误
+
+```javascript
+//假如折扣为正,重定向用户去打印他的折扣优惠劵
+function redirectToPrintDiscount(httpResponse, member, discount)
+{
+ if(discount != 0)
+ httpResponse.redirect(`/discountPrintView/${member.id}`);
+}
+
+redirectToPrintDiscount(httpResponse, someMember);
+//忘记传递参数discount, 为什么用户被重定向到折扣页面?
+
+```
+
+### 博客引用: "您应该立即抛出这些错误"
+ 摘自博客: Joyent
+
+ > 一个退化情况是有人调用一个异步函数但没有传递一个回调方法。你应该立即抛出这些错误, 因为程序有了错误, 最好的调试它的时机包括,获得至少一个stack trace, 和理想情况下,核心文件里错误的点。为此, 我们建议在函数开始时验证所有参数的类型。
\ No newline at end of file
diff --git a/sections/errorhandling/monitoring.chinese.md b/sections/errorhandling/monitoring.chinese.md
new file mode 100644
index 000000000..724dc913e
--- /dev/null
+++ b/sections/errorhandling/monitoring.chinese.md
@@ -0,0 +1,18 @@
+# 监控
+
+
+### 一段解释
+
+> 在最基本的层面上,监控意味着您可以很*容易地识别出在生产环境中发生了什么不好的事情,例如,通过电子邮件或Slack通知。挑战在于选择合适的工具集来满足您的需求而不会破坏您的防护。我建议,从确定核心的指标集开始,这些指标必须被监控以确保一个健康的状态 – CPU,服务器的RAM,node进程RAM(小于1.4GB),在最后一分钟的错误量,进程重新启动的数量,平均响应时间。然后浏览一些你可能喜欢的高级功能并添加到你的愿望清单中。一些豪华的监控功能的例子:数据库分析,跨服务的测量(即测量业务交易),前端整合,暴露原始数据给自定义的BI clients,Slack通知及其他。
+
+实现高级功能需要冗长的设置或购买商业产品如datadog,NewRelic和相似产品。不幸的是,即使是基本的实现也不像在公园散步那么简单,因为一些度量指标是硬件相关的(CPU),而其他的则在node进程内(内部错误),因此所有直接了当的工具都需要一些额外的设置。例如,云供应商监控解决方案(如AWS CloudWatch,谷歌Stackdriver)将立即告诉你关于硬件度量,但对内部应用程序的行为却无可奉告。在另一端,基于日志的解决方案如Elasticsearch默认情况下缺少hardware view。解决方案是用缺少的指标来增加您的选择,例如,一个流行的选择是将应用程序日志发送到Elastic stack,并配置一些额外的代理(如Beat)来共享与硬件相关的信息以获得完整的画面。
+
+### 博客引用: "我们对于promise有一个问题"
+ 摘自博客 pouchdb.com, 对于关键字“node promises”,排名11
+
+ > … 我们建议您为所有服务监视这些信号:
+错误率:因为错误是面向用户的,并且会立即影响您的客户。
+响应时间:因为延迟直接影响您的客户和业务。
+吞吐量:流量有助于您了解错误率增加和延迟的上下文。
+饱和度:它告诉您的服务负载多少。如果CPU使用率是90%,你的系统能处理更多的流量吗?
+…
diff --git a/sections/errorhandling/operationalvsprogrammererror.chinese.md b/sections/errorhandling/operationalvsprogrammererror.chinese.md
new file mode 100644
index 000000000..a68f94151
--- /dev/null
+++ b/sections/errorhandling/operationalvsprogrammererror.chinese.md
@@ -0,0 +1,51 @@
+# 区分操作型错误和程序型错误
+
+### 一段解释
+
+区分以下两种错误类型将最大限度地减少应用程序停机时间并帮助避免出现荒唐的错误: 操作型错误指的是您了解发生了什么情况及其影响的情形 – 例如, 由于连接问题而导致对某些 HTTP 服务的查询失败问题。另一方面, 程序型错误指的是您不知道原因, 有时是错误不知道来自何处的情况 – 可能是一些代码试图读取未定义的值或 DB 连接池内存泄漏。操作型错误相对容易处理 – 通常记录错误就足够了。当程序型错误出现,事情变得难以应付, 应用程序可能处于不一致状态, 你可以做的,没有什么比优雅的重新启动更好了。
+
+
+
+### 代码示例 – 将错误标记为可操作 (受信任)
+
+```javascript
+//将错误标记为可操作
+var myError = new Error("How can I add new product when no value provided?");
+myError.isOperational = true;
+
+//或者, 如果您使用的是一些集中式错误工厂 (请参见项目符号中的示例"仅使用内置错误对象")
+function appError(commonType, description, isOperational) {
+ Error.call(this);
+ Error.captureStackTrace(this);
+ this.commonType = commonType;
+ this.description = description;
+ this.isOperational = isOperational;
+};
+
+throw new appError(errorManagement.commonErrors.InvalidInput, "Describe here what happened", true);
+
+```
+
+### 博客引用: "程序型错误是程序中的 bug"
+ 摘自博客 Joyent, 对于关键字“Node.JS error handling”排名第一
+
+ > …从程序型错误中恢复的最好方法是立即崩溃。您应该使用restarter运行程序, 以便在发生崩溃时自动重新启动程序。在一个使用了restarter的地方, 在面对一个瞬态程序型错误, 崩溃是最快的方式来恢复可靠的服务…
+
+ ### 博客引用: "不伴随着创建一些未定义的脆性状态,没有安全的方式可以离开"
+ 摘自Node.JS官方文档
+
+ > …在 JavaScript 中, throw的工作性质, 几乎没有任何方法可以安全地"在你离开的地方重新捡起",没有泄漏引用, 或者创建一些其他形式的未定义的脆性状态,。对引发的错误进行响应的最安全方法是关闭进程。当然, 在普通的 web 服务器中, 您可能会打开许多连接, 并且由于其他人触发了错误而突然关闭这些连接是不合理的。更好的方法是向触发错误的请求发送错误响应, 同时让其他人在正常时间内完成, 并停止侦听该工作人员中的新请求。
+
+
+ ### 博客引用: "否则,您置您应用的状态于风险之中"
+ 摘自博客 debugable.com, 对于关键字“Node.JS uncaught exception”排名第3
+
+ > …所以, 除非你真的知道你在做什么, 否则你应该在收到一个"uncaughtException"异常事件之后, 对你的服务进行一次优雅的重新启动。否则, 您应用的状态, 或和第三方库的状态变得不一致, 都被置于风险之中,导致各种荒唐的错误…
+
+ ### 博客引用: "对于错误处理,有三种学院派想法"
+ 摘自博客: JS Recipes
+
+ > …对于错误处理,主要有三种学院派想法:
+1. 让应用崩溃并重启.
+2. 处理所有可能的错误,从不崩溃.
+3. 两者之间的折中方案
diff --git a/sections/errorhandling/shuttingtheprocess.chinese.md b/sections/errorhandling/shuttingtheprocess.chinese.md
new file mode 100644
index 000000000..5de0faaba
--- /dev/null
+++ b/sections/errorhandling/shuttingtheprocess.chinese.md
@@ -0,0 +1,54 @@
+# 特殊情况产生时,优雅地退出服务
+
+
+### 一段解释
+
+在您的代码的某个地方,当一个错误抛出的时候,错误处理对象负责决定如何进行时 – 如果错误是可信的(即操作型错误,在最佳实践#3了解进一步的解释),写入日志文件可能是足够的。如果错误不熟悉,事情就变得棘手了 – 这意味着某些组件可能处于故障状态,所有将来的请求都可能失败。例如,假设一个单例(singleton)的,有状态的令牌发行者服务抛出异常并失去它的状态 — 从现在起,它可能会出现意外行为并导致所有请求失败。在这种情况下,杀进程,使用“重启”的工具(像Forever,PM2,等等)重新开始。
+
+
+
+### 代码实例: 决定是否退出
+
+```javascript
+//收到未捕获的异常时,决定是否要崩溃
+//如果开发人员标记已知的操作型错误使用:error.isOperational=true, 查看最佳实践 #3
+process.on('uncaughtException', function(error) {
+ errorManagement.handler.handleError(error);
+ if(!errorManagement.handler.isTrustedError(error))
+ process.exit(1)
+});
+
+
+//封装错误处理相关逻辑在集中的错误处理中
+function errorHandler(){
+ this.handleError = function (error) {
+ return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError);
+ }
+
+ this.isTrustedError = function(error)
+ {
+ return error.isOperational;
+ }
+
+```
+
+
+### 博客引用: "最好的方式是立即崩溃"
+摘自 博客:Joyent
+
+ > …从程序型错误中恢复过来的最好方法是立即崩溃。你应该使用一个重启助手来运行您的程序,它会在崩溃的情况下自动启动程序。当使用重启助手,崩溃是面对临时性的程序型错误时,恢复可靠的服务的最快的方法…
+
+
+### 博客引用: "错误处理有三种流派"
+摘自 博客:JS Recipes
+
+ > …错误处理主要有三种流派:
+1. 让应用崩溃,并重启。
+2. 处理所有的错误,从不崩溃。
+3. 介于两者之间。
+
+
+### 博客引用: "不伴随着创建一些易碎的状态,是没有保险的方式退出"
+摘自 Node.JS 官方文档
+
+ > …就throw工作在JavaScript的本质而言,几乎没有任何方法可以安全地“在您丢下的地方捡起”,而不会泄漏引用,或者创建其他类型的未定义的易碎性状态。对抛出的错误作出响应的最安全的方法是关闭进程。当然,在一个普通的Web服务器中,可能有很多连接打开了,因为其他人触发了一个错误,所以突然关闭这些连接是不合理的。更好的方法是将错误响应发送给触发错误的请求,同时让其他人在正常时间内完成,并停止侦听该工作者的新请求。
\ No newline at end of file
diff --git a/sections/errorhandling/testingerrorflows.chinese.md b/sections/errorhandling/testingerrorflows.chinese.md
new file mode 100644
index 000000000..eadd073e3
--- /dev/null
+++ b/sections/errorhandling/testingerrorflows.chinese.md
@@ -0,0 +1,37 @@
+# 使用您喜欢的测试框架测试错误流
+
+
+### 一段解释
+
+测试‘正确’路径并不比测试失败更好。良好的测试代码覆盖率要求测试异常路径。否则,异常确实被处理正确是不可信的。每个单元测试框架,如[Mocha](https://mochajs.org/) & [Chai](http://chaijs.com/),都支持异常测试(请看下面的代码示例)。如果您觉得测试每个内部函数和异常都很乏味,那么您可以只测试REST API HTTP错误。
+
+
+
+### 代码示例: 使用 Mocha & Chai 确保正确的异常被抛出
+
+```javascript
+describe("Facebook chat", () => {
+ it("Notifies on new chat message", () => {
+ var chatService = new chatService();
+ chatService.participants = getDisconnectedParticipants();
+ expect(chatService.sendMessage.bind({message: "Hi"})).to.throw(ConnectionError);
+ });
+});
+
+```
+
+### 代码示例: 确保 API 返回正确的 HTTP 错误码
+
+```javascript
+it("Creates new Facebook group", function (done) {
+ var invalidGroupInfo = {};
+ httpRequest({method: 'POST', uri: "facebook.com/api/groups", resolveWithFullResponse: true, body: invalidGroupInfo, json: true
+ }).then((response) => {
+ //oh no if we reached here than no exception was thrown
+ }).catch(function (response) {
+ expect(400).to.equal(response.statusCode);
+ done();
+ });
+ });
+
+```
\ No newline at end of file
diff --git a/sections/errorhandling/usematurelogger.chinese.md b/sections/errorhandling/usematurelogger.chinese.md
new file mode 100644
index 000000000..1dd751119
--- /dev/null
+++ b/sections/errorhandling/usematurelogger.chinese.md
@@ -0,0 +1,54 @@
+# 使用成熟的logger提高错误可见性
+
+### 一段解释
+
+我们都特别喜欢(loovve)console.log,但显而易见地,对于严肃的项目, 有信誉和持久的Logger是必需的,比如[Winston][winston], [Bunyan][bunyan] (非常流行) or [Pino][pino](专注于性能的新库)。一套实践和工具将有助于更快速地解释错误 – (1)使用不同的级别(debug, info, error)频繁地log;(2)在记录日志时, 以 JSON 对象的方式提供上下文信息, 请参见下面的示例;(3)使用日志查询API(在大多数logger中内置)或日志查看程序软件监视和筛选日志;(4)使用操作智能工具(如 Splunk)为操作团队公开和管理日志语句。
+
+[winston]: https://www.npmjs.com/package/winston
+[bunyan]: https://www.npmjs.com/package/bunyan
+[pino]: https://www.npmjs.com/package/pino
+
+### 代码示例 – 使用Winston Logger
+
+```javascript
+//您的集中式logger对象
+var logger = new winston.Logger({
+ level: 'info',
+ transports: [
+ new (winston.transports.Console)(),
+ new (winston.transports.File)({ filename: 'somefile.log' })
+ ]
+});
+
+//在某个地方使用logger的自定义代码
+logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', { anything: 'This is metadata' });
+
+```
+
+### 代码示例 – 查询日志文件夹 (搜索条目)
+
+```javascript
+var options = {
+ from: new Date - 24 * 60 * 60 * 1000,
+ until: new Date,
+ limit: 10,
+ start: 0,
+ order: 'desc',
+ fields: ['message']
+ };
+
+
+ // 查找在今天和昨天之间记录的项目
+ winston.query(options, function (err, results) {
+ //对于结果的回调处理
+ });
+
+```
+
+### 博客引用: "Logger要求"
+ 摘自博客 Strong Loop
+
+ > 让我们确定一些要求 (对于logger):
+1. 为每条日志添加时间戳。这条很好自我解释-你应该能够告知每个日志条目发生在什么时候。
+2. 日志格式应易于被人类和机器理解。
+3. 允许多个可配置的目标流。例如, 您可能正在将trace log写入到一个文件中, 但遇到错误时, 请写入同一文件, 然后写入到错误日志文件,并同时发送电子邮件…
diff --git a/sections/errorhandling/useonlythebuiltinerror.chinese.md b/sections/errorhandling/useonlythebuiltinerror.chinese.md
new file mode 100644
index 000000000..6473ff196
--- /dev/null
+++ b/sections/errorhandling/useonlythebuiltinerror.chinese.md
@@ -0,0 +1,78 @@
+# 仅使用内建的错误对象
+
+
+### 一段解释
+
+js天生的宽容性及其多变的代码流选项(例如 EventEmitter, Callbacks, Promises等等)迫使开发人员怎么去引发错误时有多的不一致 – 有些人使用字符串,有些人使用自定义的类型。使用Node.js的内置错误对象有助于在你的代码和第三方库之间保持一致性,它还保留了重要信息,比如StackTrace。当引发异常时,这通常是一个好的习惯去使用附加的上下文属性(如错误名称和相关的HTTP错误代码)填充异常。要实现这种一致性和实践,请考虑使用附加属性扩展错误对象,见下面的代码示例。
+
+博客引用:“I don’t see the value in having lots of different types”
+
+摘自博客Ben Nadel, 对于关键字“Node.JS错误对象”,排名第五
+
+…就我个人而言,我不认为有很多不同类型的错误对象的价值 – JavaScript作为一种语言,似乎不符合基于构造函数的错误捕获。因此,区分对象属性似乎比在构造函数类型上区分要容易得多…
+
+
+
+### 代码示例 – 正确处理它
+
+```javascript
+//从典型函数抛出错误, 无论是同步还是异步
+ if(!productToAdd)
+ throw new Error("How can I add new product when no value provided?");
+
+//从EventEmitter抛出错误
+const myEmitter = new MyEmitter();
+myEmitter.emit('error', new Error('whoops!'));
+
+//从promise抛出错误
+ return new promise(function (resolve, reject) {
+ Return DAL.getProduct(productToAdd.id).then((existingProduct) => {
+ if(existingProduct != null)
+ reject(new Error("Why fooling us and trying to add an existing product?"));
+
+```
+
+### 代码示例 – 反模式
+
+```javascript
+//抛出字符串错误缺少任何stack trace信息和其他重要属性
+if(!productToAdd)
+ throw ("How can I add new product when no value provided?");
+
+```
+
+### 代码示例 – 更好处理它
+
+```javascript
+//从node错误派生的集中错误对象
+function appError(name, httpCode, description, isOperational) {
+ Error.call(this);
+ Error.captureStackTrace(this);
+ this.name = name;
+ //...在这赋值其它属性
+};
+
+appError.prototype.__proto__ = Error.prototype;
+
+module.exports.appError = appError;
+
+//客户端抛出一个错误
+if(user == null)
+ throw new appError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, "further explanation", true)
+```
+
+
+### 博客引用: "字符串不是错误"
+ 摘自博客 devthought.com, 对于关键字 “Node.JS error object” 排名第6
+
+ > …传递字符串而不是错误导致模块间协作性降低。它打破了和API的约定,可能是执行instanceof Error这样的检查,或想了解更多关于错误的信息。正如我们将看到的,错误对象在现代JavaScript引擎中拥有非常有趣的属性,同时保留传递给构造函数的消息…
+
+### 博客引用: "从Error对象继承不会增加太多的值"
+ 摘自博客 machadogj
+
+ > …我对Error类的一个问题是不太容易扩展。当然, 您可以继承该类并创建自己的Error类, 如HttpError、DbError等。然而, 这需要时间, 并且不会增加太多的价值, 除非你是在做一些关于类型的事情。有时, 您只想添加一条消息, 并保留内部错误, 有时您可能希望使用参数扩展该错误, 等等…
+
+ ### 博客引用: "所有由node.js引发的 JavaScript 和系统错误继承自Error对象"
+ 摘自 Node.JS 官方文档
+
+ > …所有由node.js引发的JavaScript和系统错误继承自,或是JavaScript标准错误类的实例, 这保证至少提供了该类的可用属性。一个通用的JavaScript错误对象, 它不表示错误为什么发生的任何特定环境。错误对象捕获一个"stack trace", 详细说明了错误被实例化时在代码中的点, 并可能提供错误的文本描述。由node.js生成的所有错误, 包括所有的系统和JavaScript错误, 都将是Error类的实例, 或继承自Error类…
diff --git a/sections/production/apmproducts.chinese.md b/sections/production/apmproducts.chinese.md
new file mode 100644
index 000000000..ebe06b011
--- /dev/null
+++ b/sections/production/apmproducts.chinese.md
@@ -0,0 +1,26 @@
+# 使用 APM 产品确保用户体验
+
+
+
+
+### 一段解释
+
+APM(应用程序性能监视)指的是一个产品系列, 目的是从端到端,也从客户的角度监控应用程序的性能。虽然传统的监控解决方案侧重于异常和独立的技术指标 (例如错误跟踪、检测慢速服务器端点等), 在现实世界中, 我们的应用程序可能会在没有任何代码异常的情况下让用户使用起来感到失望, 例如, 如果某些中间件服务执行得非常慢。APM 产品从端到端检测用户体验, 例如, 给定一个包含前端 UI 和多个分布式服务的系统 – 一些 APM 产品可以告诉您, 一个跨过多个层的事务的速度有多快。它可以判断用户体验是否可靠, 并指出问题所在。这种诱人的产品通常有一个相对较高的价格标签, 因此, 对于需要超越一般的监测的,大规模的和复杂的产品, 它们是值得推荐的。
+
+
+
+
+### APM 示例 – 一种可视化跨服务应用性能的商业产品
+![APM example](/assets/images/apm1.png "APM example")
+
+
+
+### APM 示例 – 一种强调用户体验评分的商业产品
+
+![APM example](/assets/images/apm2.png "APM example")
+
+
+
+### APM 示例 – 一种突出显示慢速代码路径的商业产品
+
+![APM example](/assets/images/apm3.png "APM example")
diff --git a/sections/production/assigntransactionid.chinese.md b/sections/production/assigntransactionid.chinese.md
new file mode 100644
index 000000000..e0319aa7b
--- /dev/null
+++ b/sections/production/assigntransactionid.chinese.md
@@ -0,0 +1,46 @@
+# 在每一个log语句指定‘TransactionId’
+
+
+
+
+### 一段解释
+
+一个典型的日志是来自所有组件和请求的条目的仓库。当检测到一些可疑行或错误时,为了与其他属于同一特定流程的行(如用户“约翰”试图购买某物)相匹配,就会变得难以应付。特别在微服务环境下,当一个请求/交易可能跨越多个计算机,这变得更加重要和具有挑战性。解决这个问题,可以通过指定一个唯一的事务标识符给从相同的请求过来的所有条目,这样当检测到一行,可以复制这个id,并搜索包含这个transaction id的每一行。但是,在node中实现这个不是那么直截了当的,这是由于它的单线程被用来服务所有的请求 – 考虑使用一个库,它可以在请求层对数据进行分组 – 在下一张幻灯片查看示例代码。当调用其它微服务,使用HTTP头“x-transaction-id”传递transaction id去保持相同的上下文。
+
+
+
+
+### 代码示例: 典型的nginx配置
+
+```javascript
+//当接收到一个新的要求,开始一个新的隔离的上下文和设置一个事务transaction id。下面的例子是使用NPM库continuation-local-storage去隔离请求
+
+const { createNamespace } = require('continuation-local-storage');
+var session = createNamespace('my session');
+
+router.get('/:id', (req, res, next) => {
+ session.set('transactionId', 'some unique GUID');
+ someService.getById(req.params.id);
+ logger.info('Starting now to get something by Id');
+});
+
+//现在, 任何其他服务或组件都可以访问上下文、每个请求、数据
+class someService {
+ getById(id) {
+ logger.info(“Starting now to get something by Id”);
+ //其它逻辑
+ }
+}
+
+//Logger现在可以将事务 id 追加到每个条目, 以便同一请求中的项将具有相同的值
+class logger{
+ info (message)
+ {console.log(`${message} ${session.get('transactionId')}`);}
+}
+```
+
+
+
+### 其他博主说什么
+摘自博客 [ARG! TEAM](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load):
+> ...Although express.js has built in static file handling through some connect middleware, you should never use it. *Nginx can do a much better job of handling static files and can prevent requests for non-dynamic content from clogging our node processes*...
diff --git a/sections/production/bestateless.chinese.md b/sections/production/bestateless.chinese.md
new file mode 100644
index 000000000..045a4ad46
--- /dev/null
+++ b/sections/production/bestateless.chinese.md
@@ -0,0 +1,42 @@
+# 保存无状态,几乎每天停掉服务器
+
+
+
+
+### 一段解释
+
+你曾经有没有遇到一类严重的线上问题,比如一个服务器丢失了一些配置或数据?这可能是由于对于不属于部署部分的本地资源的一些不必要的依赖。许多成功的产品对待服务器就像凤凰鸟–它周期性地死亡和重生不带来任何损伤。换句话说,服务器只是一个硬件,执行你的代码一段时间后,可以更换。
+这个方法:
+- 允许动态添加和删除服务器,无任何负面影响;
+- 简化了维护,因为它使我们不必费精力对每个服务器状态进行评估。
+
+
+
+
+### 代码示例: 反模式
+
+```javascript
+//典型错误1: 保存上传文件在本地服务器上
+var multer = require('multer') // 处理multipart上传的express中间件
+var upload = multer({ dest: 'uploads/' })
+
+app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {})
+
+//典型错误2: 在本地文件或者内存中,保存授权会话(密码)
+var FileStore = require('session-file-store')(session);
+app.use(session({
+ store: new FileStore(options),
+ secret: 'keyboard cat'
+}));
+
+//典型错误3: 在全局对象中保存信息
+Global.someCacheLike.result = {somedata}
+```
+
+
+
+### 其他博客作者说什么
+摘自博客 [Martin Fowler](https://martinfowler.com/bliki/PhoenixServer.html):
+> ...某天,我有了启动一个对操作的认证服务的幻想。认证评估将由我和一位同事出现在企业数据中心,并通过一个棒球棒,一个电锯和一把水枪设置关键生产服务器。评估将基于操作团队需要多长时间才能重新运行所有应用程序。这可能是一个愚蠢的幻想,但有一个真正的智慧在这里。而你应该放弃棒球棒,去定期的几乎烧毁你的服务器,这是一个好的做法。服务器应该像凤凰,经常从灰烬中升起...
+
+
diff --git a/sections/production/createmaintenanceendpoint.chinese.md b/sections/production/createmaintenanceendpoint.chinese.md
new file mode 100644
index 000000000..9b9f450ca
--- /dev/null
+++ b/sections/production/createmaintenanceendpoint.chinese.md
@@ -0,0 +1,37 @@
+# 创建维护端点
+
+
+
+
+### 一段解释
+
+维护端点是一个简单的安全的HTTP API, 它是应用程序代码的一部分, 它的用途是让ops/生产团队用来监视和公开维护功能。例如, 它可以返回进程的head dump (内存快照), 报告是否存在内存泄漏, 甚至允许直接执行 REPL 命令。在常规的 devops 工具 (监视产品、日志等) 无法收集特定类型的信息或您选择不购买/安装此类工具时, 需要使用此端点。黄金法则是使用专业的和外部的工具来监控和维护生产环境, 它们通常更加健壮和准确的。这就意味着, 一般的工具可能无法提取特定于node或应用程序的信息 – 例如, 如果您希望在 GC 完成一个周期时生成内存快照 – 很少有 NPM 库会很乐意为您执行这个, 但流行的监控工具很可能会错过这个功能。
+
+
+
+
+### 代码示例: 使用代码生产head dump
+
+```javascript
+var heapdump = require('heapdump');
+
+router.get('/ops/headump', (req, res, next) => {
+ logger.info(`About to generate headump`);
+ heapdump.writeSnapshot(function (err, filename) {
+ console.log('headump file is ready to be sent to the caller', filename);
+ fs.readFile(filename, "utf-8", function (err, data) {
+ res.end(data);
+ });
+ });
+});
+```
+
+
+
+### 推荐资源
+
+[Getting your Node.js app production ready (Slides)](http://naugtur.pl/pres3/node2prod)
+
+▶ [Getting your Node.js app production ready (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk)
+
+![Getting your Node.js app production ready](/assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready")
diff --git a/sections/production/delegatetoproxy.chinese.md b/sections/production/delegatetoproxy.chinese.md
new file mode 100644
index 000000000..7c3c210d5
--- /dev/null
+++ b/sections/production/delegatetoproxy.chinese.md
@@ -0,0 +1,54 @@
+# 委托任何可能的 (例如静态内容, gzip) 到反向代理
+
+
+
+
+### 一段解释
+
+这是非常诱人的 —— 去过度使用(cargo-cult)Express和使用其丰富的中间件提供网络相关的任务, 如服务静态文件, gzip 编码, throttling requests, SSL termination等。由于它的单线程模型将使 CPU 长时间处于忙碌状态 (请记住, node的执行模型针对短任务或异步 IO 相关任务进行了优化), 因此这是一个性能消耗。一个更好的方法是使用一个专注于处理网络任务的工具 – 最流行的是 nginx 和 HAproxy, 也被最大的云供应商使用, 以减轻在node.js进程上的面临的负载。
+
+
+
+
+### 代码示例 – 使用 nginx 压缩服务器响应
+
+```
+# 配置 gzip 压缩
+gzip on;
+gzip_comp_level 6;
+gzip_vary on;
+
+# 配置 upstream
+upstream myApplication {
+ server 127.0.0.1:3000;
+ server 127.0.0.1:3001;
+ keepalive 64;
+}
+
+#定义 web server
+server {
+ # configure server with ssl and error pages
+ listen 80;
+ listen 443 ssl;
+ ssl_certificate /some/location/sillyfacesociety.com.bundle.crt;
+ error_page 502 /errors/502.html;
+
+ # handling static content
+ location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
+ root /usr/local/silly_face_society/node/public;
+ access_log off;
+ expires max;
+}
+```
+
+
+
+### 其他博客作者说什么
+
+* 摘自博客 [Mubaloo](http://mubaloo.com/best-practices-deploying-node-js-applications):
+> …很容易落入这个陷阱 – 你看到一个包比如Express,并认为 "真棒!让我们开始吧" – 你编写了代码, 你实现了一个应用程序, 做你想要的。这很好, 老实说, 你赢得了很多的战斗。但是, 如果您将应用程序上传到服务器并让它侦听 HTTP 端口, 您将会输掉这场战争, 因为您忘记了一个非常关键的事情: node不是 web 服务器。**一旦任何流量开始访问你的应用程序, 你会发现事情开始出错: 连接被丢弃, 资源停止服务, 或在最坏的情况下, 你的服务器崩溃。你正在做的是试图让node处理所有复杂的事情, 而这些事情让一个已验证过了的 web 服务器来处理,再好也不会过。为什么要重新造轮子?It**
+> **这只是为了一个请求, 为了一个图像, 并铭记在脑海中, 您的应用程序可以用于重要的东西, 如读取数据库或处理复杂的逻辑; 为了方便起见, 你为什么要削弱你的应用?**
+
+
+* 摘自博客 [Argteam](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load):
+> 虽然 express.js 通过一些connect中间件处理静态文件, 但你不应该使用它。**Nginx 可以更好地处理静态文件, 并可以防止请求动态内容堵塞我们的node进程**…
diff --git a/sections/production/detectvulnerabilities.chinese.md b/sections/production/detectvulnerabilities.chinese.md
new file mode 100644
index 000000000..2a3628072
--- /dev/null
+++ b/sections/production/detectvulnerabilities.chinese.md
@@ -0,0 +1,17 @@
+# 使用工具自动检测有漏洞的依赖项
+
+
+
+### 一段解释
+
+现代node应用有数十个, 有时是数以百计的依赖。如果您使用的任何依赖项存在已知的安全漏洞, 您的应用也很容易受到攻击。
+下列工具自动检查依赖项中的已知安全漏洞:
+[nsp](https://www.npmjs.com/package/nsp) - Node 安全工程
+[snyk](https://snyk.io/) - 持续查找和修复依赖中的漏洞
+
+
+
+### 其他博主说什么
+摘自博客 [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) :
+
+> ...被用来管理您应用的依赖是强大且方便的。但是, 您使用的依赖包可能存在严重的安全漏洞, 也会影响您的应用。您的应用的安全性仅仅与您的依赖组件中的 "最薄弱的一环" 一样严重。幸运的是, 您可以使用两种有用的工具来确保您使用的第三方库: ** 和 requireSafe。这两种工具在很大程度上都是一样的, 所以使用两种方法都可能过于夸张, 但 "安全比抱歉" 更安全...
diff --git a/sections/production/frontendout.chinese.md b/sections/production/frontendout.chinese.md
new file mode 100644
index 000000000..f904829c9
--- /dev/null
+++ b/sections/production/frontendout.chinese.md
@@ -0,0 +1,44 @@
+# 在node外处理您的前端资产
+
+
+
+
+### 一段解释
+
+在一个经典的 web 应用中,后端返回前端资源/图片给浏览器, 在node的世界,一个非常常见的方法是使用 Express 静态中间件, 以数据流的形式把静态文件返回到客户端。但是, node并不是一个典型的 web应用, 因为它使用单个线程,对于同时服务多个文件,未经过任何优化。相反, 考虑使用反向代理、云存储或 CDN (例如Nginx, AWS S3, Azure Blob 存储等), 对于这项任务, 它们做了很多优化,并获得更好的吞吐量。例如, 像 nginx 这样的专业中间件在文件系统和网卡之间的直接挂钩, 并使用多线程方法来减少多个请求之间的干预。
+
+您的最佳解决方案可能是以下形式之一:
+1. 反向代理 – 您的静态文件将位于您的node应用的旁边, 只有对静态文件文件夹的请求才会由位于您的node应用前面的代理 (如 nginx) 提供服务。使用这种方法, 您的node应用负责部署静态文件, 而不是为它们提供服务。你的前端的同事会喜欢这种方法, 因为它可以防止 cross-origin-requests 的前端请求。
+2. 云存储 – 您的静态文件将不会是您的node应用内容的一部分, 他们将被上传到服务, 如 AWS S3, Azure BlobStorage, 或其他类似的服务, 这些服务为这个任务而生。使用这种方法, 您的node应用即不负责部署静态文件, 也不为它们服务, 因此, 在node和前端资源之间完全解耦, 这是由不同的团队处理。
+
+
+
+
+### 代码示例: 对于静态文件,典型的nginx配置
+
+```
+# configure gzip compression
+gzip on;
+keepalive 64;
+
+# defining web server
+server {
+listen 80;
+listen 443 ssl;
+
+# handle static content
+location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
+root /usr/local/silly_face_society/node/public;
+access_log off;
+expires max;
+}
+```
+
+
+
+### 其它博主说了什么
+摘自博客 [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-two-performance-and-reliability/):
+
+>…开发模式下, 您可以使用 [res.sendFile()](http://expressjs.com/4x/api.html#res.sendFile) 服务静态文件. 但是不要在生产中这样做, 因为这个函数为了每个文件请求,必须从文件系统中读取, 因此它会遇到很大的延迟, 并影响应用程序的整体性能。请注意, res.sendFile() 没有用系统调用 sendFile 实现, 这将使它更高效。相反, 使用serve-static中间件 (或类似的东西), 在express应用中服务文件,这是优化了的。更佳的选择是使用反向代理来服务静态文件; 有关详细信息, 请参阅使用反向代理…
+
+
diff --git a/sections/production/guardprocess.chinese.md b/sections/production/guardprocess.chinese.md
new file mode 100644
index 000000000..52ec578a9
--- /dev/null
+++ b/sections/production/guardprocess.chinese.md
@@ -0,0 +1,19 @@
+# 保护和重启你的失败进程(用正确的工具)
+
+
+
+
+### 一段解释
+
+在基本级别,必须保护Node进程并在出现故障时重新启动。简单地说, 对于那些小应用和不使用容器的应用 – 像这样的工具 [PM2](https://www.npmjs.com/package/pm2-docker) 是完美的,因为它们带来简单性,重启能力以及与Node的丰富集成。其他具有强大Linux技能的人可能会使用systemd并将Node作为服务运行。对于使用Docker或任何容器技术的应用程序来说,事情会变得更加有趣,因为集群管理和协调工具(比如[AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html ),[Kubernetes](https://kubernetes.io/)等)会完成部署,监视和保持容器健康的功能。拥有所有丰富的集群管理功能(包括容器重启),为什么还要与其他工具(如PM2)混为一谈?这里并没有可靠的答案。将PM2保留在容器(主要是其容器特定版本[pm2-docker](https://www.npmjs.com/package/pm2-docker))中作为第一个守护层是有充分的理由的 - 在主机容器要求正常重启时,重新启动更快,并提供特定于node的功能比如向代码发送信号。其他选择可能会避免不必要的层。总而言之,没有一个解决方案适合所有人,但了解这些选择是最重要的。
+
+
+
+
+### 其它博主说了什么
+
+* 来自[Express 生成最佳实践](https://expressjs.com/en/advanced/best-practice-performance.html):
+> ... 在开发中,您只需从命令行使用node.js或类似的东西启动您的应用程序。**但是在生产中这样做是一种灾难。 如果应用程序崩溃,它将掉线**,直到您重新启动它。要确保应用程序在崩溃时重新启动,请使用进程管理器。流程管理器是便于部署的应用程序的“容器”,提供高可用性,并使您能够在运行时管理应用程序。
+
+* 摘自 the Medium blog post [了解节点集群](https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.cssigr5z3):
+> ...了解Docker-Land中的NodeJS集群“Docker容器”是流线型的轻量级虚拟环境,旨在将流程简化为最低限度。管理和协调自己资源的流程不再有价值。**相反,像Kubernetes,Mesos和Cattle这样的管理层已经普及了这些资源应该在整个基础设施范围进行管理的概念**。CPU和内存资源由“调度器”分配,网络资源由堆栈提供的负载均衡器管理。
diff --git a/sections/production/lockdependencies.chinese.md b/sections/production/lockdependencies.chinese.md
new file mode 100644
index 000000000..f01121832
--- /dev/null
+++ b/sections/production/lockdependencies.chinese.md
@@ -0,0 +1,73 @@
+# 锁定依赖版本
+
+
+
+
+### 一段解释
+
+
+
+您的代码依赖于许多外部包,假设它“需要”和使用momentjs-2.1.4,默认情况下,当布署到生产中时,NPM可能会获得momentjs 2.1.5,但不幸的是,这将带来一些新的bug。使用NPM配置文件和设置 ```–save-exact=true``` 指示NPM去完成安装,以便下次运行 ```npm install```(在生产或在Docker容器中,您计划将其用于测试)时,将获取相同的依赖版本。另一种可选择受欢迎的方法是使用一个shrinkwrap文件(很容易使用NPM生成)指出应该安装哪些包和版本,这样就不需要环境来获取新版本了。
+
+* **更新:** 在NPM5中,使用.shrinkwrap依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。
+
+
+
+
+### 代码示例: .npmrc文件指示NPM使用精确的版本
+
+```
+// 在项目目录上保存这个为.npmrc 文件
+save-exact:true
+```
+
+
+
+### 代码示例: shirnkwrap.json文件获取准确的依赖关系树
+
+```javascript
+{
+ "name": "A",
+ "dependencies": {
+ "B": {
+ "version": "0.0.1",
+ "dependencies": {
+ "C": {
+ "version": "0.1.0"
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+### 代码示例: NPM5依赖锁文件 - package.json
+
+```javascript
+{
+ "name": "package-name",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "dependencies": {
+ "cacache": {
+ "version": "9.2.6",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz",
+ "integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg=="
+ },
+ "duplexify": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz",
+ "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=",
+ "dependencies": {
+ "end-of-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz",
+ "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4="
+ }
+ }
+ }
+ }
+}
+```
diff --git a/sections/production/measurememory.chinese.md b/sections/production/measurememory.chinese.md
new file mode 100644
index 000000000..9bab948b6
--- /dev/null
+++ b/sections/production/measurememory.chinese.md
@@ -0,0 +1,24 @@
+# 测量和防范内存使用情况
+
+
+
+
+### 一段解释
+
+在一个完美的开发过程中, Web开发人员不应该处理内存泄漏问题。 实际上,内存问题是一个必须了解的Node已知的问题。首先,内存使用必须不断监视.在开发和小型生产站点上,您可以使用Linux命令或NPM工具和库(如node-inspector和memwatch)来手动测量。 这个人工操作的主要缺点是它们需要一个人进行积极的监控 - 对于正规的生产站点来说,使用鲁棒性监控工具是非常重要的,例如(AWS CloudWatch,DataDog或任何类似的主动系统),当泄漏发生时提醒。 防止泄漏的开发指南也很少:避免将数据存储在全局级别,使用动态大小的流数据,使用let和const限制变量范围。
+
+
+
+### 其他博客说了什么
+
+* 摘自博客 [Dyntrace](http://apmblog.dynatrace.com/):
+> ... ”正如我们所了解到的,在Node.js 中,JavaScript被V8编译为机器码。由此产生的机器码数据结构与原始表达没有多大关系,只能由V8管理. 这意味着我们不能主动分配或释放JavaScript中的内存. V8 使用了一个众所周知的垃圾收集机制来解决这个问题.”
+
+* 摘自博客 [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load):
+> ... “虽然这个例子导致了明显的结果,但这个过程总是一样的:用一些时间和相当数量的内存分配创建heap dumps,比较dumps,以找出正在增长的内存泄露。”
+
+* 摘自博客 [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load):
+> ... “故障, 在内存较少的系统上运行时必须限制内存,Node.js会尝试使用大约1.5GB的内存。这是预期的行为,垃圾收集是一个代价很高的操作。
+解决方案是为Node.js进程添加一个额外的参数:
+node –max_old_space_size=400 server.js –production ”
+“为什么垃圾收集代价很高? V8 JavaScript 使用了 stop-the-world (STW)的垃圾回收机制。 事实上,这意味着程序在进行垃圾回收时停止执行。”
\ No newline at end of file
diff --git a/sections/production/monitoring.chinese.md b/sections/production/monitoring.chinese.md
new file mode 100644
index 000000000..ac23b193f
--- /dev/null
+++ b/sections/production/monitoring.chinese.md
@@ -0,0 +1,39 @@
+
+# 监控!
+
+
+
+### 一段解释
+
+基本来说,当在生产环境中发生意外时,监控意味着你能够很*容易*识别它们。比如,通过电子邮件或Slack获得通知。挑战在于选择既能满足你的需求又不会破坏防护的合适的工具集。我建议, 首先定义一组核心的度量标准, 这些指标必须被监视, 以确保健康状态 – CPU, 服务器RAM, Node进程RAM(小于1.4GB),最后一分钟的错误数量,进程重启次数,平均响应时间。然后去看看你可能喜欢的一些高级功能,并添加到你的愿望清单。一些高级监控功能的例子:DB分析,跨服务测量(即测量业务事务),前端集成,将原始数据展示给自定义BI客户端,Slack 通知等等。
+
+要实现高级功能需要冗长的设置或购买诸如Datadog,Newrelic之类的商业产品。不幸的是,实现基本功能也并不容易,因为一些测量标准是与硬件相关的(CPU),而其它则在node进程内(内部错误),因此所有简单的工具都需要一些额外的设置。例如,云供应商监控解决方案(例如[AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/))能立即告诉您硬件度量标准,但不涉及内部应用程序行为。另一方面,基于日志的解决方案(如ElasticSearch)默认缺少硬件视图。解决方案是通过缺少的指标来增加您的选择,例如,一个流行的选择是将应用程序日志发送到[Elastic stack](https://www.elastic.co/products)并配置一些额外的代理(例如[Beat](https://www.elastic.co/products))来共享硬件相关信息以获得完整的展现。
+
+
+
+### 监控示例:AWS cloudwatch默认仪表板。很难提取应用内指标
+
+![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png)
+
+
+
+### 监控示例:StackDriver默认仪表板。很难提取应用内指标
+
+![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg)
+
+
+
+### 监控示例:Grafana作为可视化原始数据的UI层
+
+
+![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png)
+
+
+### 其他博主说了什么
+ 摘自博客 [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/):
+
+> ...我们建议您为所有服务监听这些信号:
+> 错误率:因为错误是用户面对的,并立即会影响您的客户。
+> 响应时间:因为延迟会直接影响您的客户和业务。
+> 吞吐量:流量可帮助您了解增加的错误率和延迟的上下文。
+> 饱和度:饱和度告诉你你的服务有多“满”。如果CPU使用率是90%,您的系统可以处理更多的流量吗?...
diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md
new file mode 100644
index 000000000..c5b97d24b
--- /dev/null
+++ b/sections/production/productoncode.chinese.md
@@ -0,0 +1,17 @@
+# 代码生产环境的准备
+
+
+
+
+### 一段解释
+
+以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性:
+
+* 十二因素指南 — 熟悉[12因素](https://12factor.net/)指南
+* 无状态 — 在一个特定的web服务器上不保存本地数据(请参阅相关条目 - “Be Stateless”)
+* 高速缓存 — 大量使用缓存,但不会因为缓存不匹配而产生错误
+* 测试内存 — 测量内存的使用和泄漏,是作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务
+* 命名函数 — 将匿名函数(例如,内联callbabk)的使用最小化,因为一个典型的内存分析器为每个方法名提供内存使用情况
+* 使用CI工具 — 在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用–trace-sync-io来识别用了同步api的代码(而不是异步版本)
+* 明确的日志 — 包括在每个日志语句中希望用json格式记录上下文信息,以便于日志聚合工具,如Elastic可以在这些属性上搜索(请参阅相关条目 – “Increase visibility using smart logs”)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅 — “Include Transaction-ID”)
+* 错误管理 — 错误处理是Node.js生产站点的致命弱点 – 许多Node进程由于小错误而崩溃,然而其他Node进程则会在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的, 在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/)
\ No newline at end of file
diff --git a/sections/production/setnodeenv.chinese.md b/sections/production/setnodeenv.chinese.md
new file mode 100644
index 000000000..a89061df5
--- /dev/null
+++ b/sections/production/setnodeenv.chinese.md
@@ -0,0 +1,37 @@
+# 配置环境变量 NODE_ENV = production
+
+
+
+
+### 一段解释
+
+进程的环境变量是一组键值对,可用于任何运行程序,通常用于配置。虽然可以使用其他任何变量,但Node鼓励使用一个名为NODE_ENV的变量来标记我们是否正在开发。这一决定允许组件在开发过程中能提供更好的诊断,例如禁用缓存或发出冗长的日志语句。任何现代部署工具 — Chef、Puppet、CloudFormation等 — 在部署时都支持设置环境变量。
+
+
+
+
+### 代码实例:配置和读取NODE_ENV环境变量
+
+```javascript
+//在启动node进程前,在bash中设置环境变量
+$ NODE_ENV=development
+$ node
+
+//使用代码读取环境变量
+If(process.env.NODE_ENV === “production”)
+ useCaching = true;
+```
+
+
+
+
+### 其他博主说了什么
+摘自这篇博客[dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/):
+> ...在node.js中有一个约定, 它使用名为NODE_ENV的变量来设置当前工作模式。我们看到它实际上是读取NODE_ENV,如果它没有设置,则默认为“development”。我们清楚的看到,通过设置NODE_ENV为production,node.js可以处理请求的数量可以提高大约三分之二,而CPU的使用率会略有下降。 *让我强调一下:设置NODE_ENV为production可以让你的应用程序快3倍!*
+
+
+![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production")
+
+
+
+
diff --git a/sections/production/smartlogging.chinese.md b/sections/production/smartlogging.chinese.md
new file mode 100644
index 000000000..2b51ca8dc
--- /dev/null
+++ b/sections/production/smartlogging.chinese.md
@@ -0,0 +1,40 @@
+# 使用智能日志使你的应用程序变得清晰
+
+
+
+
+### 一段解释
+
+无论如何,您要打印日志,显然需要一些可以在其中跟踪错误和核心指标的接口来包装生产环境信息(例如,每小时发生了多少错误,最慢的API节点是哪一个)为什么不在健壮的日志框架中进行一些适度的尝试呢? 要实现这一目标,需要在三个步骤上做出深思熟虑的决定:
+
+**1. 智能日志** – 在最基本的情况下,您需要使用像[Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan)这样有信誉的日志库,在每个事务开始和结束时输出有意义的信息。还可以考虑将日志语句格式化为JSON,并提供所有上下文属性(如用户id、操作类型等)。这样运维团队就可以在这些字段上操作。在每个日志行中包含一个唯一的transaction ID,更多的信息查阅条款 “Write transaction-id to log”。最后要考虑的一点还包括一个代理,它记录系统资源,如内存和CPU,比如Elastic Beat。
+
+**2. 智能聚合** – 一旦您在服务器文件系统中有了全面的信息,就应该定期将这些信息推送到一个可以聚合、处理和可视化数据的系统中。例如,Elastic stack是一种流行的、自由的选择,它提供所有组件去聚合和产生可视化数据。许多商业产品提供了类似的功能,只是它们大大减少了安装时间,不需要主机托管。
+
+**3. 智能可视化** – 现在的信息是聚合和可搜索的, 一个可以满足仅仅方便地搜索日志的能力, 可以走得更远, 没有编码或花费太多的努力。我们现在可以显示一些重要的操作指标, 如错误率、平均一天CPU使用, 在过去一小时内有多少新用户选择, 以及任何其他有助于管理和改进我们应用程序的指标。
+
+
+
+
+### 可视化示例: Kibana(Elastic stack的一部分)促进了对日志内容的高级搜索
+![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")
+
+
+
+### 可视化示例: Kibana(Elastic stack的一部分)基于日志来可视化数据
+![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")
+
+
+
+### 博客应用: Logger的需求
+摘自博客 [Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/):
+
+> 让我们识别一些需求(对于一个日志记录器来说):
+> 1. 每条日志对应一个时间戳。这个很好解释 – 您应该能够判断每个日志条目出现的时间。
+> 2. 日志格式应该很容易被人和机器消化理解。
+> 3. 允许多个可配置的目标流。例如,您可能在一个文件中写入trace日志,但是当遇到错误时,将其写入相同的文件,然后写入错误日志文件并同时发送电子邮件...
+
+
+
+
+
diff --git a/sections/production/utilizecpu.chinese.md b/sections/production/utilizecpu.chinese.md
new file mode 100644
index 000000000..8fb0072a1
--- /dev/null
+++ b/sections/production/utilizecpu.chinese.md
@@ -0,0 +1,28 @@
+# 利用所有的CPU内核
+
+
+
+
+### 一段解释
+
+这应该不会让人感到意外, 在其基本形式上,Node运行在单进程,单线程,单个CPU上。购买了一个强大的包含4个或8个CPU的硬件,只使用一个听起来是不可思议的,对吗?适合中型应用最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和路由请求产生一个进程,进程之间以round-robin的形式存在。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给cluster模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用。对于那些高级的用例,考虑使用自定义部署脚本复制NODE进程,并使用像nginx
+这样的专门的工具进行负载均衡,或者使用像AWS ECS或Kubernetees这样的容器引擎,这些工具具有部署和复制进程的高级特性。
+
+
+
+
+### 比较:使用Node的clustre vs nginx做负载均衡
+
+![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx")
+
+
+
+### 其他博主说什么
+* 摘自[Node.JS documentation](https://nodejs.org/api/cluster.html#cluster_how_it_works):
+> ... 理论上第二种方法, Node clusters,应该是性能最佳的。然而, 在实践中, 由于操作系统调度程序的反复无常, 分布往往非常不平衡。观察负载, 所有连接中,超过70%在两个进程中处理, 而总共有八个进程...
+
+* 摘自博客[StrongLoop](From the blog StrongLoop):
+> ...通过Node的cluster模块实现集群化。这使一个主进程能够产生工作进程,并在工作进程间分配进入的连接。然而,与其直接使用这个模块,更好的选择是使用其中的许多工具之一, 它为您自动处理它; 例如,node-pm或cluster-service...
+
+* 摘自the Medium post[node.js进程负载平衡性能:比较cluster moudlle、iptables和Nginx](https://medium.com/@fermads/node-js-process-load-balancing- iptabls -and- Nginx -6746aaf38272)
+> ... Node cluster易于实施和配置,不依赖于其他软件就可以在Node的领域内进行。请记住,你的主进程将会工作几乎和你的工作进程一样多,比较于其他的解决方案,少一点请求率...
\ No newline at end of file
diff --git a/sections/projectstructre/breakintcomponents.chinese.md b/sections/projectstructre/breakintcomponents.chinese.md
index 91cc30ec5..1da60edcc 100644
--- a/sections/projectstructre/breakintcomponents.chinese.md
+++ b/sections/projectstructre/breakintcomponents.chinese.md
@@ -1,26 +1,36 @@
-# Structure your solution by components
+# 组件式构建你的解决方案
-### One Paragraph Explainer
+### 一段解释
-For medium sized apps and above, monoliths are really bad - a one big software with many dependencies is just hard to reason about and often lead to code spaghetti. Even those smart architects who are skilled to tame the beast and 'modularize' it - spend great mental effort on design and each change requires to carefully evaluate the impact on other dependant objects. The ultimate solution is to develop small software: divide the whole stack into self-contained components that don't share files with others, each constitute very few files (e.g. API, service, data access, test, etc) so that it's very easy to reason about it. Some may call this 'microservices' architecture - it's important to understand that microservices is not a spec which you must follow rather a set of principles. You may adopt many principles into a full-blown microservices architecture or adopt only few. Both are good as long as you keep the software complexity low. The very least you should do is create a basic borders between components, assign a folder in your project root for each business component and make it self contained - other components are allowed to consume its functionality only through its public interface or API. This is the foundation for keeping your components simple, avoid dependencies hell and pave the way to full-blown microservices in the future once your app grows.
+对于中等规模的应用程序及以上,一个代码库是非常糟糕的 - 一个包含很多依赖的大型软件很难理解,往往导致代码混乱。即使是那些擅长解决负责问题和 "模块化" 的聪明架构师 - 在设计上花费了很大的脑力, 每一个变化都需要仔细评估对其他依赖对象的影响。最终的解决方案是开发小型软件:将整个堆栈划分为独立的组件,这些组件不与其他组件共享文件,每个组件由很少的文件构成(例如API、服务、数据访问、测试等),因此很容易理解它。有些人可能称之为 "microservices" 架构 - 重要的是要理解 microservices 不是一个你必须遵循的规范,而是一套原则。您可以将许多原则引入到成熟的 microservices 体系结构中, 或者只采用少数几个。只要您保持软件的复杂性低, 两者都是好的。最起码应该做的是在组件之间创建一个基本边界, 为每个业务组件在项目根目录中分配一个文件夹, 并使其自包含-其他组件只能通过其公共接口或 API 使用其功能。这是保持您的组件简单的基础,在未来, 一旦您的应用程序增长,避免依赖性地狱,为全面的 microservices 架构铺平了道路.
-### Blog Quote: "Scaling requires scaling of the entire application"
- From the blog MartinFowler.com
+### 博客引用: "伸缩需要对整个应用程序进行伸缩设计"
+ 摘自博客 MartinFowler.com
- > Monolithic applications can be successful, but increasingly people are feeling frustrations with them - especially as more applications are being deployed to the cloud . Change cycles are tied together - a change made to a small part of the application, requires the entire monolith to be rebuilt and deployed. Over time it's often hard to keep a good modular structure, making it harder to keep changes that ought to only affect one module within that module. Scaling requires scaling of the entire application rather than parts of it that require greater resource.
+ > 单个应用程序可以成功, 但越来越多的人对它们感到失望 - 尤其是随着更多的应用程序被部署到云中。更改周期被捆绑在一起 - 对应用程序的一小部分进行更改, 需要重建和部署整个整体。随着时间的推移, 通常很难保持一个良好的模块化结构, 这使得更改哪怕只会影响该模块中的一个模块变得更加困难。伸缩设计需要扩展整个应用程序, 而不是它的部分,这往往需要更多资源。
- ### Good: Structure your solution by self-contained components
+ ### 博客引用: "那么, 你的应用程序的架构声明了什么?"
+ 摘自博客 [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html)
+
+> ...如果你正在寻找一个图书馆的建筑架构, 你可能会看到一个盛大的入口, 一个 check-in-out 的文员, 阅读区, 小会议室, 画廊, 画廊后面容纳了装载所有图书馆书籍的书架。建筑会声明: 图书馆.
+那么, 应用程序的体系架构会声明什么呢? 当您查看顶级目录结构和最高级别包中的源文件时; 他们声明: 医疗保健系统, 或会计系统, 或库存管理系统? 或者他们声明: Rails, 或Spring/Hibernate, 或 ASP?.
+
+
+
+
+ ### 推荐: 通过独立组件构建解决方案
![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components")
+
-### Bad: Group your files by technical role
+### 避免: 按技术角色对文件进行分组
![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles")
diff --git a/sections/projectstructre/configguide.chinese.md b/sections/projectstructre/configguide.chinese.md
index 10b65e5e5..90bddc18c 100644
--- a/sections/projectstructre/configguide.chinese.md
+++ b/sections/projectstructre/configguide.chinese.md
@@ -1,17 +1,19 @@
-使用环境感知,安全,分层的配置
+# 使用环境感知,安全,分层的配置
-解释
+### 一段解释
当我们处理配置参数时,常常会很慢并且很烦躁:(1)当需要注入100个keys(而不是只在配置文件中提交它们)时,使用进程环境变量设置所有的keys变得非常繁琐,但是当处理只有devops管理权限的文件时,不改变代码行为就不不会变。一个可靠的配置解决方案必须结合配置文件和进程变量覆盖。(2)枚举一个普通JSON的所有keys时,当目录变得非常庞杂的时候,查找修改条目困难。几乎没有配置库允许将配置存储在多个文件中,运行时将所有文件联合起来。分成几个部分的分层JSON文件能够克服这个问题。请参照下面示例。(3)不推荐存储像密码数据这样的敏感信息,但是又没有快速便捷的方法解决这个难题。一些配置库允许文件加密,其他库在Git提交时加密目录,或者不存储这些目录的真实值,在通过环境变量部署期间枚举真实值。(4)一些高级配置场景需要通过命令行(vargs)注入配置值,或者像Redis一样通过集中缓存同步配置信息,所以不同的服务器不会保存不同的数据。
一些配置库可以免费提供这些功能的大部分功能,请查看NPM库([nconf](https://www.npmjs.com/package/nconf) 和 [config](https://www.npmjs.com/package/config))这些库可以满足这些要求中的许多要求。
+
-代码示例-分层配置有助于查找条目和维护庞大的配置文件
-javascript
+### 代码示例 – 分层配置有助于查找条目和维护庞大的配置文件
+
+```javascript
{
// Customer module configs
"Customer": {
@@ -27,5 +29,6 @@ javascript
}
}
}
+```
diff --git a/sections/projectstructre/createlayers.chinese.md b/sections/projectstructre/createlayers.chinese.md
index d86633e6d..efa7db1b6 100644
--- a/sections/projectstructre/createlayers.chinese.md
+++ b/sections/projectstructre/createlayers.chinese.md
@@ -1,10 +1,11 @@
-应用程序分层,保持Express在其边界内
+# 应用程序分层,保持Express在其边界内
+
- 将组件代码分成web, services, DAL层
+ ### 将组件代码分成web, services, DAL层
![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers")
-1分钟说明:混合层的缺点
+### 1分钟说明:混合层的缺点
![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers")
diff --git a/sections/projectstructre/separateexpress.chinese.md b/sections/projectstructre/separateexpress.chinese.md
new file mode 100644
index 000000000..8b8a2d703
--- /dev/null
+++ b/sections/projectstructre/separateexpress.chinese.md
@@ -0,0 +1,63 @@
+# Express的 '应用' 和 '服务' 分离
+
+
+
+
+### 一段解释
+
+最新的Express生成器有一个值得保留的伟大实践--API声明与网络相关配置(端口、协议等)是分开的。这样就可以在不执行网络调用的情况下对API进行在线测试,它所带来的好处是:快速执行测试操作和获取代码覆盖率。它还允许在灵活多样的网络条件下部署相同的API。额外好处:更好的关注点分离和更清晰的代码结构。
+
+
+
+### 代码示例:API声明应该在 app.js 文件里面
+
+```javascript
+var app = express();
+app.use(bodyParser.json());
+app.use("/api/events", events.API);
+app.use("/api/forms", forms);
+
+```
+
+
+
+### 代码示例: 服务器网络声明,应该在 /bin/www 文件里面
+
+```javascript
+var app = require('../app');
+var http = require('http');
+
+/**
+ * Get port from environment and store in Express.
+ */
+
+var port = normalizePort(process.env.PORT || '3000');
+app.set('port', port);
+
+/**
+ * Create HTTP server.
+ */
+
+var server = http.createServer(app);
+
+```
+
+
+### 示例代码: 使用超快的流行的测试包在线测试你的代码
+
+```javascript
+const app = express();
+
+app.get('/user', function(req, res) {
+ res.status(200).json({ name: 'tobi' });
+});
+
+request(app)
+ .get('/user')
+ .expect('Content-Type', /json/)
+ .expect('Content-Length', '15')
+ .expect(200)
+ .end(function(err, res) {
+ if (err) throw err;
+ });
+````
diff --git a/sections/projectstructre/thincomponents.chinese.md b/sections/projectstructre/thincomponents.chinese.md
new file mode 100644
index 000000000..65a0cf3be
--- /dev/null
+++ b/sections/projectstructre/thincomponents.chinese.md
@@ -0,0 +1,26 @@
+# 用组件来构造你的解决方案
+
+
+
+
+### 一段解释
+
+对于中型应用以上来说,按部就班的写在一起真是太糟糕了-当一个有很多依赖的大型的软件会导致我们理解起来非常困难并且导致我们的代码杂乱不堪。甚至像那些能够熟练地驯服野兽的聪明的设计师一样,他们在设计上花费大量的精力用来"模块化"代码,每一次改动都需要仔细的评估对于其他依赖对象的影响。构建小型项目的最终方法是:将整体的项目分享一个个不与其他组件共享文件的独立组件,每个组件由很少的文件组成(例如API、服务、数据访问、测试等),所以这是比较容易理解的。一些被称为"microservices"的架构,去理解"microservices"不是你必须遵守的规范而是一套原则是非常重要的。你可以将许多原则应用到一个成熟的微服务体系结构中,或者只采用少数几个原则。只要你把软件的复杂性保持在低水平,两者都是好的。您至少应该做的是在组件之间创建一个基本的边界,在项目根中为每个业务组件分配一个文件夹,并让它自己做到其他组件只允许通过它的公共接口或API来实现它的功能。这是让你的组件保持简单的基础,避免依赖关系,在你的应用程序成长后,为将来成熟的微服务铺平道路。
+
+
+
+
+### 引用博客: "扩展需要整个应用的扩展"
+ 摘自博客 MartinFowler.com
+
+ > 单片应用程序可以成功,但是越来越多的人对它们感到失望——特别是当越来越多的应用程序被部署到云上时。变更周期是绑定在一起的——对应用程序的一小部分进行了更改,需要重新构建和部署整个庞然大物。随着时间的推移,保持良好的模块结构通常很难,这使得更改只会影响自己内部的模块变得更加困难。扩展需要扩展整个应用程序,而不是需要更大的资源的部分。
+
+
+
+ ### 推荐: 通过自包含的组件来构造解决方案
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components")
+
+
+
+### 避免: 通过技术角色对文件进行分组
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles")
diff --git a/sections/projectstructre/wraputilities.chinese.md b/sections/projectstructre/wraputilities.chinese.md
new file mode 100644
index 000000000..5b99915f5
--- /dev/null
+++ b/sections/projectstructre/wraputilities.chinese.md
@@ -0,0 +1,14 @@
+# 将公用实用工具封装成 NPM 包
+
+
+
+
+### 一段解释
+一旦你开始在不同的服务器上增加不同的组件并使用不同的服务器,这些服务器会消耗类似的工具,那么你应该开始管理依赖关系 - 你如何保留实用工具代码的一个副本,并让多个使用组件者使用和部署? 好吧,有一个这样的框架,它被称为NPM ...首先用自己的代码包装第三方实用工具包,以便将来可以轻松替换,并发布自己的代码作为私人NPM包。 现在,您所有的代码库都可以导入该代码并受益于免费的依赖管理框架。 您可以发布NPM包供您自己的私人使用,而无需公开分享 [私人模块](https://docs.npmjs.com/private-modules/intro), [私人注册表](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) or [本地 NPM 包](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc)
+
+
+
+
+
+ ### 在环境和组件中共享你自己的公用实用工具
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/Privatenpm.png "构建解决方案的组件")
diff --git a/sections/testingandquality/citools.chinese.md b/sections/testingandquality/citools.chinese.md
new file mode 100644
index 000000000..0f263a489
--- /dev/null
+++ b/sections/testingandquality/citools.chinese.md
@@ -0,0 +1,53 @@
+# 仔细挑选您的 CI 平台
+
+
+
+
+### 一段解释
+
+CI世界曾经是[Jenkins](https://jenkins.io/) vs SaaS供应商的简单性。游戏正在改变,比如SaaS提供者 [CircleCI](https://circleci.com/) 和 [Travis](https://travis-ci.org/) 提供了强大的解决方案,包含最小化设置时间的Docker容器,而Jenkins也尝试在简单易用性上做文字而提高竞争性。虽然您可以在云上设置丰富的 CI 解决方案, 如果它需要控制更多的细节Jenkins仍然是选择的平台。最终的选择归结为 CI 过程应自定义的范围: 云供应商允许运行自定义 shell 命令、自定义的docker images、调整工作流、运行矩阵生成和其他丰富的功能的自由和设置自由。但是, 如果使用像 Java 这样的正式编程语言来控制基础结构或编程 CI 逻辑 - Jenkins可能仍然是首选。否则, 考虑选择简单和设置自由的云选项
+
+
+
+
+### 代码示例 – 典型的云 CI 配置。一个.yml 文件就够了
+```javascript
+version: 2
+jobs:
+ build:
+ docker:
+ - image: circleci/node:4.8.2
+ - image: mongo:3.4.4
+ steps:
+ - checkout
+ - run:
+ name: Install npm wee
+ command: npm install
+ test:
+ docker:
+ - image: circleci/node:4.8.2
+ - image: mongo:3.4.4
+ steps:
+ - checkout
+ - run:
+ name: Test
+ command: npm test
+ - run:
+ name: Generate code coverage
+ command: './node_modules/.bin/nyc report --reporter=text-lcov'
+ - store_artifacts:
+ path: coverage
+ prefix: coverage
+
+```
+
+
+
+ ### Circle CI - 几乎零设置云 CI
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/circleci.png "API error handling")
+
+### Jenkins - 完善和强大的CI
+![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/jenkins_dashboard.png "API error handling")
+
+
+
diff --git a/writing-guidelines.chinese.md b/writing-guidelines.chinese.md
new file mode 100644
index 000000000..9204a4979
--- /dev/null
+++ b/writing-guidelines.chinese.md
@@ -0,0 +1,31 @@
+# 我们的内容写作声明
+如何提高访问者的阅读和学习体验
+
+## 1. 越简单越好
+
+
+我们的使命, 我们管理内容是为了使阅读和吸收知识更容易。因此, 我们专注于将复杂和无趣的话题转化为一个简化的清单, 用缩短和不那么精确的细节来交易超载信息, 避免 ‘易燃’ 和有争议的话题, 摆脱主观想法, 赞成普遍接受做法
+
+
+
+## 2. 以证据为基础并且可靠
+
+
+我们的读者应该有很大的信心, 他们浏览的内容是可靠的。我们通过包括引用、数据和本主题可用的其他资源等证据来实现这一点。实际上, 努力包括可靠来源的引用, 显示基准, 相关的设计模式或任何科学措施, 以证明您的主张
+
+
+## 3. MECE (Mutually Exclusive and Collectively Exhaustive)
+除了大量编辑和可靠的内容, 通过它略读也应该提供全面覆盖的主题。不应排除重要的子主题
+
+## 4. 一致的格式
+内容是使用固定模板显示的。任何将来的内容都必须符合同一模板。如果希望添加新项目符号, 请从现有项目符号复制项目符号格式, 并将其扩展以满足您的需要。有关其他信息, 请查看[模版](https://github.com/i0natan/nodebestpractices/blob/master/sections/template.md)
+
+## 5. 关于Node.js
+每个建议都应直接与Node.js相关, 而不是一般软件开发。当我们建议在Node.js中实现通用模式/规则时, 内容应该集中在Node的实现上。例如, 当我们建议将所有请求的输入为了安全原因进行处理时, 应使用Node行话 - '使用中间件来处理请求输入'
+
+## 6. 仅限主要的vendor
+有时, 包括可以解决某些挑战和问题 (如 NPM 软件包、开源工具甚至商业产品) 的供应商名称是很有用的。为了避免极长的列表或推荐信誉不好和不稳定的项目, 我们提出了以下规则:
+
+- 只有排名前3的vendor应该被推荐 – 对于一个给定的相关关键词,如果某个vendor出现在搜索引擎结果中排名前3(谷歌或GitHub通过人气排序),那么它可以包含在我们的推荐里
+- 如果它是一个NPM包,它必须平均一天下载至少750次
+- 如果它是一个开源项目,它必须在过去的6个月里至少更新一次