From ba821207a65e70a8a5b53952b9c6c0ec246a7da3 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Tue, 28 Nov 2017 18:10:01 +0800 Subject: [PATCH 01/75] [Chinese-translation]add 'table of contents' and '1.1' in README.chinese.md --- README.chinese.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index a14a8aae0..9c039a255 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -1,6 +1,6 @@ [✔]: assets/images/checkbox-small-blue.png -# Node.js Best Practices +# Node.js 最佳实践

Node.js Best Practices @@ -17,35 +17,35 @@ [![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-# Welcome! 3 Things You Ought To Know First: -**1. When you read here, you in fact read dozens of the best Node.JS articles -** this is a summary and curation of the top-ranked content on Node JS best practices +# 欢迎! 首先您应该知道的三件事情: +**1. 当您读到这里,实际上您读了很多关于Node.JS的优秀文章 -** 这里是关于Node JS 最佳实践的优质内容的总结和管理 -**2. It is the largest compilation, and it is growing every week -** currently, more than 50 best practices, style guides, and architectural tips are presented. We welcome issues and PR to ever keep this live book updated. We'd love to see you contributing here, whether fixing some code mistake or suggesting brilliant new ideas - be part of the Node.JS best practices book +**2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。我们欢迎议题和PR使这本在线书籍不断更新。我们也乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是建议卓越的新想法 - 作为Node.JS最佳实践这本书中的一部分 -**3. Most bullets have additional info -** nearby most best practice bullets you'll find **🔗Read More** link that will present you with code examples, quotes from selected blogs and more info +**3. 大部分的条目包含额外的信息 -** 大部分的最佳实践条目的旁边,您将发现 **🔗Read More** 链接,它将呈现给您示例代码,博客引用和更多信息


-## Table of Contents -1. [Project structure Practices (5)](#1-project-structure-practices) -2. [Error Handling Practices (11) ](#2-error-handling-practices) -3. [Code Style Practices (12) ](#3-code-style-practices) -4. [Testing And Overall Quality Practices (8) ](#4-testing-and-overall-quality-practices) +## 目录 +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. [Going To Production Practices (16) ](#5-going-to-production-practices) 6. Security Practices (coming soon) 7. Performance Practices (coming soon)


-# `1. Project Structure Practices` +# `1. 项目结构实践` -## ![✔] 1.1 Structure your solution by components +## ![✔] 1.1 组件式构建你的解决方案Structure your solution by components - **TL;DR:** The worst large applications pitfall is maintaining a huge code base with hundreds of dependencies - such a monolith slows down developers as they try to incorporate new features. Instead, partition your code into components, each gets its own folder or a dedicated codebase, and ensure that each unit is kept small and simple. Visit 'Read More' below to see examples of correct project structure + **TL;DR:** 最大的项目隐患就是维护一个巨大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。 -**Otherwise:** When developers who code new features struggle to realize the impact of their change and fear to break other dependant components - deployments become slower and more risky. It's also considered harder to scale-out when all the business units are not separated +**另外:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展 -🔗 [**Read More: structure by components**](/sections/projectstructre/breakintcomponents.chinese.md) +🔗 [**更多: 组件结构**](/sections/projectstructre/breakintcomponents.chinese.md)

From 37e289fcf75a88755e7b1d720518cf35fc05c83a Mon Sep 17 00:00:00 2001 From: matt_jin Date: Wed, 29 Nov 2017 16:46:28 +0800 Subject: [PATCH 02/75] [Chinese-translation]add 1.2 --- README.chinese.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 9c039a255..23e04df2e 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -49,17 +49,17 @@

-## ![✔] 1.2 Layer your components, keep Express within its boundaries +## ![✔] 1.2 分层设计组件,保持Express在特定的区域 -**TL;DR:** Each component should contain 'layers' - a dedicated object for the web, logic and data access code. This not only draws a clean separation of concerns but also significantly ease mocking and testing the system. Though this is a very common pattern, API developers tend to mix layers by passing the web layer objects (Express req, res) to business logic and data layers - this makes your application dependant on and accessible by Express only +**TL;DR:** 每一个组件都应该包含'层级' - 一个专注的用于接入网络,逻辑,数据的概念。这样不仅获得一个清晰的分离考量,而且使仿真和测试系统变得异常容易。尽管这是一个普通的模式,但接口开发者易于混淆层级关系,比如把网络层的对象(Express req, res)传给业务逻辑和数据层 - 这会令您的应用彼此依赖,并且只能通过Express使用。 -**Otherwise:** App that mixes web objects with other layers can not be accessed by testing code, CRON jobs and other non-Express callers +**另外:** 对于混淆了网络层和其它层的应用,将不易于测试,执行CRON的任务,其它非-Express的调用者无法使用 -🔗 [**Read More: layer your app**](/sections/projectstructre/createlayers.md) +🔗 [**更多: 应用分层**](/sections/projectstructre/createlayers.md)

-## ![✔] 1.3 Wrap common utilities as NPM packages +## ![✔] 1.3 封装公共模块成为NPM的包 **TL;DR:** In a large app that constitutes a large code base, cross-cutting-concern utilities like logger, encryption and alike, should be wrapped by your own code and exposed as private NPM packages. This allows sharing them among multiple code bases and projects From 47f0eeb2cf6b1c762eee222c6eb8c228e776c30e Mon Sep 17 00:00:00 2001 From: matt_jin Date: Wed, 29 Nov 2017 17:04:30 +0800 Subject: [PATCH 03/75] [Chinese-translation]add 1.3 --- README.chinese.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 23e04df2e..3813b0977 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -43,7 +43,7 @@ **TL;DR:** 最大的项目隐患就是维护一个巨大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。 -**另外:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展 +**否则:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展 🔗 [**更多: 组件结构**](/sections/projectstructre/breakintcomponents.chinese.md) @@ -53,7 +53,7 @@ **TL;DR:** 每一个组件都应该包含'层级' - 一个专注的用于接入网络,逻辑,数据的概念。这样不仅获得一个清晰的分离考量,而且使仿真和测试系统变得异常容易。尽管这是一个普通的模式,但接口开发者易于混淆层级关系,比如把网络层的对象(Express req, res)传给业务逻辑和数据层 - 这会令您的应用彼此依赖,并且只能通过Express使用。 -**另外:** 对于混淆了网络层和其它层的应用,将不易于测试,执行CRON的任务,其它非-Express的调用者无法使用 +**否则:** 对于混淆了网络层和其它层的应用,将不易于测试,执行CRON的任务,其它非-Express的调用者无法使用 🔗 [**更多: 应用分层**](/sections/projectstructre/createlayers.md) @@ -61,11 +61,11 @@ ## ![✔] 1.3 封装公共模块成为NPM的包 -**TL;DR:** In a large app that constitutes a large code base, cross-cutting-concern utilities like logger, encryption and alike, should be wrapped by your own code and exposed as private NPM packages. This allows sharing them among multiple code bases and projects +**TL;DR:** 由大量代码构成的一个大型应用中,贯彻全局的,比如日志,加密和其它类似的公共组件,应该进行封装,并暴露成一个私有的NPM包。这将使其在更多的代码库和项目中被使用变成了可能。 -**Otherwise:** You'll have to invent your own deployment and dependency wheel +**否则:** 您将不得不重造部署和依赖的轮子 -🔗 [**Read More: Structure by feature**](/sections/projectstructre/wraputilities.md) +🔗 [**更多: 通过需求构建**](/sections/projectstructre/wraputilities.md)

From 4a51d32d470a8e26beadad3067ffd3a48edda9f2 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Wed, 29 Nov 2017 18:32:46 +0800 Subject: [PATCH 04/75] [Chinese-translation]README.chinese.md add 1.4 --- README.chinese.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 3813b0977..af2d58d76 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -69,13 +69,13 @@

-## ![✔] 1.4 Separate Express 'app' and 'server' +## ![✔] 1.4 分离 Express 'app' and 'server' -**TL;DR:** Avoid the nasty habit of defining the entire [Express](https://expressjs.com/) app in a single huge file - separate your 'Express' definition to at least two files: the API declaration (app.js) and the networking concerns (WWW). For even better structure, locate your API declaration within components +**TL;DR:** 避免定义整个[Express](https://expressjs.com/)应用在一个单独的大文件的不好习惯 - 分离您的 'Express' 定义至少在两个文件中: API声明(app.js) 和 网络相关(WWW)。对于更好的结构,是把你的API声明放在组件中。 -**Otherwise:** Your API will be accessible for testing via HTTP calls only (slower and much harder to generate coverage reports). It probably won't be a big pleasure to maintain hundreds of lines of code in a single file +**否者:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。 -🔗 [**Read More: separate Express 'app' and 'server'**](/sections/projectstructre/separateexpress.md) +🔗 [**更多: 分离 Express 'app' and 'server'**](/sections/projectstructre/separateexpress.md)

From ccf88af368f6bcb5e17ef09816c130d07a3a5c30 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 29 Nov 2017 22:25:25 +0800 Subject: [PATCH 05/75] [Chinese-translation]README.chinese.md add 1.5 --- README.chinese.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index af2d58d76..6089bafb9 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -73,20 +73,19 @@ **TL;DR:** 避免定义整个[Express](https://expressjs.com/)应用在一个单独的大文件的不好习惯 - 分离您的 'Express' 定义至少在两个文件中: API声明(app.js) 和 网络相关(WWW)。对于更好的结构,是把你的API声明放在组件中。 -**否者:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。 +**否则:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。 🔗 [**更多: 分离 Express 'app' and 'server'**](/sections/projectstructre/separateexpress.md)

-## ![✔] 1.5 Use environment aware, secure and hierarchical config +## ![✔] 1.5 使用易于设置环境变量,安全和分级的配置 -**TL;DR:** A perfect and flawless configuration setup should ensure (a) keys can be read from file AND from environment variable (b) secrets are kept outside committed code (c) config is hierarchical for easier findability. There are only a few packages that can help tick most of those boxes like [nconf](https://www.npmjs.com/package/nconf) and [config](https://www.npmjs.com/package/config). +**TL;DR:** 一个完美无瑕的配置安装应该确保 (a) 元素可以从文件中,也可以从环境变量中读取 (b) 密码排除在提交的代码之外 (c) 为了易于检索,配置是分级的。仅有几个包可以满足这样的条件,比如[nconf](https://www.npmjs.com/package/nconf) 和 [config](https://www.npmjs.com/package/config)。 -**Otherwise:** Failing to satisfy any of the config requirements will simply bog down the development or devops team. Probably both - -🔗 [**Read More: configuration best practices**](/sections/projectstructre/configguide.md) +**否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。 +🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.md)


From 9f628c55b742d1cee787bd52fb1573ad0e8ed3fe Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 29 Nov 2017 22:59:32 +0800 Subject: [PATCH 06/75] [Chinese-translation]README.chinese.md - error handler init. --- README.chinese.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 6089bafb9..885f9195e 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -92,26 +92,26 @@

⬆ Return to top

-# `2. Error Handling Practices` +# `2. 错误处理最佳实践` -## ![✔] 2.1 Use Async-Await or promises for async error handling +## ![✔] 2.1 使用 Async-Await 和 promises 用于异步错误处理 -**TL;DR:** Handling async errors in callback style is probably the fastest way to hell (a.k.a the pyramid of doom). The best gift you can give to your code is using a reputable promise library or async-await instead which enables a much more compact and familiar code syntax like try-catch +**TL;DR:** 使用回调的方式处理异步错误可能是导致灾难的最快的方式(a.k.a the pyramid of doom)。对您的代码来说,最好的礼物就是使用规范的promise库或async-await来替代,这会使其像try-catch一样更加简洁,熟悉的代码结构。 -**Otherwise:** Node.JS callback style, function(err, response), is a promising way to un-maintainable code due to the mix of error handling with casual code, excessive nesting and awkward coding patterns +**否则:** Node.JS 回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。 -🔗 [**Read More: avoiding callbacks**](/sections/errorhandling/asyncerrorhandling.md) +🔗 [**更多: 避免回调**](/sections/errorhandling/asyncerrorhandling.md)

-## ![✔] 2.2 Use only the built-in Error object +## ![✔] 2.2 仅使用内建的错误对象 -**TL;DR:** Many throws errors as a string or as some custom type – this complicates the error handling logic and the interoperability between modules. Whether you reject a promise, throw exception or emit error – using only the built-in Error object will increase uniformity and prevent loss of information +**TL;DR:** 很多人抛出异常使用字符串类型或一些自定义类型 - 这会导致错误处理逻辑和模块间的调用复杂化。是否您reject一个promise,抛出异常或发出(emit)错误 - 使用内建的错误对象将会增加设计一致性,并防止信息的丢失。 **Otherwise:** When invoking some component, being uncertain which type of errors come in return – it makes proper error handling much harder. Even worse, using custom types to describe errors might lead to loss of critical error information like the stack trace! -🔗 [**Read More: using the built-in error object**](/sections/errorhandling/useonlythebuiltinerror.md) +🔗 [**更多: 使用内建错误对象**](/sections/errorhandling/useonlythebuiltinerror.md)

From ec091c8abe2325c0c1dc5e3cf713367311174cbc Mon Sep 17 00:00:00 2001 From: matt_jin Date: Thu, 30 Nov 2017 20:32:16 +0800 Subject: [PATCH 07/75] [Chinese-translation]README.chinese.md - add 2.4 & 2.6 --- README.chinese.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 885f9195e..86f5e9870 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -109,7 +109,7 @@ **TL;DR:** 很多人抛出异常使用字符串类型或一些自定义类型 - 这会导致错误处理逻辑和模块间的调用复杂化。是否您reject一个promise,抛出异常或发出(emit)错误 - 使用内建的错误对象将会增加设计一致性,并防止信息的丢失。 -**Otherwise:** When invoking some component, being uncertain which type of errors come in return – it makes proper error handling much harder. Even worse, using custom types to describe errors might lead to loss of critical error information like the stack trace! +**否则:** 调用某些模块,将不确定哪种错误类型会返回 - 这将会使恰当的错误处理更加困难。更坏的情况是,使用特定的类型描述错误,会导致重要的错误信息缺失,比如stack trace! 🔗 [**更多: 使用内建错误对象**](/sections/errorhandling/useonlythebuiltinerror.md) @@ -125,13 +125,13 @@

-## ![✔] 2.4 Handle errors centrally, not within an Express middleware +## ![✔] 2.4 集中处理错误,不要在Express中间件中处理错误 -**TL;DR:** Error handling logic such as mail to admin and logging should be encapsulated in a dedicated and centralized object that all endpoints (e.g. Express middleware, cron jobs, unit-testing) call when an error comes in. +**TL;DR:** 错误处理逻辑,比如给管理员发送邮件,日志应该封装在一个特定的,集中的对象当中,这样当错误产生的时候,所有的终端(例如 Express中间件,cron任务,单元测试)都可以调用。 -**Otherwise:** Not handling errors within a single place will lead to code duplication and probably to improperly handled errors +**否则:** 错误处理的逻辑不放在一起将会导致代码重复和非常可能不恰当的错误处理。 -🔗 [**Read More: handling errors in a centralized place**](/sections/errorhandling/centralizedhandling.md) +🔗 [**更多: 集中处理错误**](/sections/errorhandling/centralizedhandling.md)

@@ -146,13 +146,13 @@

-## ![✔] 2.6 Shut the process gracefully when a stranger comes to town +## ![✔] 2.6 当一个特殊的情况产生,停掉服务是得体的 -**TL;DR:** When an unknown error occurs (a developer error, see best practice number #3)- there is uncertainty about the application healthiness. A common practice suggests restarting the process carefully using a ‘restarter’ tool like Forever and PM2 +**TL;DR:** 当一个不确定错误产生(一个开发错误,最佳实践条款#3) - 这就意味着对应用运转健全的不确定。一个普通的实践将是建议仔细地重启进程,并使用一些‘启动器’工具,比如Forever和PM2。 -**Otherwise:** When an unfamiliar exception is caught, some object might be in a faulty state (e.g an event emitter which is used globally and not firing events anymore due to some internal failure) and all future requests might fail or behave crazily +**否则:** 当一个未知的异常被抛出,意味着某些对象包含错误的状态(例如某个全局事件发生器由于某些内在的错误,不在产生事件),未来的请求可能失败或者行为异常。 -🔗 [**Read More: shutting the process**](/sections/errorhandling/shuttingtheprocess.md) +🔗 [**更多: 停掉服务**](/sections/errorhandling/shuttingtheprocess.md)

From a7ad703b0a334aa404cd6df636473a88b4dfbab5 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 30 Nov 2017 23:23:57 +0800 Subject: [PATCH 08/75] [Chinese-translation]README.chinese.md - add 2.5 and some minor changes. --- README.chinese.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 86f5e9870..b49298ba2 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -135,14 +135,13 @@

-## ![✔] 2.5 Document API errors using Swagger +## ![✔] 2.5 对API错误使用Swagger文档化 -**TL;DR:** Let your API callers know which errors might come in return so they can handle these thoughtfully without crashing. This is usually done with REST API documentation frameworks like Swagger +**TL;DR:** 让你的API调用者知道哪种错误会返回,这样他们就能完全的处理这些错误,而不至于系统崩溃。Swagger,REST API的文档框架,通常处理这类问题。 +**否则:** 任何API的客户端可能决定崩溃并重启,仅仅因为它收到一个不能处理的错误。注意:API的调用者可能是你(在微服务环境中非常典型)。 -**Otherwise:** An API client might decide to crash and restart only because he received back an error he couldn’t understand. Note: the caller of your API might be you (very typical in a microservice environment) - -🔗 [**Read More: documenting errors in Swagger**](/sections/errorhandling/documentingusingswagger.md) +🔗 [**更多: 使用Swagger记录错误**](/sections/errorhandling/documentingusingswagger.md)

@@ -158,9 +157,9 @@ -## ![✔] 2.7 Use a mature logger to increase error visibility +## ![✔] 2.7 使用一个成熟的日志工具提高错误的可见性 -**TL;DR:** A set of mature logging tools like Winston, Bunyan or Log4J, will speed-up error discovery and understanding. So forget about console.log. +**TL;DR:** 一系列成熟的日志工具,比如Winston,Bunyan和Log4J,会加速错误的发现和理解。忘记console.log吧。 **Otherwise:** Skimming through console.logs or manually through messy text file without querying tools or a decent log viewer might keep you busy at work until late @@ -216,9 +215,9 @@

⬆ Return to top

-# `3. Code Style Practices` +# `3. 编码风格实践` -## ![✔] 3.1 Use ESLint +## ![✔] 3.1 使用ESLint **TL;DR:** ESLint is the de-facto standard for checking code style, not only to identify nitty-gritty spacing issues but also to detect serious code anti-patterns like developers throwing errors without classification. Using ESLint and following the rest of the code style practices below means following the same styles used by the rest of the community, as well as the same code styles used in the core products themselves. @@ -226,7 +225,7 @@

-## ![✔] 3.2 Node JS Specific Plugins +## ![✔] 3.2 Node JS 特定的插件 **TL;DR:** On top of ESLint standard rules that cover vanilla JS only, add Node-specific plugins like [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) From b16d36c1b297b6523ede337ebd7b01fe1eb4775b Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 30 Nov 2017 23:37:14 +0800 Subject: [PATCH 09/75] [Chinese-translation]README.chinese.md - add 3.5 --- README.chinese.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index b49298ba2..be47bc5d2 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -265,11 +265,11 @@

-## ![✔] 3.5 Name Your Functions +## ![✔] 3.5 命名您的方法 -**TL;DR:** Name all functions, including closures and callbacks. Avoid anonymous functions. This is especially useful when profiling a node app. Naming all functions will allow you to easily understand what you're looking at when checking a memory snapshot. +**TL;DR:** 命名所有的方法,包含闭包和回调。避免匿名方法。当剖析一个node应用的时候,这是特别有用的。命名所有的方法将会使您非常容易的理解内存快照中您正在查看的内容。 -**Otherwise:** Debugging production issues using a core dump (memory snapshot) might become challenging as you notice significant memory consumption from anonymous functions. +**否则:** 使用一个核心dump(内存快照)调试线上问题,会是一项非常挑战的事项,因为你注意到的严重内存泄漏问题极有可能产生于匿名的方法。

From 6f0b5a9cadb6c4a908539395b0a11c6d9832e610 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 1 Dec 2017 13:16:36 +0800 Subject: [PATCH 10/75] [Chinese-translation]README.chinese.md - add 5.15. --- README.chinese.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index be47bc5d2..36f7cf175 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -629,14 +629,14 @@ All statements above will return false if used with `===`

-## ![✔] 5.15. Set NODE_ENV=production +## ![✔] 5.15. 设置NODE_ENV=production -**TL;DR:** Set the environment variable NODE_ENV to ‘production’ or ‘development’ to flag whether production optimizations should get activated – many NPM packages determining the current environment and optimize their code for production +**TL;DR:** 设置环境变量NODE_ENV为‘production’ 或者 ‘development’,这是一个是否激活上线优化的标志 - 很多NPM的包通过它来判断当前的环境,据此优化生产环境代码。 -**Otherwise:** Omitting this simple property might greatly degrade performance. For example, when using Express for server side rendering omitting NODE_ENV makes the slower by a factor of three! +**否则:** 遗漏这个简单的属性可能大幅减弱性能。例如,在使用Express作为服务端渲染页面的时候,如果未设置NODE_ENV,性能将会减慢大概三分之一! -🔗 [**Read More: Set NODE_ENV=production**](/sections/production/setnodeenv.md) +🔗 [**更多: 设置NODE_ENV=production**](/sections/production/setnodeenv.md)

From 5490185cd9660938f6cebf117ee119908c225cae Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 1 Dec 2017 17:02:37 +0800 Subject: [PATCH 11/75] [Chinese-translation]README.chinese.md - add 3.4 --- README.chinese.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 36f7cf175..9725ced13 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -257,11 +257,11 @@

-## ![✔] 3.4 Don't Forget the Semicolon +## ![✔] 3.4 不要忘记分号 -**TL;DR:** While not unanimously agreed upon, it is still recommended to put a semicolon at the end of each statement. This will make your code more readable and explicit to other developers who read it. +**TL;DR:** 即使没有获得一致的认同,但在每一个表达式后面放置分号还是值得推荐的。这将使您的代码, 对于其他阅读代码的开发者来说,可读性,明确性更强。 -**Otherwise:** As seen in the previous section, JavaScript's interpeter automatically adds a semicolon at the end of a statement if there isn't one which might lead to some undesired results. +**否则:** 在前面的章节里面已经提到,如果表达式的末尾没有添加分号,JavaScript的解释器会在自动添加一个,这可能会导致一些意想不到的结果。

From 82cdb0692d4a6c311d637802bb84e04306d7f862 Mon Sep 17 00:00:00 2001 From: lilanlan Date: Sat, 2 Dec 2017 15:26:12 +0800 Subject: [PATCH 12/75] =?UTF-8?q?separate=20Express=20=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../separateexpress.chinese.md | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 sections/projectstructre/separateexpress.chinese.md diff --git a/sections/projectstructre/separateexpress.chinese.md b/sections/projectstructre/separateexpress.chinese.md new file mode 100644 index 000000000..0c8771985 --- /dev/null +++ b/sections/projectstructre/separateexpress.chinese.md @@ -0,0 +1,63 @@ +# Express的 '应用' 和 '服务' 分离 + +

+ + +### 段落解释 + +最新的Express生成器有一个值得保留的伟大实践--API声明与网络相关配置(端口、协议等)是分开的。这样就可以在不执行网络调用的情况下对API进行在线测试,它所带来的好处是:快速执行测试操作和获取代码覆盖率。它还允许在灵活多样的网络条件下部署相同的AP。额外好处:更好的关注点分离和更清晰的代码结构。 + +

+ +### 代码示例: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; + }); +```` From 36df5070a3c660ae02cb1192e0edd5e46c773f72 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Mon, 4 Dec 2017 20:27:22 +0800 Subject: [PATCH 13/75] [Chinese-translation] README.chinese.md add 2.7 & 2.8 --- README.chinese.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 9725ced13..e64601911 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -161,22 +161,22 @@ **TL;DR:** 一系列成熟的日志工具,比如Winston,Bunyan和Log4J,会加速错误的发现和理解。忘记console.log吧。 -**Otherwise:** Skimming through console.logs or manually through messy text file without querying tools or a decent log viewer might keep you busy at work until late +**否则:** 浏览console的log,和不通过查询工具或者一个好的日志查看器,手动浏览繁琐的文本文件,会使你忙于工作到很晚。 -🔗 [**Read More: using a mature logger**](/sections/errorhandling/usematurelogger.md) +🔗 [**更多: 使用好用的日志工具**](/sections/errorhandling/usematurelogger.md)

-## ![✔] 2.8 Test error flows using your favorite test framework +## ![✔] 2.8 使用你最喜欢的测试框架测试错误流 -**TL;DR:** Whether professional automated QA or plain manual developer testing – Ensure that your code not only satisfies positive scenario but also handle and return the right errors. Testing frameworks like Mocha & Chai can handle this easily (see code examples within the "Gist popup") +**TL;DR:** 无论专业的自动化测试或者简单的手动开发测试 - 确保您的代码不仅满足正常的场景,而且处理并且返回正确的错误。测试框架,比如Mocha & Chai可以非常容易的处理这些问题(在"Gist popup"中查看代码实例) 。 -**Otherwise:** Without testing, whether automatically or manually, you can’t rely on our code to return the right errors. Without meaningful errors – there’s no error handling +**否则:** 没有测试,不管自动还是手动,您不可能依赖代码去返回正确的错误。而没有可以理解的错误,那将毫无错误处理可言。 -🔗 [**Read More: testing error flows**](/sections/errorhandling/testingerrorflows.md) +🔗 [**更多: 测试错误流向**](/sections/errorhandling/testingerrorflows.md)

From fd31f4ac529256b447a0335bc3593cfbb4353022 Mon Sep 17 00:00:00 2001 From: iamphr <353721401@qq.com> Date: Tue, 5 Dec 2017 11:13:43 +0800 Subject: [PATCH 14/75] Create thincomponents.chinese.md chinese.md --- .../projectstructre/thincomponents.chinese.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 sections/projectstructre/thincomponents.chinese.md diff --git a/sections/projectstructre/thincomponents.chinese.md b/sections/projectstructre/thincomponents.chinese.md new file mode 100644 index 000000000..0e9bb58a8 --- /dev/null +++ b/sections/projectstructre/thincomponents.chinese.md @@ -0,0 +1,23 @@ +# 用组件来构造你的解决方案 +

+ + +### 一段解释 + +对于中型应用以上来说,按部就班的写在一起真是太糟糕了-当一个有很多依赖的大型的软件会导致我们理解起来非常困难并且导致我们的代码杂乱不堪。甚至像那些能够熟练地驯服野兽的聪明的设计师一样,他们在设计上花费大量的精力用来"模块化"代码,每一次改动都需要仔细的评估对于其他依赖对象的影响。构建小型项目的最终方法是:将整体的项目分享一个个不与其他组件共享文件的独立组件,每个组件由很少的文件组成(例如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") From 78307bd9793e5e4730cce5f171eff0097bdc86c5 Mon Sep 17 00:00:00 2001 From: songxianjin Date: Tue, 5 Dec 2017 20:53:14 +0800 Subject: [PATCH 15/75] [Chinese-translation] production\productoncode.chinese.md --- sections/production/productoncode.chinese.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 sections/production/productoncode.chinese.md diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md new file mode 100644 index 000000000..fdd0a6229 --- /dev/null +++ b/sections/production/productoncode.chinese.md @@ -0,0 +1,18 @@ + +生产环境代码准备 + +

+ + +解释 +以下是影响生产维护和稳定性的开发技巧: + + +* 十二因素指南 – 熟悉十二因素 [Twelve factors](https://12factor.net/) +* 无状态-不在特定web服务器上保存本地数据(请参阅独立项目 - “Be Stateless”) +* 大量使用缓存,但不会因缓存不匹配而失败 +* 测试内存-测量内存使用情况和内存泄漏是开发流程的一部分,比如‘memwatch’这类工具可以极大地简化测量内存使用情况和内存泄漏。 +* 命名函数-最小化匿名函数(即内联回调)的用法作为典型内存测评器慧提供每隔方法名的内存占用。 +* 使用CI工具-使用CI工具在发送生产之前检测故障。例如,使用ESLint检测引用错误和未定义的变量。使用-trace-sync-io标识使用同步API的代码(而不是异步版本)。 +* 日志记录-在每个日志语句中希望以JSON格式记录上下文信息,以便像Elastic这样的日志聚合工具能够搜索这些属性(请参阅独立项目 - “使用智能日志提高可见性”)。此外,还包括标识每个请求的transaction-id 并允许关联描述相同事务的行(请参阅独立项目 - “Include Transaction-ID”) +* 错误管理 - 错误处理是Node.JS生产站点的薄弱环节-许多Node进程由于小错误而崩溃,而另一些进程虽然没有奔溃却一直处于错误状态。设置错误处理策略非常重要,请阅读我的【错误处理最佳实践】(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file From 992a9b4fa7ec0beafa3a2b59d4986437f906b79d Mon Sep 17 00:00:00 2001 From: leijingyun Date: Thu, 7 Dec 2017 18:47:55 +0800 Subject: [PATCH 16/75] [chinese_translation] add sections\production\productoncode.chinese.md --- sections/production/productoncode.chinese.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 sections/production/productoncode.chinese.md diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md new file mode 100644 index 000000000..6d02ebba4 --- /dev/null +++ b/sections/production/productoncode.chinese.md @@ -0,0 +1,15 @@ +# 使代码生产就绪 + +

+ + +### 段落讲解 +以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性: +*十二因素指南——熟悉[12因素](https://12factor.net/)指南 +*无状态——在一个特定的web服务器上不保存本地数据(参照独立的项目符号-“无状态的”) +*高速缓存——大量使用缓存,但由于缓存不匹配而不会失败 +*测试内存——测量内存的使用和泄漏,作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务 +*名称函数——将匿名函数(即内联callbabk)的使用最小化,作为一个典型的内存分析器将为每个方法名提供内存使用 +*使用CI工具——在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用- trace-sync- io来识别使用同步的api的代码(而不是异步版本) +*明确的日志——包括在每个日志语句上下文信息中,希望日志聚合工具是以json格式,如Elastic可以在这些属性上搜索(参照独立的项目符号——使用智能日志增加可见性)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅“包含事务id”) +*错误管理——错误处理是Node.js生产站点的致命弱点——许多节点进程由于小错误而崩溃,而其他节点则在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的,在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file From 3d2aa27af156b5274689ef8449791505341c9e5a Mon Sep 17 00:00:00 2001 From: matt_jin Date: Thu, 7 Dec 2017 19:28:19 +0800 Subject: [PATCH 17/75] [Chinese-translation] README.chinese.md add 2.3 --- README.chinese.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index e64601911..60d813637 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -115,13 +115,13 @@

-## ![✔] 2.3 Distinguish operational vs programmer errors +## ![✔] 2.3 区分运行错误和程序设计错误 -**TL;DR:** Operational errors (e.g. API received an invalid input) refer to known cases where the error impact is fully understood and can be handled thoughtfully. On the other hand, programmer error (e.g. trying to read undefined variable) refers to unknown code failures that dictate to gracefully restart the application +**TL;DR:** 运行错误(例如, API接受到一个无效的输入)指的是一些已知场景下的错误,这类错误的影响已经完全被理解,并能被考虑周全的处理掉。同时,程序设计错误(例如,尝试读取未定义的变量)指的是未知的编码问题,影响到应用得当的重启。 -**Otherwise:** You may always restart the application when an error appears, but why let ~5000 online users down because of a minor, predicted, operational error? the opposite is also not ideal – keeping the application up when an unknown issue (programmer error) occurred might lead to an unpredicted behavior. Differentiating the two allows acting tactfully and applying a balanced approach based on the given context +**否则:** 当一个错误产生的时候,您总是得重启应用,但为什么要让 ~5000 个在线用户不能访问,仅仅是因为一个细微的,可以预测的,运行时错误?相反的方案,也不完美 – 当未知的问题(程序问题)产生的时候,使应用依旧可以访问,可能导致不可预测行为。区分两者会使处理更有技巧,并在给定的上下文下给出一个平衡的对策。 - 🔗 [**Read More: operational vs programmer error**](/sections/errorhandling/operationalvsprogrammererror.md) +🔗 [**更多: 运行错误和程序设计错误**](/sections/errorhandling/operationalvsprogrammererror.md)

From 22777998655839ceb5211afc823a139b99743dba Mon Sep 17 00:00:00 2001 From: leijingyun Date: Fri, 8 Dec 2017 11:32:39 +0800 Subject: [PATCH 18/75] [chinese-translation]remodification sections\production\productoncode.chinese.md --- sections/production/productoncode.chinese.md | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md index 6d02ebba4..1a0341aa7 100644 --- a/sections/production/productoncode.chinese.md +++ b/sections/production/productoncode.chinese.md @@ -1,15 +1,15 @@ -# 使代码生产就绪 +代码生产环境的准备 -

-### 段落讲解 以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性: -*十二因素指南——熟悉[12因素](https://12factor.net/)指南 -*无状态——在一个特定的web服务器上不保存本地数据(参照独立的项目符号-“无状态的”) -*高速缓存——大量使用缓存,但由于缓存不匹配而不会失败 -*测试内存——测量内存的使用和泄漏,作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务 -*名称函数——将匿名函数(即内联callbabk)的使用最小化,作为一个典型的内存分析器将为每个方法名提供内存使用 -*使用CI工具——在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用- trace-sync- io来识别使用同步的api的代码(而不是异步版本) -*明确的日志——包括在每个日志语句上下文信息中,希望日志聚合工具是以json格式,如Elastic可以在这些属性上搜索(参照独立的项目符号——使用智能日志增加可见性)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅“包含事务id”) -*错误管理——错误处理是Node.js生产站点的致命弱点——许多节点进程由于小错误而崩溃,而其他节点则在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的,在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file + + +* 十二因素指南 — 熟悉[12因素](https://12factor.net/) +* 无状态 — 在一个特定的web服务器上不保存本地数据(请参阅独立项目-“Be Stateless”) +* 高速缓存 — 大量使用缓存,但不会因为缓存不匹配而失败 +* 测试内存 — 测量内存的使用和泄漏,是作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务 +* 命名函数 — 将匿名函数(即内联callbabk)的使用最小化,作为一个典型的内存分析器为每个方法名提供内存使用 +* 使用CI工具 — 在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用- trace-sync-io来识别用了同步的api代码(而不是异步版本) +* 明确的日志 — 包括在每个日志语句中希望用json格式记录上下文信息,以便于日志聚合工具,如Elastic可以在这些属性上搜索(请参阅独立项目 — 使 使用智能日志增加可见性)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅“Include Transaction-ID”) +* 错误管理 — 错误处理是Node.js生产站点的致命弱点——许多节点进程由于小错误而崩溃,然而其他节点则会在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的,在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file From f23c2393169ead46bcfe682202f44a8cb1107af7 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 8 Dec 2017 17:25:00 +0800 Subject: [PATCH 19/75] [Chinese-translation] README.chinese.md add 2.10 --- README.chinese.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 60d813637..5bcdccc89 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -192,14 +192,14 @@

-## ![✔] 2.10 Catch unhandled promise rejections +## ![✔] 2.10 捕获未处理的promise rejections -**TL;DR:** Any exception thrown within a promise will get swallowed and discarded unless a developer didn’t forget to explictly handle. Even if your code is subscribed to process.uncaughtException! Overcome this by registering to the event process.unhandledRejection +**TL;DR:** 任何在promise中被抛出的异常将被收回和遗弃,除非开发者没有忘记去明确的处理。即使您的代码调用的是process.uncaughtException!解决这个问题可以注册到事件process.unhandledRejection。 -**Otherwise:** Your errors will get swallowed and leave no trace. Nothing to worry about +**否则:** 您的错误将被回收,无踪迹可循。没有什么可以需要考虑。 -🔗 [**Read More: catching unhandled promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.md) +🔗 [**更多: 捕获未处理的promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.md)

From fb9a072a69fb8a0b18530823038348a1ebbd34ed Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 8 Dec 2017 17:43:52 +0800 Subject: [PATCH 20/75] [Chinese-translation] README.chinese.md -- add 2.11 --- README.chinese.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 5bcdccc89..ed59d3aef 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -203,13 +203,13 @@

-## ![✔] 2.11 Fail fast, validate arguments using a dedicated library +## ![✔] 2.11 快速查错,验证参数使用一个专门的库Fail fast, validate arguments using a dedicated library -**TL;DR:** This should be part of your Express best practices – Assert API input to avoid nasty bugs that are much harder to track later. Validation code is usually tedious unless using a very cool helper libraries like Joi +**TL;DR:** 这应该是您的Express最佳实践中的一部分 – assert API输入避免难以理解的漏洞,这类漏洞以后会非常难以追踪。而验证代码通常是一件乏味的事情,除非使用一些非常炫酷的帮助库比如Joi。 -**Otherwise:** Consider this – your function expects a numeric argument “Discount” which the caller forgets to pass, later on your code checks if Discount!=0 (amount of allowed discount is greater than zero), then it will allow the user to enjoy a discount. OMG, what a nasty bug. Can you see it? +**否则:** 考虑这种情况 – 您的功能期望一个数字参数 “Discount” ,然而调用者忘记传值,之后在您的代码中检查是否 Discount!=0 (允许的折扣值大于零),这样它将允许用户使用一个折扣。OMG,多么不爽的一个漏洞。你能明白吗? -🔗 [**Read More: failing fast**](/sections/errorhandling/failfast.md) +🔗 [**更多: 快速查错**](/sections/errorhandling/failfast.md)


From 14858d5be4c8b537a521c424773653afb5b92013 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 8 Dec 2017 17:55:38 +0800 Subject: [PATCH 21/75] [Chinese-translation]README.chinese.md -- add 2.9 --- README.chinese.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index ed59d3aef..2c7d18fa2 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -180,14 +180,14 @@

-## ![✔] 2.9 Discover errors and downtime using APM products +## ![✔] 2.9 使用APM产品发现错误和宕机时间 -**TL;DR:** Monitoring and performance products (a.k.a APM) proactively gauge your codebase or API so they can auto-magically highlight errors, crashes and slow parts that you were missing +**TL;DR:** 监控和性能产品 (别名 APM) 先前一步的检测您的代码库和API,这样他们能自动的,像使用魔法一样的强调错误,宕机和您忽略的性能慢的部分。 -**Otherwise:** You might spend great effort on measuring API performance and downtimes, probably you’ll never be aware which are your slowest code parts under real world scenario and how these affects the UX +**否则:** 您花了很多的力气在测量API的性能和错误,但可能您从来没有意识到真实场景下您最慢的代码块和他们对UX的影响。 -🔗 [**Read More: using APM products**](/sections/errorhandling/apmproducts.md) +🔗 [**更多: 使用APM产品**](/sections/errorhandling/apmproducts.md)

From ab7192de2ea8dba9a9b4b01bf08dda09d31732fd Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 8 Dec 2017 18:32:10 +0800 Subject: [PATCH 22/75] [Chinese-translation] README.chinese.md - add 3.1 --- README.chinese.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 2c7d18fa2..030327f3a 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -219,9 +219,9 @@ ## ![✔] 3.1 使用ESLint -**TL;DR:** ESLint is the de-facto standard for checking code style, not only to identify nitty-gritty spacing issues but also to detect serious code anti-patterns like developers throwing errors without classification. Using ESLint and following the rest of the code style practices below means following the same styles used by the rest of the community, as well as the same code styles used in the core products themselves. +**TL;DR:** ESLint是检查代码风格的事实上的标准,不仅要查明实际的间距问题,也要检测严重的反模式问题,像开发者没有分类的抛出异常。使用ESLint及下面列出的其他的代码风格实践,意味着和社区里的其他人保持同一种风格,以及用在核心产品本身相同的代码风格。 -**Otherwise:** developers will focus on tedious spacing and line-width concerns +**否则:** 开发者必须专注于单调的间距和线宽的问题上。

From d1929eef3e7d751be3bf3493e07af9fb795e4085 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sat, 9 Dec 2017 14:52:37 +0800 Subject: [PATCH 23/75] [Chinese-translation] README.chinese.md - add 3.2 3.3 3.6 3.7 --- README.chinese.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 030327f3a..e8f64f7d2 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -227,33 +227,33 @@ ## ![✔] 3.2 Node JS 特定的插件 -**TL;DR:** On top of ESLint standard rules that cover vanilla JS only, add Node-specific plugins like [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) +**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) -**Otherwise:** Many faulty Node.JS code patterns might escape under the radar. For example, developers might require(variableAsPath) files with a variable given as path which allows attackers to execute any JS script. Node.JS linters can detect such patterns and complain early +**否则:** 许多错误的Node.js代码模式可能在检测下逃生。例如,开发人员可能需要某些文件,把一个变量作为路径名 (variableAsPath) ,这会导致攻击者可以执行任何JS脚本。Node.JS linters可以检测这类模式,并及早预警。

-## ![✔] 3.3 Start a Codeblock's Curly Braces in the Same Line +## ![✔] 3.3 在同一行开始一个代码块的大括号 -**TL;DR:** The opening curly braces of a code block should be in the same line of the opening statement. +**TL;DR:** 代码块的第一个大括号应该和声明的起始保持在同一行中。 -### Code Example +### 代码示例 ```javascript - // Do + // 建议 function someFunction() { - // code block + // 代码块 } - //Avoid + // 避免 function someFunction { - // code block + // 代码块 } ``` -**Otherwise:** Deferring from this best practice might lead to unexpected results, as seen in the Stackoverflow thread below: +**否则:** 不遵守这项最佳实践可能导致意外的结果,在Stackoverflow的帖子中可以查看到,如下: -🔗 [**Read more:** "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) +🔗 [**更多:** "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)

@@ -273,23 +273,23 @@

-## ![✔] 3.6 Naming conventions for variables, constants, functions and classes +## ![✔] 3.6 变量、常量、函数和类的命名约定 -**TL;DR:** Use ***lowerCamelCase*** when naming variables and functions, ***UpperCamelCase*** (capital first letter as well) when naming classes and ***UPPERCASE*** for constants. This will help you to easily distinguish between plain variables / functions, and classes that require instantiation. Use descriptive names, but try to keep them short. +**TL;DR:** 当命名变量和方法的时候,使用 ***lowerCamelCase*** , 当命名类的时候,使用***UpperCamelCase*** (首字母大写),对于常量,则***UPPERCASE***。这将帮助您轻松地区分普通变量/函数和需要实例化的类。使用描述性名称,但使它们尽量简短。 -**Otherwise:** Javascript is the only language in the world which allows to invoke a constructor ("Class") directly without instantiating it first. Consequently, Classes and function-constructors are differentiated by starting with UpperCamelCase. +**否则:** JavaScript是世界上唯一一门不需要实例化,就可以直接调用构造函数("Class")的编码语言。因此,类和函数的构造函数由采用UpperCamelCase开始区分。 -### Code Example ### +### 代码示例 ### ```javascript - // for class name we use UpperCamelCase + // 使用UpperCamelCase命名类名 class SomeClassExample () { - // for const name we use UPPERCASE + // 常量使用UPPERCASE const CONFIG = { key: 'value' }; - // for variables and functions names we use lowerCamelCase + // 变量和方法使用lowerCamelCase let someVariableExample = 'value'; function doSomething() { @@ -300,13 +300,13 @@

-## ![✔] 3.7 Prefer const over let. Ditch the var +## ![✔] 3.7 使用const优于let,废弃var -**TL;DR:** Using `const` means that once a variable is assigned, it cannot be reassigned. Prefering const will help you to not be tempted to use the same variable for different uses, and make your code clearer. If a variable needs to be reassigned, in a for loop for example, use `let` to declare it. Another important aspect of let is that a variable declared using let is only available in the block scope in which it was defined. `var` is function scoped, not block scoped, and [shouldn't be used in ES6](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70) now that you have const and let at your disposal. +**TL;DR:** 使用` const `意味着一旦一个变量被分配,它不能被重新分配。使用const将帮助您免于使用相同的变量用于不同的用途,并使你的代码更清晰。如果一个变量需要被重新分配,以在一个循环为例,使用 `let` 声明它。let的另一个重要方面是,使用let声明的变量只在定义它的块作用域中可用。 `var` 是函数作用域,不是块级作用域,既然您有const和let让您随意使用,那么[不应该在ES6中使用var](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70)。 -**Otherwise:** Debugging becomes way more cumbersome when following a variable that frequently changes. +**否则:** 当经常更改变量时,调试变得更麻烦了。 -🔗 [**Read more: JavaScript ES6+: var, let, or const?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75) +🔗 [**更多: JavaScript ES6+: var, let, or const?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75)

From b662665197f5bb4397ed6c87f2800a9f21de40e9 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sat, 9 Dec 2017 18:28:01 +0800 Subject: [PATCH 24/75] [Chinese-translation] README.chinese.md - add 3.8, 3.9, 3.10,3.11,3.12,5.1~5.6 --- README.chinese.md | 101 +++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index e8f64f7d2..e00b27256 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -312,28 +312,27 @@ ## ![✔] 3.8 Requires come first, and not inside functions -**TL;DR:** Require modules at the beginning of each file, before and outside of any functions. This simple best practice will not only help you easily and quickly tell the dependencies of a file right at the top, but also avoids a couple of potential problems. +**TL;DR:** 在每个文件的起始位置,在任何函数的前面和外部 require 模块。这种简单的最佳实践,不仅能帮助您轻松快速地在文件顶部辨别出依赖关系,而且避免了一些潜在的问题。 -**Otherwise:** Requires are run synchronously by NodeJS. If they are called from within a function, it may block other requests from being handled at a more critical time. Also, if a required module or any of its own dependencies throw an error and crash the server, it is best to find out about it as soon as possible, which might not be the case if that module is required from within a function. +**否则:** 在 NodeJs 中,require 是同步运行的。如果从函数中调用它们,它可能会阻塞其他请求,在更关键的时间得到处理。另外,如果所 require 的模块或它自己的任何依赖项抛出错误并使服务器崩溃,最好尽快查明它,如果该模块在函数中 require 的,则可能不是这样的情况。

-## ![✔] 3.9 Do Require on the folders, not directly on the files +## ![✔] 3.9 在文件夹上 require ,而不是直接在文件上 -**TL;DR:** When developing a module/library in a folder, place an index.js file that exposes the module's -internals so every consumer will pass through it. This serves as an 'interface' to your module and ease -future changes without breaking the contract. +**TL;DR:** 当在一个文件夹中开发库/模块,放置一个文件index.js暴露模块的 +内部,这样每个消费者都会通过它。这将作为您模块的一个接口,并使 +未来的变化简单而不违反规则。 -**Otherwise:** Changing to the internal structure of files or the signature may break the interface with -clients. +**否则:** 更改文件内部结构或签名可能会破坏与客户端的接口。 -### Code example +### 代码示例 ```javascript - // Do + // 建议 module.exports.SMSProvider = require('./SMSProvider'); module.exports.SMSNumberResolver = require('./SMSNumberResolver'); - // Avoid + // 避免 module.exports.SMSProvider = require('./SMSProvider/SMSProvider.js'); module.exports.SMSNumberResolver = require('./SMSNumberResolver/SMSNumberResolver.js'); ``` @@ -341,13 +340,13 @@ clients.

-## ![✔] 3.10 Use the `===` operator +## ![✔] 3.10 使用 `===` 操作符 -**TL;DR:** Prefer the strict equality operator `===` over the weaker abstract equality operator `==`. `==` will compare two variables after converting them to a common type. There is no type conversion in `===`, and both variables must be of the same type to be equal. +**TL;DR:** 对比弱等于 `==`,优先使用严格的全等于 `===` 。`==`将在它们转换为普通类型后比较两个变量。在 `===` 中没有类型转换,并且两个变量必须是相同的类型。 -**Otherwise:** Unequal variables might return true when compared with the `==` operator. +**否则:** 与 `==` 操作符比较,不相等的变量可能会返回true。 -### Code example +### 代码示例 ```javascript '' == '0' // false 0 == '' // true @@ -362,27 +361,27 @@ null == undefined // true ' \t\r\n ' == 0 // true ``` -All statements above will return false if used with `===` +如果使用`===`, 上面所有语句都将返回 false。

-## ![✔] 3.11 Use Async Await, avoid callbacks +## ![✔] 3.11 使用 Async Await, 避免回调 -**TL;DR:** Node 8 LTS now has full support for Async-await. This is a new way of dealing with asyncronous code which supersedes callbacks and promises. Async-await is non-blocking, and it makes asynchronous code look synchronous. The best gift you can give to your code is using async-await which provides a much more compact and familiar code syntax like try-catch. +**TL;DR:** Node 8 LTS现已全面支持异步等待。这是一种新的方式处理异步请求,取代回调和promise。Async-await是非阻塞的,它使异步代码看起来像是同步的。你可以给你的代码的最好的礼物是用async-await提供了一个更紧凑的,熟悉的,类似try catch的代码语法。 -**Otherwise:** Handling async errors in callback style is probably the fastest way to hell - this style forces to check errors all over, deal with akward code nesting and make it difficult to reason about the code flow. +**否则:** 使用回调的方式处理异步错误可能是陷入困境最快的方式 - 这种方式必须面对不停地检测错误,处理别扭的代码内嵌,难以推理编码流。 -🔗[**Read more:** Guide to async await 1.0](https://github.com/yortus/asyncawait) +🔗[**更多:** async await 1.0 引导](https://github.com/yortus/asyncawait)

-## ![✔] 3.12 Use Fat (=>) Arrow Functions +## ![✔] 3.12 使用 (=>) 箭头函数 -**TL;DR:** Though it's recommended to use async-await and avoid function parameters, when dealing with older API that accept promises or callbacks - arrow functions make the code structure more compact and keep the lexical context of the root function (i.e. 'this'). +**TL;DR:** 尽管使用 async-await 和避免方法作为参数是被推荐的, 但当处理那些接受promise和回调的老的API的时候 - 箭头函数使代码结构更加紧凑,并保持了根方法上的语义上下文 (例如 'this')。 -**Otherwise:** Longer code (in ES5 functions) is more prone to bugs and cumbersome to read. +**否则:** 更长的代码(在ES5方法中)更易于产生缺陷,并读起来很是笨重。 -🔗 [**Read mode: It’s Time to Embrace Arrow Functions**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) +🔗 [**更多: It’s Time to Embrace Arrow Functions**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75)


@@ -390,9 +389,9 @@ All statements above will return false if used with `===`

⬆ Return to top

-# `4. Testing And Overall Quality Practices` +# `4. 测试和总体的质量实践` -## ![✔] 4.1 At the very least, write API (component) testing +## ![✔] 4.1 至少,编写API(组件)测试 **TL;DR:** Most projects just don't have any automated testing due to short time tables or often the 'testing project' run out of control and being abandoned. For that reason, prioritize and start with API testing which are the easiest to write and provide more coverage than unit testing (you may even craft API tests without code using tools like [Postman](https://www.getpostman.com/). Afterwards, should you have more resources and time, continue with advanced test types like unit testing, DB testing, performance testing, etc @@ -465,71 +464,71 @@ All statements above will return false if used with `===`

⬆ Return to top

-# `5. Going To Production Practices` -## ![✔] 5.1. Monitoring! +# `5. 上线实践` +## ![✔] 5.1. 监控! -**TL;DR:** Monitoring is a game of finding out issues before customers do – obviously this should be assigned unprecedented importance. The market is overwhelmed with offers thus consider starting with defining the basic metrics you must follow (my suggestions inside), then go over additional fancy features and choose the solution that ticks all boxes. Click ‘The Gist’ below for overview of solutions +**TL;DR:** 监控是一种在顾客之前发现问题的游戏 – 显然这应该被赋予前所未有的重要性。考虑从定义你必须遵循的基本度量标准开始(我的建议在里面),到检查附加的花哨特性并选择解决所有问题的解决方案。市场已经淹没其中。点击下面的 ‘The Gist’ ,了解解决方案的概述。 -**Otherwise:** Failure === disappointed customers. Simple. +**否则:** 错误 === 失望的客户. 非常简单. -🔗 [**Read More: Monitoring!**](/sections/production/monitoring.md) +🔗 [**更多: 监控!**](/sections/production/monitoring.md)

-## ![✔] 5.2. Increase transparency using smart logging +## ![✔] 5.2. 使用智能日志增加透明度Increase transparency using smart logging -**TL;DR:** Logs can be a dumb warehouse of debug statements or the enabler of a beautiful dashboard that tells the story of your app. Plan your logging platform from day 1: how logs are collected, stored and analyzed to ensure that the desired information (e.g. error rate, following an entire transaction through services and servers, etc) can really be extracted +**TL;DR:** 日志可以是调试语句的一个不能说话的仓库,或者表述应用运行过程的一个漂亮仪表板的驱动。从第1天计划您的日志平台:如何收集、存储和分析日志,以确保所需信息(例如,错误率、通过服务和服务器等完成整个事务)都能被提取出来。 -**Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information +**否则:** 您最终像是面对一个黑盒,不知道发生了什么事情,然后你开始重新写日志语句添加额外的信息。 -🔗 [**Read More: Increase transparency using smart logging**](/sections/production/smartlogging.md) +🔗 [**更多: Increase transparency using smart logging**](/sections/production/smartlogging.md)

-## ![✔] 5.3. Delegate anything possible (e.g. gzip, SSL) to a reverse proxy +## ![✔] 5.3. 委托一切可能的(例如:gzip,SSL)给反向代理 -**TL;DR:** Node is awfully bad at doing CPU intensive tasks like gzipping, SSL termination, etc. Instead, use a ‘real’ middleware services like nginx, HAproxy or cloud vendor services +**TL;DR:** node处理CPU密集型任务,如gzipping,SSL termination等,表现糟糕。相反,使用一个 ‘真正’ 的中间件服务像Nginx,HAProxy或者云供应商的服务。 -**Otherwise:** Your poor single thread will keep busy doing networking tasks instead of dealing with your application core and performance will degrade accordingly +**否则:** 单线程的node服务器将不幸地忙于处理网络任务,而不是处理应用程序核心,性能会相应降低。 -🔗 [**Read More: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy**](/sections/production/delegatetoproxy.md) +🔗 [**更多: 委托一切可能的(例如:gzip,SSL)给反向代理**](/sections/production/delegatetoproxy.md)

-## ![✔] 5.4. Lock dependencies +## ![✔] 5.4. 锁住依赖 -**TL;DR:** Your code must be identical across all environments, but amazingly NPM lets dependencies drift across environments by default – when you install packages at various environments it tries to fetch packages’ latest patch version. Overcome this by using NPM config files , .npmrc, that tell each environment to save the exact (not the latest) version of each package. Alternatively, for finer grain control use NPM” shrinkwrap”. *Update: as of NPM5 , dependencies are locked by default. The new package manager in town, Yarn, also got us covered by default +**TL;DR:** 您的代码必须在所有的环境中是相同的,但是令人惊讶的是,NPM默认情况下会让依赖在不同环境下发生偏移 – 当在不同的环境中安装包的时候,它试图拿包的最新版本。克服这种问题可以利用NPM配置文件, .npmrc,告诉每个环境保存准确的(不是最新的)包的版本。另外,对于更精细的控制,使用NPM “shrinkwrap”。*更新:作为NPM5,依赖默认锁定。新的包管理工具,Yarn,也默认锁定。 -**Otherwise:** QA will thoroughly test the code and approve a version that will behave differently at production. Even worse, different servers at the same production cluster might run different code +**否则:** QA测试通过的代码和批准的版本,在生产中表现不一致。更糟糕的是,同一生产集群中的不同服务器可能运行不同的代码。 -🔗 [**Read More: Lock dependencies**](/sections/production/lockdependencies.md) +🔗 [**更多: 锁住依赖**](/sections/production/lockdependencies.md)

-## ![✔] 5.5. Guard process uptime using the right tool +## ![✔] 5.5. 使用正确的工具保护进程正常运行 -**TL;DR:** The process must go on and get restarted upon failures. For simple scenario, ‘restarter’ tools like PM2 might be enough but in today ‘dockerized’ world – a cluster management tools should be considered as well +**TL;DR:** 进程必须继续运行,并在失败时重新启动。对于简单的情况下,“重启”工具如PM2可能足够,但在今天的“Dockerized”世界 – 集群管理工具也值得考虑 -**Otherwise:** Running dozens of instances without clear strategy and too many tools together (cluster management, docker, PM2) might lead to a devops chaos +**否则:** 运行几十个实例没有明确的战略和太多的工具(集群管理,docker,PM2)可能导致一个DevOps混乱 -🔗 [**Read More: Guard process uptime using the right tool**](/sections/production/guardprocess.md) +🔗 [**更多: 使用正确的工具保护进程正常运行**](/sections/production/guardprocess.md)

-## ![✔] 5.6. Utilize all CPU cores +## ![✔] 5.6. 利用CPU多核 -**TL;DR:** At its basic form, a Node app runs on a single CPU core while all other are left idling. It’s your duty to replicate the Node process and utilize all CPUs – For small-medium apps you may use Node Cluster or PM2. For a larger app consider replicating the process using some Docker cluster (e.g. K8S, ECS) or deployment scripts that are based on Linux init system (e.g. systemd) +**TL;DR:** 在基本形式上,node应用程序运行在单个CPU核心上,而其他都处于空闲状态。复制node进程和利用多核,这是您的职责 – 对于中小应用,您可以使用Node Cluster和PM2. 对于一个大的应用,可以考虑使用一些Docker cluster(例如k8s,ECS)复制进程或基于Linux init system(例如systemd)的部署脚本 -**Otherwise:** Your app will likely utilize only 25% of its available resources(!) or even less. Note that a typical server has 4 CPU cores or more, naive deployment of Node.JS utilizes only 1 (even using PaaS services like AWS beanstalk!) +**否则:** 您的应用可能只是使用了其可用资源中的25% (!),甚至更少。注意,一台典型的服务器有4个或更多的CPU,默认的Node.JS部署仅仅用了一个CPU(甚至使用PaaS服务,比如AWS beanstalk,也一样)。 -🔗 [**Read More: Utilize all CPU cores**](/sections/production/utilizecpu.md) +🔗 [**更多: 利用所有的CPU**](/sections/production/utilizecpu.md)

From 82edd79b278d5f33e63d1df6a7d3740ac96ce238 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sun, 10 Dec 2017 17:12:47 +0800 Subject: [PATCH 25/75] [Chinese-translation] README.chinese.md - add 5.x --- README.chinese.md | 70 +++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index e00b27256..c48e92d20 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -532,98 +532,98 @@ null == undefined // true

-## ![✔] 5.7. Create a ‘maintenance endpoint’ +## ![✔] 5.7. 创建一个“维护端点” -**TL;DR:** Expose a set of system-related information, like memory usage and REPL, etc in a secured API. Although it’s highly recommended to rely on standard and battle-tests tools, some valuable information and operations are easier done using code +**TL;DR:** 在一个安全的API中暴露一组系统相关的信息,比如内存使用情况和REPL等等。尽管这里强烈建议依赖标准和作战测试工具,但一些有价值的信息和操作更容易使用代码完成。 -**Otherwise:** You’ll find that you’re performing many “diagnostic deploys” – shipping code to production only to extract some information for diagnostic purposes +**否则:** 您会发现,您正在执行许多“诊断部署” — 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。 -🔗 [**Read More: Create a ‘maintenance endpoint’**](/sections/production/createmaintenanceendpoint.md) +🔗 [**更多: 创建一个 ‘维护端点’ **](/sections/production/createmaintenanceendpoint.md)

-## ![✔] 5.8. Discover errors and downtime using APM products +## ![✔] 5.8. 使用APM产品发现错误和宕机时间 -**TL;DR:** Monitoring and performance products (a.k.a APM) proactively gauge codebase and API so they can auto-magically go beyond traditional monitoring and measure the overall user-experience across services and tiers. For example, some APM products can highlight a transaction that loads too slow on the end-users side while suggesting the root cause +**TL;DR:** 监控和性能的产品(即APM)先前一步地评估代码库和API,自动的超过传统的监测,并测量在服务和层级上的整体用户体验。例如,一些APM产品可以突显导致最终用户负载过慢的事务,同时指出根本原因。 -**Otherwise:** You might spend great effort on measuring API performance and downtimes, probably you’ll never be aware which is your slowest code parts under real world scenario and how these affects the UX +**否则:** 你可能会花大力气测量API性能和停机时间,也许你永远不会知道,真实场景下哪个是你最慢的代码部分,这些怎么影响用户体验。 -🔗 [**Read More: Discover errors and downtime using APM products**](/sections/production/apmproducts.md) +🔗 [**更多: 使用APM产品发现错误和宕机时间**](/sections/production/apmproducts.md)

-## ![✔] 5.9. Make your code production-ready +## ![✔] 5.9. 使您的代码保持生产环境就绪 -**TL;DR:** Code with the end in mind, plan for production from day 1. This sounds a bit vague so I’ve compiled a few development tips that are closely related to production maintenance (click Gist below) +**TL;DR:** 在意识中抱着最终上线的想法进行编码,从第1天开始计划上线。这听起来有点模糊,所以我编写了一些与生产维护密切相关的开发技巧(点击下面的要点) -**Otherwise:** A world champion IT/devops guy won’t save a system that is badly written +**否则:** 一个世界冠军级别的IT/运维人员也不能拯救一个编码低劣的系统。 -🔗 [**Read More: Make your code production-ready**](/sections/production/productoncode.md) +🔗 [**更多: 使您的代码保持生产环境就绪**](/sections/production/productoncode.md)

-## ![✔] 5.10. Measure and guard the memory usage +## ![✔] 5.10. 测量和保护内存使用 -**TL;DR:** Node.js has controversial relationships with memory: the v8 engine has soft limits on memory usage (1.4GB) and there are known paths to leaks memory in Node’s code – thus watching Node’s process memory is a must. In small apps you may gauge memory periodically using shell commands but in medium-large app consider baking your memory watch into a robust monitoring system +**TL;DR:** Node.js和内存有引起争论的联系:V8引擎对内存的使用有稍微的限制(1.4GB),在node的代码里面有内存泄漏的很多途径 – 因此监视node的进程内存是必须的。在小应用程序中,你可以使用shell命令周期性地测量内存,但在中等规模的应用程序中,考虑把内存监控建成一个健壮的监控系统。 -**Otherwise:** Your process memory might leak a hundred megabytes a day like happened in Wallmart +**否则:** 您的内存可能一天泄漏一百兆,就像曾发生在沃尔玛的一样。 -🔗 [**Read More: Measure and guard the memory usage**](/sections/production/measurememory.md) +🔗 [**更多: 测量和保护内存使用**](/sections/production/measurememory.md)

-## ![✔] 5.11. Get your frontend assets out of Node +## ![✔] 5.11. Node外管理您的前端资源 -**TL;DR:** Serve frontend content using dedicated middleware (nginx, S3, CDN) because Node performance really gets hurt when dealing with many static files due to its single threaded model +**TL;DR:** 使用专门的中间件(nginx,S3,CDN)服务前端内容,这是因为在处理大量静态文件的时候,由于node的单线程模型,它的性能很受影响。 -**Otherwise:** Your single Node thread will be busy streaming hundreds of html/images/angular/react files instead of allocating all its resources for the task it was born for – serving dynamic content +**否则:** 您的单个node线程将忙于传输成百上千的html/图片/angular/react文件,而不是分配其所有的资源为了其擅长的任务 – 服务动态内容 -🔗 [**Read More: Get your frontend assets out of Node**](/sections/production/frontendout.md) +🔗 [**更多: Node外管理您的前端资源**](/sections/production/frontendout.md)

-## ![✔] 5.12. Be stateless, kill your Servers almost every day +## ![✔] 5.12. 保持无状态,几乎每天都要停下服务器 -**TL;DR:** Store any type of data (e.g. users session, cache, uploaded files) within external data stores. Consider ‘killing’ your servers periodically or use ‘serverless’ platform (e.g. AWS Lambda) that explicitly enforces a stateless behavior +**TL;DR:** 在外部数据存储上,存储任意类型数据(例如用户会话,缓存,上传文件)。考虑间隔地停掉您的服务器或者使用 ‘serverless’ 平台(例如 AWS Lambda),这是一个明确的强化无状态的行为。 -**Otherwise:** Failure at a given server will result in application downtime instead of just killing a faulty machine. Moreover, scaling-out elasticity will get more challenging due to the reliance on a specific server +**否则:** 某个服务器上的故障将导致应用程序宕机,而不仅仅是停用故障机器。此外,由于依赖特定服务器,伸缩弹性会变得更具挑战性。 -🔗 [**Read More: Be stateless, kill your Servers almost every day**](/sections/production/bestateless.md) +🔗 [**Read More: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.md)

-## ![✔] 5.13. Use tools that automatically detect vulnerabilities +## ![✔] 5.13. 使用自动检测漏洞的工具 -**TL;DR:** Even the most reputable dependencies such as Express have known vulnerabilities (from time to time) that can put a system at risk. This can get easily tamed using community and commercial tools that constantly check for vulnerabilities and warn (locally or at GitHub), some can even patch them immediately +**TL;DR:** 即使是最有信誉的依赖项,比如Express,会有使系统处于危险境地的已知漏洞(随着时间推移)。通过使用社区的或者商业工具,不时的检查漏洞和警告(本地或者Github上),这类问题很容易被抑制,有些问题甚至可以立即修补。 -**Otherwise:** Otherwise: Keeping your code clean from vulnerabilities without dedicated tools will require to constantly follow online publications about new threats. Quite tedious +**否则:** 否则: 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物。相当繁琐。 -🔗 [**Read More: Use tools that automatically detect vulnerabilities**](/sections/production/detectvulnerabilities.md) +🔗 [**更多: 使用自动检测漏洞的工具**](/sections/production/detectvulnerabilities.md)

-## ![✔] 5.14. Assign ‘TransactionId’ to each log statement +## ![✔] 5.14. 在每一个log语句中指明 ‘TransactionId’ -**TL;DR:** Assign the same identifier, transaction-id: {some value}, to each log entry within a single request. Then when inspecting errors in logs, easily conclude what happened before and after. Unfortunately, this is not easy to achieve in Node due its async nature, see code examples inside +**TL;DR:** 在每一个请求的每一条log入口,指明同一个标识符,transaction-id: {某些值}。然后在检查日志中的错误时,很容易总结出前后发生的事情。不幸的是,由于Node异步的天性自然,这是不容易办到的,看下代码里面的例子 -**Otherwise:** Looking at a production error log without the context – what happened before – makes it much harder and slower to reason about the issue +**否则:** 在没有上下文的情况下查看生产错误日志,这会使问题变得更加困难和缓慢去解决。 -🔗 [**Read More: Assign ‘TransactionId’ to each log statement**](/sections/production/assigntransactionid.md) +🔗 [**更多: 在每一个log语句中指明 ‘TransactionId’**](/sections/production/assigntransactionid.md)

@@ -641,11 +641,11 @@ null == undefined // true

-## ![✔] 5.16. Design automated, atomic and zero-downtime deployments +## ![✔] 5.16. 设计自动化、原子化和零停机时间部署 -**TL;DR:** Researches show that teams who perform many deployments – lowers the probability of severe production issues. Fast and automated deployments that don’t require risky manual steps and service downtime significantly improves the deployment process. You should probably achieve that using Docker combined with CI tools as they became the industry standard for streamlined deployment +**TL;DR:** 研究表明,执行许多部署的团队降低了严重上线问题的可能性。不需要危险的手动步骤和服务停机时间的快速和自动化部署大大改善了部署过程。你应该达到使用Docker结合CI工具,使他们成为简化部署的行业标准。 -**Otherwise:** Long deployments -> production down time & human-related error -> team unconfident and in making deployment -> less deployments and features +**否则:** 长时间部署 -> 线上宕机 & 和人相关的错误 -> 团队部署时不自信 -> 更少的部署和需求


From 9cbed0573200115597000e2f9986c88efb09e450 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sun, 10 Dec 2017 22:15:34 +0800 Subject: [PATCH 26/75] [Chinese-translation]README.chinese.md - add 4.1,4.2,4.3 --- README.chinese.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index c48e92d20..8dc7a4b9e 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -393,36 +393,36 @@ null == undefined // true ## ![✔] 4.1 至少,编写API(组件)测试 -**TL;DR:** Most projects just don't have any automated testing due to short time tables or often the 'testing project' run out of control and being abandoned. For that reason, prioritize and start with API testing which are the easiest to write and provide more coverage than unit testing (you may even craft API tests without code using tools like [Postman](https://www.getpostman.com/). Afterwards, should you have more resources and time, continue with advanced test types like unit testing, DB testing, performance testing, etc +**TL;DR:** 大多数项目只是因为时间表太短而没有进行任何自动化测试,或者测试项目失控而正被遗弃。因此,优先从API测试开始,这是最简单的编写和提供比单元测试更多覆盖率的事情(你甚至可能不需要编码而进行API测试,像[Postman](https://www.getpostman.com/)。之后,如果您有更多的资源和时间,继续使用高级测试类型,如单元测试、DB测试、性能测试等。 -**Otherwise:** You may spend long days on writing unit tests to find out that you got only 20% system coverage +**否则:** 您可能需要花很长时间编写单元测试,才发现只有20%的系统覆盖率。

-## ![✔] 4.2 Detect code issues with ESLint + specific Node plugin rules +## ![✔] 4.2 检测代码问题使用ESLint + 特定node插件的规则 -**TL;DR:** ESLint is the de-facto standard for checking code style, not only to identify nitty-gritty spacing issues but also to detect serious code anti-patterns like developers throwing errors without classification. On top of ESLint standard rules that cover vanilla JS only, add Node-specific plugins like [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) +**TL;DR:** ESLint是检查代码风格的事实上的标准,不仅要查明实际的间距问题,也要检测严重的反模式问题,像开发者没有分类的抛出异常。除了仅仅涉及 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) 和 [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security) -**Otherwise:** Many faulty Node.JS code patterns might escape under the radar. For example, developers might require(variableAsPath) files with a variable given as path which allows attackers to execute any JS script. Node.JS linters can detect such patterns and complain early +**否则:** 许多错误的Node.js代码模式可能在检测下逃生。例如,开发人员可能需要某些文件,把一个变量作为路径名 (variableAsPath) ,这会导致攻击者可以执行任何JS脚本。Node.JS linters可以检测这类模式,并及早预警。

-## ![✔] 4.3 Carefully choose your CI platform (Jenkins vs CircleCI vs Travis vs Rest of the world) +## ![✔] 4.3 仔细挑选您的持续集成(CI)平台 -**TL;DR:** Your continuous integration platform (CICD) will host all the quality tools (e.g test, lint) so it should come with a vibrant ecosystem of plugins. [Jenkins](https://jenkins.io/) used to be the default for many projects as it has the biggest community along with a very powerful platform at the price of complex setup that demands a steep learning curve. Nowdays, it became much easier to setup a CI solution using SaaS tools like [CircleCI](https://circleci.com) and others. These tools allow crafting a flexible CI pipeline without the burden of managing the whole infrastructure. Eventually, it's a trade-off between robustness and speed - choose your side carefully. +**TL;DR:** 您的持续集成平台(cicd)将集成各种质量工具(如测试、lint),所以它应该是一个充满活力的生态系统,包含各种插件。[jenkins](https://jenkins.io/)曾经是许多项目的默认选项,因为它有最大的社区,同时也是一个非常强大的平台,这样的代价是要求一个陡峭的学习曲线。如今,使用SaaS工具,比如[CircleCI](https://circleci.com)及其他,安装一套CI解决方案,相对是一件容易的事情。这些工具允许构建灵活的CI管道,而无需管理整个基础设施。最终,这是一个鲁棒性和速度之间的权衡 - 仔细选择您支持的方案。 -**Otherwise:** Choosing some niche vendor might get you blocked once you need some advanced customization. On the other hand, going with Jenkins might burn precious time on infrastructure setup +**否则:** 一旦您需要一些高级定制,选择一些细分市场供应商可能会让您停滞不前。另一方面,伴随着jenkins,可能会在基础设施设置上浪费宝贵的时间。 -🔗 [**Read More: Choosing CI platform**](/sections/testingandquality/citools.md) +🔗 [**更多: 挑选 CI 平台**](/sections/testingandquality/citools.md)

-## ![✔] 4.4 Constantly inspect for vulnerable dependencies +## ![✔] 4.4 经常检查易受攻击的依赖 -**TL;DR:** Even the most reputable dependencies such as Express have known vulnerabilities. This can get easily tamed using community and commercial tools such as 🔗 [nsp](https://github.com/nodesecurity/nsp) that can be invoked from your CI on every build +**TL;DR:** 即使是那些最有名的依赖模块,比如Express,也有已知的漏洞。使用社区和商业工具,比如 🔗 [nsp](https://github.com/nodesecurity/nsp) ,集成在您的CI平台上,在每一次构建的时候都会被调用,这样可以很容易地解决漏洞问题。 -**Otherwise:** Keeping your code clean from vulnerabilities without dedicated tools will require to constantly follow online publications about new threats. Quite tedious +**否则:** 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物。相当繁琐。

From c262d6fdc55a0e173cadc828a7de1a5124788d7c Mon Sep 17 00:00:00 2001 From: songxianjin Date: Mon, 11 Dec 2017 18:30:05 +0800 Subject: [PATCH 27/75] void --- sections/production/productoncode.chinese.md | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 sections/production/productoncode.chinese.md diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md deleted file mode 100644 index fdd0a6229..000000000 --- a/sections/production/productoncode.chinese.md +++ /dev/null @@ -1,18 +0,0 @@ - -生产环境代码准备 - -

- - -解释 -以下是影响生产维护和稳定性的开发技巧: - - -* 十二因素指南 – 熟悉十二因素 [Twelve factors](https://12factor.net/) -* 无状态-不在特定web服务器上保存本地数据(请参阅独立项目 - “Be Stateless”) -* 大量使用缓存,但不会因缓存不匹配而失败 -* 测试内存-测量内存使用情况和内存泄漏是开发流程的一部分,比如‘memwatch’这类工具可以极大地简化测量内存使用情况和内存泄漏。 -* 命名函数-最小化匿名函数(即内联回调)的用法作为典型内存测评器慧提供每隔方法名的内存占用。 -* 使用CI工具-使用CI工具在发送生产之前检测故障。例如,使用ESLint检测引用错误和未定义的变量。使用-trace-sync-io标识使用同步API的代码(而不是异步版本)。 -* 日志记录-在每个日志语句中希望以JSON格式记录上下文信息,以便像Elastic这样的日志聚合工具能够搜索这些属性(请参阅独立项目 - “使用智能日志提高可见性”)。此外,还包括标识每个请求的transaction-id 并允许关联描述相同事务的行(请参阅独立项目 - “Include Transaction-ID”) -* 错误管理 - 错误处理是Node.JS生产站点的薄弱环节-许多Node进程由于小错误而崩溃,而另一些进程虽然没有奔溃却一直处于错误状态。设置错误处理策略非常重要,请阅读我的【错误处理最佳实践】(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file From 9a7cb11e18319090bc9e483d2d767e706fbff9f8 Mon Sep 17 00:00:00 2001 From: lilanlan Date: Mon, 11 Dec 2017 19:23:57 +0800 Subject: [PATCH 28/75] translation -lll --- sections/projectstructre/wraputilitie.chinese.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 sections/projectstructre/wraputilitie.chinese.md diff --git a/sections/projectstructre/wraputilitie.chinese.md b/sections/projectstructre/wraputilitie.chinese.md new file mode 100644 index 000000000..b0fbd030a --- /dev/null +++ b/sections/projectstructre/wraputilitie.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 "构建解决方案的组件") From 6d3d646b49d379e828a61d802a8367b4cf3c9908 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Mon, 11 Dec 2017 23:12:22 +0800 Subject: [PATCH 29/75] [Chinese-translation] README.chinese.md - add 4.x --- README.chinese.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 8dc7a4b9e..d574dbfe5 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -426,19 +426,19 @@ null == undefined // true

-## ![✔] 4.5 Tag your tests +## ![✔] 4.5 测试标签化 -**TL;DR:** Different tests must run on different scenarios: quick smoke, IO-less, tests should run when a developer saves or commits a file, full end-to-end tests usually run when a new pull request is submitted, etc. This can be achieved by tagging tests with keywords like #cold #api #sanity so you can grep with your testing harness and invoke the desired subset. For example, this is how you would invoke only the sanity test group with [Mocha](https://mochajs.org/): mocha --grep 'sanity' +**TL;DR:** 不同的测试必须运行在不同的情景:quick smoke,IO-less,当开发者保存或提交一个文件,测试应该启动;完整的端到端的测试通常运行在一个新的pull request被提交之后,等等。这可以通过对测试用例设置标签,比如关键字像#cold #api #sanity,来完成。这样您可以对您的测试集进行grep,调用需要的子集。例如,这就是您通过[Mocha](https://mochajs.org/)仅仅调用sanity测试集所需要做的:mocha --grep 'sanity'。 -**Otherwise:** Running all the tests, including tests that perform dozens of DB queries, any time a developer makes a small change can be extremly slow and keeps developers away from running tests +**否则:** 运行所有的测试,包括执行数据库查询的几十个测试,任何时候开发者进行小的改动都可能很慢,这使得开发者不愿意运行测试。

-## ![✔] 4.6 Check your test coverage, it helps to identify wrong test patterns +## ![✔] 4.6 检查测试覆盖率,它有助于识别错误的测试模式 -**TL;DR:** Code coverage tools like [Istanbul/NYC ](https://github.com/gotwarlost/istanbul)are great for 3 reasons: it comes for free (no effort is required to benefit this reports), it helps to identify a decrease in testing coverage, and last but not least it highlights testing mismatches: by looking at colored code coverage reports you may notice, for example, code areas that are never tested like catch clauses (meaning that tests only invoke the happy paths and not how the app behaves on errors). Set it to fail builds if the coverage falls under a certain threshold +**TL;DR:** 代码覆盖工具比如[Istanbul/NYC ](https://github.com/gotwarlost/istanbul),很好用有3个原因:它是免费的(获得这份报告不需要任何开销),它有助于确定测试覆盖率降低的部分,以及最后但非最不重要的是它指出了测试中的不匹配:通过查看颜色标记的代码覆盖报告您可以注意到,例如,从来不会被测到的代码片段像catch语句(即测试只是调用正确的路径,而不调用应用程序发生错误时的行为)。如果覆盖率低于某个阈值,则将其设置为失败的构建。 -**Otherwise:** There won't be any automated metric telling you when a large portion of your code is not covered by testing +**否则:** 当你的大部分代码没有被测试覆盖时,就不会有任何自动化的度量指标告诉你了。 @@ -452,12 +452,12 @@ null == undefined // true

-## ![✔] 4.8 Use docker-compose for e2e testing +## ![✔] 4.8 对于 e2e testing,使用 docker-compose -**TL;DR:** End to end (e2e) testing which includes live data used to be the weakest link of the CI process as it depends on multiple heavy services like DB. Docker-compose turns this problem into a breeze by crafting production-like environment using a simple text file and easy commands. It allows crafting all the dependent services, DB and isolated network for e2e testing. Last but not least, it can keep a stateless environment that is invoked before each test suite and dies right after +**TL;DR:** 端对端(e2e)测试包含现场数据,由于它依赖于很多重型服务如数据库,习惯被认为是CI过程中最薄弱的环节。Docker-compose通过制定类似生产的环境,并使用一个简单的文本文件和简单的命令,轻松化解了这个问题。它为了e2e测试,允许制作所有相关服务,数据库和隔离网络。最后但并非最不重要的一点是,它可以保持一个无状态环境,该环境在每个测试套件之前被调用,然后立即消失。 -**Otherwise:** Without docker-compose teams must maintain a testing DB for each testing environment including developers machines, keep all those DBs in sync so test results won't vary across environments +**否则:** 没有docker-compose,团队必须维护一个测试数据库在每一个测试环境上,包含开发机器,保持所有数据同步,这样测试结果不会因环境不同而不同。


From 955e57f1b2bc26ca20329935ccbfe6c87f00feaf Mon Sep 17 00:00:00 2001 From: leijingyun Date: Tue, 12 Dec 2017 09:45:38 +0800 Subject: [PATCH 30/75] [chinese_translaton] add /production/setnodeenv.chinese.md --- sections/production/setnodeenv.chinese.md | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 sections/production/setnodeenv.chinese.md diff --git a/sections/production/setnodeenv.chinese.md b/sections/production/setnodeenv.chinese.md new file mode 100644 index 000000000..dbfda4985 --- /dev/null +++ b/sections/production/setnodeenv.chinese.md @@ -0,0 +1,30 @@ +配置环境变量 NODE_ENV = production + + +段落解释: + +进程的环境变量是一组键值对,可用于任何运行程序,通常用于配置。虽然可以使用其他任何变量,但Node鼓励使用一个名为NODE_ENV的变量来标记我们是否正在开发。这一决定允许组件在开发过程中能提供更好的诊断,例如禁用缓存或发出冗长的日志语句。任何现代部署工具 — Chef、Puppet、CloudFormation等 — 在部署时都支持设置环境变量 + + +代码实例:配置和读取NODE_ENV环境变量 +javascript +//Using a command line, initializing node process and setting before environment variables +Set NODE_ENV=development&& set otherVariable=someValue&& node +使用命令行,在环境变量设置之前初始化节点进程和设置 +设置NODE_ENV =development&& 设置otherVariable =someValue&& 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来生成请求node.js的数量可以处理大约三分之二的跳转,尽管CPU的使用率会略有下降。 +*让我强调一下:设置NODE_ENV去开发可以让你的应用程序快3倍* + + +![Set NODE_ENV = production](/assets/images/setnodeenv1.png "Set NODE_ENV = production") + From f13be67bb548f8487215b7a74b476d0a4a098720 Mon Sep 17 00:00:00 2001 From: leijingyun Date: Thu, 14 Dec 2017 13:26:59 +0800 Subject: [PATCH 31/75] [chinese_translation] add sections\production\utilizecpu.chinese.md --- sections/production/utilizecpu.chinese.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 sections/production/utilizecpu.chinese.md diff --git a/sections/production/utilizecpu.chinese.md b/sections/production/utilizecpu.chinese.md new file mode 100644 index 000000000..6c879b31a --- /dev/null +++ b/sections/production/utilizecpu.chinese.md @@ -0,0 +1,17 @@ +#利用所有的CPU内核 + +### 段落解释: + nodejs的基本形式可能不会让人感到意外,是一个运行于单进程单线程单个CPU的服务器引擎。负担一个强大的硬件需要用4个或8个CPU,只使用一个听起来是不可思议的,对吗?适合中型应用程序最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和流程之间的路由请求产生一个循环样式的过程。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给集群模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用程序。对于那些高级的用例,考虑使用自定义部署脚本复制节点流程,并使用像nginx这样的特殊工具进行 + 平衡,或者使用像AWS、ECS或kubernet这样的容器引擎,这些工具具有放置和复制进程的高级特性。 + +### 比较:平衡使用Node的clustre和nginx + +### 其他博客作者说什么: +* 来自[Node.JS documentation](https://nodejs.org/api/cluster.html#cluster_how_it_works): + 理论上第二种方法应该是效率最佳的,但在实际情况下,由于操作系统调度机制的难以捉摸,会使分发变得不稳定。我们遇到过这种情况:8个进程中的2个,分担了70%的负载。 + +* 来自博客[StrongLoop](From the blog StrongLoop): + ...通过Node的集群模块实现集群化。这使一个主进程能够产生工作进程,并在工作人员之间分配传入的连接。然而,与其直接使用这个模块,不如使用其中的一个工具自动完成它;例如,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的领域内进行操作。请记住,你的主进程将会工作几乎和你的工作进程一样多,并且有较少的请求率,然后其他的解决方案... \ No newline at end of file From 8e2a92b2a4f8d4630fb9e2e95a92f9d5415920c2 Mon Sep 17 00:00:00 2001 From: leijingyun Date: Thu, 14 Dec 2017 17:07:59 +0800 Subject: [PATCH 32/75] repair --- sections/production/productoncode.chinese.md | 15 ++++++---- sections/production/setnodeenv.chinese.md | 31 ++++++++++++-------- sections/production/utilizecpu.chinese.md | 29 ++++++++++++------ 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md index 1a0341aa7..2ec9634ad 100644 --- a/sections/production/productoncode.chinese.md +++ b/sections/production/productoncode.chinese.md @@ -1,15 +1,18 @@ -代码生产环境的准备 +# 代码生产环境的准备 +

-以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性: +### 段落解释 +以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性: -* 十二因素指南 — 熟悉[12因素](https://12factor.net/) +* 十二因素指南 — 熟悉[12因素](https://12factor.net/)指南 * 无状态 — 在一个特定的web服务器上不保存本地数据(请参阅独立项目-“Be Stateless”) * 高速缓存 — 大量使用缓存,但不会因为缓存不匹配而失败 * 测试内存 — 测量内存的使用和泄漏,是作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务 * 命名函数 — 将匿名函数(即内联callbabk)的使用最小化,作为一个典型的内存分析器为每个方法名提供内存使用 -* 使用CI工具 — 在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用- trace-sync-io来识别用了同步的api代码(而不是异步版本) -* 明确的日志 — 包括在每个日志语句中希望用json格式记录上下文信息,以便于日志聚合工具,如Elastic可以在这些属性上搜索(请参阅独立项目 — 使 使用智能日志增加可见性)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅“Include Transaction-ID”) -* 错误管理 — 错误处理是Node.js生产站点的致命弱点——许多节点进程由于小错误而崩溃,然而其他节点则会在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的,在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file +* 使用CI工具 — 在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用- trace-sync-io来识别用了同步的api代 +码(而不是异步版本) +* 明确的日志 — 包括在每个日志语句中希望用json格式记录上下文信息,以便于日志聚合工具,如Elastic可以在这些属性上搜索(请参阅独立项目 — 使 使用智能日志增加可见性)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅 — “Include Transaction-ID”) +* 错误管理 — 错误处理是Node.js生产站点的致命弱点——许多节点进程由于小错误而崩溃,然而其他节点则会在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的,在这里阅读我的(错误处理的最佳实践)(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 index dbfda4985..1be86e700 100644 --- a/sections/production/setnodeenv.chinese.md +++ b/sections/production/setnodeenv.chinese.md @@ -1,30 +1,37 @@ -配置环境变量 NODE_ENV = production +# 配置环境变量 NODE_ENV = production +

-段落解释: -进程的环境变量是一组键值对,可用于任何运行程序,通常用于配置。虽然可以使用其他任何变量,但Node鼓励使用一个名为NODE_ENV的变量来标记我们是否正在开发。这一决定允许组件在开发过程中能提供更好的诊断,例如禁用缓存或发出冗长的日志语句。任何现代部署工具 — Chef、Puppet、CloudFormation等 — 在部署时都支持设置环境变量 +### 段落解释 +进程的环境变量是一组键值对,可用于任何运行程序,通常用于配置。虽然可以使用其他任何变量,但Node鼓励使用一个名为NODE_ENV的变量来标记我们是否正在开发。这一决定允许组件在开发过程中能提供更好的诊断,例如禁用缓存或发出冗长的日志语句。任何现代部署工具 — Chef、Puppet、CloudFormation等 — 在部署时都支持设置环境变量。 -代码实例:配置和读取NODE_ENV环境变量 -javascript -//Using a command line, initializing node process and setting before environment variables +

+ + +### 代码实例:配置和读取NODE_ENV环境变量 + +```javascript +//Using a command line, initializing node process and setting before environment variables Set NODE_ENV=development&& set otherVariable=someValue&& node -使用命令行,在环境变量设置之前初始化节点进程和设置 -设置NODE_ENV =development&& 设置otherVariable =someValue&& 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来生成请求node.js的数量可以处理大约三分之二的跳转,尽管CPU的使用率会略有下降。 -*让我强调一下:设置NODE_ENV去开发可以让你的应用程序快3倍* +### 其他博客作者说什么 +来自这篇博客[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来生成请求node.js的数量可以处理大约三分之二的跳转,尽管CPU的使用率会略有下降。 *让我强调一下:设置NODE_ENV去开发可以让你的应用程序快3倍!* ![Set NODE_ENV = production](/assets/images/setnodeenv1.png "Set NODE_ENV = production") + +

+ diff --git a/sections/production/utilizecpu.chinese.md b/sections/production/utilizecpu.chinese.md index 6c879b31a..793b90d29 100644 --- a/sections/production/utilizecpu.chinese.md +++ b/sections/production/utilizecpu.chinese.md @@ -1,17 +1,28 @@ -#利用所有的CPU内核 +# 利用所有的CPU内核 -### 段落解释: - nodejs的基本形式可能不会让人感到意外,是一个运行于单进程单线程单个CPU的服务器引擎。负担一个强大的硬件需要用4个或8个CPU,只使用一个听起来是不可思议的,对吗?适合中型应用程序最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和流程之间的路由请求产生一个循环样式的过程。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给集群模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用程序。对于那些高级的用例,考虑使用自定义部署脚本复制节点流程,并使用像nginx这样的特殊工具进行 - 平衡,或者使用像AWS、ECS或kubernet这样的容器引擎,这些工具具有放置和复制进程的高级特性。 +

-### 比较:平衡使用Node的clustre和nginx -### 其他博客作者说什么: +### 段落解释 + +nodejs的基本形式可能不会让人感到意外,是一个运行于单进程单线程单个CPU的服务器引擎。负担一个强大的硬件需要用4个或8个CPU,只使用一个听起来是不可思议的,对吗?适合中型应用程序最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和流程之间的路由请求产生一个循环样式的过程。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给集群模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用程序。对于那些高级的用例,考虑使用自定义部署脚本复制节点流程,并使用像nginx +这样的特殊工具进行平衡,或者使用像AWS、ECS或kubernet这样的容器引擎,这些工具具有放置和复制进程的高级特性。 + +

+ + +### 比较:均衡使用Node的clustre和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): - 理论上第二种方法应该是效率最佳的,但在实际情况下,由于操作系统调度机制的难以捉摸,会使分发变得不稳定。我们遇到过这种情况:8个进程中的2个,分担了70%的负载。 +> ... 理论上第二种方法应该是效率最佳的,但在实际情况下,由于操作系统调度机制的难以捉摸,会使分发变得不稳定。我们遇到过这种情况:8个进程中的2个,分担了70%的负载... * 来自博客[StrongLoop](From the blog StrongLoop): - ...通过Node的集群模块实现集群化。这使一个主进程能够产生工作进程,并在工作人员之间分配传入的连接。然而,与其直接使用这个模块,不如使用其中的一个工具自动完成它;例如,node-pm或cluster-service... +> ...通过Node的集群模块实现集群化。这使一个主进程能够产生工作进程,并在工作人员之间分配传入的连接。然而,与其直接使用这个模块,不如使用其中的一个工具自动完成它;例如,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的领域内进行操作。请记住,你的主进程将会工作几乎和你的工作进程一样多,并且有较少的请求率,然后其他的解决方案... \ No newline at end of file +> ... 节点集群的实现和配置很简单,不依赖于其他软件就可以在Node的领域内进行操作。请记住,你的主进程将会工作几乎和你的工作进程一样多,并且有较少的请求率,然后其他的解决方案... \ No newline at end of file From 405d3baa1e8be0481d007b04fd1ae1905afe0d35 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Thu, 14 Dec 2017 23:19:31 +0800 Subject: [PATCH 33/75] [Chinese translation] shuttingtheprocess.chinese.md - init --- .../shuttingtheprocess.chinese.md | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 sections/errorhandling/shuttingtheprocess.chinese.md diff --git a/sections/errorhandling/shuttingtheprocess.chinese.md b/sections/errorhandling/shuttingtheprocess.chinese.md new file mode 100644 index 000000000..ae9a185ae --- /dev/null +++ b/sections/errorhandling/shuttingtheprocess.chinese.md @@ -0,0 +1,54 @@ +# 特殊情况产生时,优雅地停掉服务 + + +### 一段解释 + +在您的代码的某个地方,当一个错误抛出的时候,错误处理对象负责决定如何进行时 – 如果错误是可信的(即操作型错误,在最佳实践# 3了解进一步的解释),写入日志文件可能是足够的。如果错误不熟悉,事情就变得棘手了 – 这意味着某些组件可能处于故障状态,所有将来的请求都可能失败。例如,假设一个单例(singleton)的、有状态的令牌发行者服务抛出异常并失去它的状态 — 从现在起,它可能会出现意外行为并导致所有请求失败。在这种情况下,杀进程,使用“重启”的工具(像Forever,PM2,等等)重新开始。 + + + +### 代码实例: 决定是否退出 + +```javascript +//deciding whether to crash when an uncaught exception arrives +//Assuming developers mark known operational errors with error.isOperational=true, read best practice #3 +process.on('uncaughtException', function(error) { + errorManagement.handler.handleError(error); + if(!errorManagement.handler.isTrustedError(error)) + process.exit(1) +}); + + +//centralized error handler encapsulates error-handling related logic +function errorHandler(){ + this.handleError = function (error) { + return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError); + } + + this.isTrustedError = function(error) + { + return error.isOperational; + } + +``` + + +### Blog Quote: "The best way is to crash" + From the blog Joyent + + > …从程序型错误中恢复过来的最好方法是立即崩溃。你应该使用一个重启助手来运行您的程序,它会在崩溃的情况下自动启动程序。当使用重启助手,崩溃是面对临时性的程序型错误时,恢复可靠的服务的最快的方法… + + +### Blog Quote: "错误处理有三种流派" + From the blog: JS Recipes + + > …错误处理主要有三种流派: +1. 让应用崩溃,并重启。 +2. 处理所有的错误,从不崩溃。 +3. 介于两者之间。 + + +### Blog Quote: "No safe way to leave without creating some undefined brittle state" +From Node.JS official documentation + + > …By the very nature of how throw works in JavaScript, there is almost never any way to safely “pick up where you left off”, without leaking references, or creating some other sort of undefined brittle state. The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else. The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker. \ No newline at end of file From 4609781fe91e9e4cba0572c13167966f02d62c37 Mon Sep 17 00:00:00 2001 From: jin jing Date: Fri, 15 Dec 2017 15:44:01 +0800 Subject: [PATCH 34/75] [Chinese-translation]shuttingtheprocess.chinese.md - finished. --- .../shuttingtheprocess.chinese.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sections/errorhandling/shuttingtheprocess.chinese.md b/sections/errorhandling/shuttingtheprocess.chinese.md index ae9a185ae..45e17af0b 100644 --- a/sections/errorhandling/shuttingtheprocess.chinese.md +++ b/sections/errorhandling/shuttingtheprocess.chinese.md @@ -10,8 +10,8 @@ ### 代码实例: 决定是否退出 ```javascript -//deciding whether to crash when an uncaught exception arrives -//Assuming developers mark known operational errors with error.isOperational=true, read best practice #3 +//收到未捕获的异常时,决定是否要崩溃 +//如果开发人员标记已知的操作型错误使用:error.isOperational=true, 查看最佳实践 #3 process.on('uncaughtException', function(error) { errorManagement.handler.handleError(error); if(!errorManagement.handler.isTrustedError(error)) @@ -19,7 +19,7 @@ process.on('uncaughtException', function(error) { }); -//centralized error handler encapsulates error-handling related logic +//封装错误处理相关逻辑在集中的错误处理中 function errorHandler(){ this.handleError = function (error) { return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError); @@ -33,14 +33,14 @@ function errorHandler(){ ``` -### Blog Quote: "The best way is to crash" - From the blog Joyent +### 博客引用: "最好的方式是立即崩溃" +摘自 博客:Joyent > …从程序型错误中恢复过来的最好方法是立即崩溃。你应该使用一个重启助手来运行您的程序,它会在崩溃的情况下自动启动程序。当使用重启助手,崩溃是面对临时性的程序型错误时,恢复可靠的服务的最快的方法… -### Blog Quote: "错误处理有三种流派" - From the blog: JS Recipes +### 博客引用: "错误处理有三种流派" +摘自 博客:JS Recipes > …错误处理主要有三种流派: 1. 让应用崩溃,并重启。 @@ -48,7 +48,7 @@ function errorHandler(){ 3. 介于两者之间。 -### Blog Quote: "No safe way to leave without creating some undefined brittle state" -From Node.JS official documentation +### 博客引用: "不伴随着创建一些易碎的状态,是没有保险的方式退出" +摘自 Node.JS 官方文档 - > …By the very nature of how throw works in JavaScript, there is almost never any way to safely “pick up where you left off”, without leaking references, or creating some other sort of undefined brittle state. The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else. The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker. \ No newline at end of file + > …就throw工作在JavaScript的本质而言,几乎没有任何方法可以安全地“在您丢下的地方捡起”,而不会泄漏引用,或者创建其他类型的未定义的易碎性状态。对抛出的错误作出响应的最安全的方法是关闭进程。当然,在一个普通的Web服务器中,可能有很多连接打开了,因为其他人触发了一个错误,所以突然关闭这些连接是不合理的。更好的方法是将错误响应发送给触发错误的请求,同时让其他人在正常时间内完成,并停止侦听该工作者的新请求。 \ No newline at end of file From a9a424b12cab34353e16bf00a8dcf32291ce19cc Mon Sep 17 00:00:00 2001 From: jin jing Date: Fri, 15 Dec 2017 17:23:01 +0800 Subject: [PATCH 35/75] [Chinese-translation] bestateless.chinese.md - add. --- sections/production/bestateless.chinese.md | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 sections/production/bestateless.chinese.md diff --git a/sections/production/bestateless.chinese.md b/sections/production/bestateless.chinese.md new file mode 100644 index 000000000..8f0a484de --- /dev/null +++ b/sections/production/bestateless.chinese.md @@ -0,0 +1,39 @@ +# 保存无状态,几乎每天都要停掉服务器 + +

+ + +### 一段解释 + +你曾经有没有遇到一类严重的线上问题,比如一个服务器丢失了一些配置或数据?这可能是由于对于不属于部署部分的本地资源的一些不必要的依赖。许多成功的产品对待服务器就像凤凰鸟–它周期性地死亡和重生不带来任何损伤。换句话说,服务器只是一个硬件,执行你的代码一段时间后,可以更换。 +这个方法: +1. 允许动态添加和删除服务器,无任何负面影响; +2. 简化了维护,因为它使我们不必费精力对每个服务器状态进行评估。 + +

+ + +### 代码示例: 反模式 + +```javascript +//典型错误1: 保存上传文件在本地服务器上 +var multer = require('multer') //express middleware for fetching uploads +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): +> ...某天,我有了启动一个对操作的认证服务的幻想。认证评估将由我和一位同事出现在企业数据中心,并通过一个棒球棒,一个电锯和一把水枪设置关键生产服务器。评估将基于操作团队需要多长时间才能重新运行所有应用程序。这可能是一个愚蠢的幻想,但有一个真正的智慧在这里。而你应该放弃棒球棒,去定期的几乎烧毁你的服务器,这是一个好的做法。服务器应该像凤凰,经常从灰烬中升起... + +

From e78d246fb6edcbc9885f7bafc024f7de6fc2b2dd Mon Sep 17 00:00:00 2001 From: matt_jin Date: Fri, 15 Dec 2017 22:57:32 +0800 Subject: [PATCH 36/75] [Chinese-translation] centralizedhandling.chinese.md - init. --- .../centralizedhandling.chinese.md | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 sections/errorhandling/centralizedhandling.chinese.md diff --git a/sections/errorhandling/centralizedhandling.chinese.md b/sections/errorhandling/centralizedhandling.chinese.md new file mode 100644 index 000000000..6ebdee842 --- /dev/null +++ b/sections/errorhandling/centralizedhandling.chinese.md @@ -0,0 +1,83 @@ +# 集中处理错误,通过但不是在中间件里处理错误Ha + + +### 一段解释 + +如果没有一个专用的错误处理对象,那么由于操作不当,隐藏在雷达下的重要错误的可能性更大。错误处理对象负责使错误可见,例如通过写入一个格式话良好的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); +}); + +``` + +### 博客引用: "Sometimes lower levels can’t do anything useful except propagate the error to their caller" + From the blog Joyent, ranked 1 for the keywords “Node.JS error handling” + + > …You may end up handling the same error at several levels of the stack. This happens when lower levels can’t do anything useful except propagate the error to their caller, which propagates the error to its caller, and so on. Often, only the top-level caller knows what the appropriate response is, whether that’s to retry the operation, report an error to the user, or something else. But that doesn’t mean you should try to report all errors to a single top-level callback, because that callback itself can’t know in what context the error occurred… + + +### Blog Quote: "Handling each err individually would result in tremendous duplication" + From the blog JS Recipes, ranked 17 for the keywords “Node.JS error handling” + + > ……In Hackathon Starter api.js controller alone, there are over 79 occurences of error objects. Handling each err individually would result in tremendous amount of code duplication. The next best thing you can do is to delegate all error handling logic to an Express middleware… + + +### Blog Quote: "HTTP errors have no place in your database code" + From the blog Daily JS, ranked 14 for the keywords “Node.JS error handling” + + > ……You should set useful properties in error objects, but use such properties consistently. And, don’t cross the streams: HTTP errors have no place in your database code. Or for browser developers, Ajax errors have a place in code that talks to the server, but not code that processes Mustache templates… + From bf59401936652b1faaa723594d59f955a0bde17f Mon Sep 17 00:00:00 2001 From: jin jing Date: Sat, 16 Dec 2017 17:07:31 +0800 Subject: [PATCH 37/75] [Chinese-translation]assigntransactionid.chinese.md - init. --- .../production/assigntransactionid.chinese.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 sections/production/assigntransactionid.chinese.md diff --git a/sections/production/assigntransactionid.chinese.md b/sections/production/assigntransactionid.chinese.md new file mode 100644 index 000000000..7469931e7 --- /dev/null +++ b/sections/production/assigntransactionid.chinese.md @@ -0,0 +1,43 @@ +# 在每一个log语句指定‘TransactionId’ + +

+ + +### 一段解释 + +一个典型的日志是来自所有组件和请求的条目的仓库。当检测到一些可疑行或错误时,为了与其他属于同一特定流程的行(如用户“约翰”试图购买某物)相匹配,就会变得难以应付。特别在微服务环境下,当一个请求/交易可能跨越多个计算机,这变得更加重要和具有挑战性。解决这个问题,可以通过指定一个唯一的事务标识符给从相同的请求过来的所有条目,这样当检测到一行,可以复制这个id,并搜索包含这个transaction id的每一行。但是,在node中实现这个不是那么直截了当的,这是由于它的单线程被用来服务所有的请求 – 考虑使用一个库,它可以在请求层对数据进行分组 – 在下一张幻灯片查看示例代码。当调用其它微服务,使用HTTP头“x-transaction-id”传递transaction id去保持相同的上下文。 + +

+ + +### 代码示例: 典型的nginx配置 + +```javascript +//当接收到一个新的要求,开始一个新的隔离的上下文和设置一个事务transaction id。下面的例子是使用NPM库continuation-local-storage去隔离请求 + +var createNamespace = require('continuation-local-storage').createNamespace; +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'); +} +//Now any other service or components can have access to the contextual, per-request, data +class someService { + getById(id) { + logger.info(“Starting now to get something by Id”); + //other logic comes here + } +} +//Logger can now append transaction-id to each entry, so that entries from the same request will have the same value +class logger{ + info (message) + {console.log(`${message} ${session.get('transactionId')}`);} +} +``` + +

+ +### What Other Bloggers Say +摘自博客 [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*... From 7954c21c27c5221c21ee8605a094d721c8a442a1 Mon Sep 17 00:00:00 2001 From: jin jing Date: Sat, 16 Dec 2017 18:31:56 +0800 Subject: [PATCH 38/75] [Chinese-translation] createmaintenanceendpoint.chinese.md & delegatetoproxy.chinese.md - init. --- .../createmaintenanceendpoint.chinese.md | 37 ++++++++++++++ .../production/delegatetoproxy.chinese.md | 50 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 sections/production/createmaintenanceendpoint.chinese.md create mode 100644 sections/production/delegatetoproxy.chinese.md diff --git a/sections/production/createmaintenanceendpoint.chinese.md b/sections/production/createmaintenanceendpoint.chinese.md new file mode 100644 index 000000000..b3568ab4e --- /dev/null +++ b/sections/production/createmaintenanceendpoint.chinese.md @@ -0,0 +1,37 @@ +# 创建维护端点Create a maintenance endpoint + +

+ + +### 一段解释 + +维护端点是一个简单的安全的HTTP API, 它是应用程序代码的一部分, 它的用途是让ops/生产团队用来监视和公开维护功能。例如, 它可以返回进程的head dump (内存快照), 报告是否存在内存泄漏, 甚至允许直接执行 REPL 命令。在常规的 devops 工具 (监视产品、日志等) 无法收集特定类型的信息或您选择不购买/安装此类工具时, 需要使用此端点。黄金法则是使用专业的和外部的工具来监控和维护生产环境, 它们通常都是更加健壮和准确的。这就意味着, 一般的工具可能无法提取特定于node或应用程序的信息 – 例如, 如果您希望在 GC 完成一个周期时生成内存快照 – 很少有 NPM 库会很乐意为您执行这个, 但流行的监控工具很可能会错过这个功能A maintenance endpoint is a plain secured HTTP API that is part of the app code and its purpose is to be used by the ops/production team to monitor and expose maintenance functionality. For example, it can return a head dump (memory snapshot) of the process, report whether there are some memory leaks and even allow to execute REPL commands directly. This endpoint is needed where the conventional devops tools (monitoring products, logs, etc) fails to gather some specific type of information or you choose not to buy/install such tools. The golden rule is using professional and external tools for monitoring and maintaining the production, these are usually more robust and accurate. That said, there are likely to be cases where the generic tools will fail to extract information that is specific to Node or to your app – for example, should you wish to generate a memory snapshot at the moment GC completed a cycle – few NPM libraries will be glad to perform this for you but popular monitoring tools will be likely to miss this functionality + +

+ + +### Code example: generating a head dump via code + +```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); + }); + }); +}); +``` + +

+ +### Recommended Resources + +[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..587eb9221 --- /dev/null +++ b/sections/production/delegatetoproxy.chinese.md @@ -0,0 +1,50 @@ +# Delegate anything possible (e.g. static content, gzip) to a reverse proxy + +

+ + +### One Paragraph Explainer + +It’s very tempting to cargo-cult Express and use its rich middleware offering for networking related tasks like serving static files, gzip encoding, throttling requests, SSL termination, etc. This is a performance kill due to its single threaded model which will keep the CPU busy for long periods (Remember, Node’s execution model is optimized for short tasks or async IO related tasks). A better approach is to use a tool that expertise in networking tasks – the most popular are nginx and HAproxy which are also used by the biggest cloud vendors to lighten the incoming load on node.js processes. + +

+ + +### Code Example – explanation + +```javascript +gzip on; +#defining gzip compression +gzip_comp_level 6; +gzip_vary on; +upstream myApplication { + server 127.0.0.1:3000; + server 127.0.0.1:3001; + keepalive 64; +} + +#defining web server +server { + 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; +} +``` + +

+ +### What Other Bloggers Say + +* From the blog [Mubaloo](http://mubaloo.com/best-practices-deploying-node-js-applications): +> …It’s very easy to fall into this trap – You see a package like Express and think “Awesome! Let’s get started” – you code away and you’ve got an application that does what you want. This is excellent and, to be honest, you’ve won a lot of the battle. However, you will lose the war if you upload your app to a server and have it listen on your HTTP port, because you’ve forgotten a very crucial thing: Node is not a web server. **As soon as any volume of traffic starts to hit your application, you’ll notice that things start to go wrong: connections are dropped, assets stop being served or, at the very worst, your server crashes. What you’re doing is attempting to have Node deal with all of the complicated things that a proven web server does really well. Why reinvent the wheel?** +> **This is just for one request, for one image and bearing in mind this is memory that your application could be using for important stuff like reading a database or handling complicated logic; why would you cripple your application for the sake of convenience?** + + +* From the blog [Argteam](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**… From e989d733ca1981ce5e084c25b4395ba27e1fa0c0 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sat, 16 Dec 2017 23:18:34 +0800 Subject: [PATCH 39/75] [Chinese-translation] createmaintenanceendpoint.chinese.md & delegatetoproxy.chinese.md - finished. --- .../createmaintenanceendpoint.chinese.md | 8 ++++---- .../production/delegatetoproxy.chinese.md | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sections/production/createmaintenanceendpoint.chinese.md b/sections/production/createmaintenanceendpoint.chinese.md index b3568ab4e..9b9f450ca 100644 --- a/sections/production/createmaintenanceendpoint.chinese.md +++ b/sections/production/createmaintenanceendpoint.chinese.md @@ -1,16 +1,16 @@ -# 创建维护端点Create a maintenance endpoint +# 创建维护端点

### 一段解释 -维护端点是一个简单的安全的HTTP API, 它是应用程序代码的一部分, 它的用途是让ops/生产团队用来监视和公开维护功能。例如, 它可以返回进程的head dump (内存快照), 报告是否存在内存泄漏, 甚至允许直接执行 REPL 命令。在常规的 devops 工具 (监视产品、日志等) 无法收集特定类型的信息或您选择不购买/安装此类工具时, 需要使用此端点。黄金法则是使用专业的和外部的工具来监控和维护生产环境, 它们通常都是更加健壮和准确的。这就意味着, 一般的工具可能无法提取特定于node或应用程序的信息 – 例如, 如果您希望在 GC 完成一个周期时生成内存快照 – 很少有 NPM 库会很乐意为您执行这个, 但流行的监控工具很可能会错过这个功能A maintenance endpoint is a plain secured HTTP API that is part of the app code and its purpose is to be used by the ops/production team to monitor and expose maintenance functionality. For example, it can return a head dump (memory snapshot) of the process, report whether there are some memory leaks and even allow to execute REPL commands directly. This endpoint is needed where the conventional devops tools (monitoring products, logs, etc) fails to gather some specific type of information or you choose not to buy/install such tools. The golden rule is using professional and external tools for monitoring and maintaining the production, these are usually more robust and accurate. That said, there are likely to be cases where the generic tools will fail to extract information that is specific to Node or to your app – for example, should you wish to generate a memory snapshot at the moment GC completed a cycle – few NPM libraries will be glad to perform this for you but popular monitoring tools will be likely to miss this functionality +维护端点是一个简单的安全的HTTP API, 它是应用程序代码的一部分, 它的用途是让ops/生产团队用来监视和公开维护功能。例如, 它可以返回进程的head dump (内存快照), 报告是否存在内存泄漏, 甚至允许直接执行 REPL 命令。在常规的 devops 工具 (监视产品、日志等) 无法收集特定类型的信息或您选择不购买/安装此类工具时, 需要使用此端点。黄金法则是使用专业的和外部的工具来监控和维护生产环境, 它们通常更加健壮和准确的。这就意味着, 一般的工具可能无法提取特定于node或应用程序的信息 – 例如, 如果您希望在 GC 完成一个周期时生成内存快照 – 很少有 NPM 库会很乐意为您执行这个, 但流行的监控工具很可能会错过这个功能。

-### Code example: generating a head dump via code +### 代码示例: 使用代码生产head dump ```javascript var heapdump = require('heapdump'); @@ -28,7 +28,7 @@ router.get('/ops/headump', (req, res, next) => {

-### Recommended Resources +### 推荐资源 [Getting your Node.js app production ready (Slides)](http://naugtur.pl/pres3/node2prod) diff --git a/sections/production/delegatetoproxy.chinese.md b/sections/production/delegatetoproxy.chinese.md index 587eb9221..0b0eb7dd5 100644 --- a/sections/production/delegatetoproxy.chinese.md +++ b/sections/production/delegatetoproxy.chinese.md @@ -1,16 +1,16 @@ -# Delegate anything possible (e.g. static content, gzip) to a reverse proxy +# 委托任何可能的 (例如静态内容, gzip) 到反向代理

-### One Paragraph Explainer +### 一段解释 -It’s very tempting to cargo-cult Express and use its rich middleware offering for networking related tasks like serving static files, gzip encoding, throttling requests, SSL termination, etc. This is a performance kill due to its single threaded model which will keep the CPU busy for long periods (Remember, Node’s execution model is optimized for short tasks or async IO related tasks). A better approach is to use a tool that expertise in networking tasks – the most popular are nginx and HAproxy which are also used by the biggest cloud vendors to lighten the incoming load on node.js processes. +这是非常诱人的去过度使用(cargo-cult)Express和使用其丰富的中间件提供网络相关的任务, 如服务静态文件, gzip 编码, throttling requests, SSL termination等。由于它的单线程模型将使 CPU 长时间处于忙碌状态 (请记住, node的执行模型针对短任务或异步 IO 相关任务进行了优化), 因此这是一个性能消耗。一个更好的方法是使用一个专注于处理网络任务的工具 – 最流行的是 nginx 和 HAproxy, 也被最大的云供应商使用, 以减轻在node.js进程上的面临的负载。

-### Code Example – explanation +### 代码示例 – 说明 ```javascript gzip on; @@ -39,12 +39,12 @@ server {

-### What Other Bloggers Say +### 其他博客作者说什么 -* From the blog [Mubaloo](http://mubaloo.com/best-practices-deploying-node-js-applications): -> …It’s very easy to fall into this trap – You see a package like Express and think “Awesome! Let’s get started” – you code away and you’ve got an application that does what you want. This is excellent and, to be honest, you’ve won a lot of the battle. However, you will lose the war if you upload your app to a server and have it listen on your HTTP port, because you’ve forgotten a very crucial thing: Node is not a web server. **As soon as any volume of traffic starts to hit your application, you’ll notice that things start to go wrong: connections are dropped, assets stop being served or, at the very worst, your server crashes. What you’re doing is attempting to have Node deal with all of the complicated things that a proven web server does really well. Why reinvent the wheel?** -> **This is just for one request, for one image and bearing in mind this is memory that your application could be using for important stuff like reading a database or handling complicated logic; why would you cripple your application for the sake of convenience?** +* 摘自博客 [Mubaloo](http://mubaloo.com/best-practices-deploying-node-js-applications): +> …很容易落入这个陷阱 – 你看到一个包比如Express,并认为 "真棒!让我们开始吧" – 你编写了代码, 你实现了一个应用程序, 做你想要的。这很好, 老实说, 你赢得了很多的战斗。但是, 如果您将应用程序上传到服务器并让它侦听 HTTP 端口, 您将会输掉这场战争, 因为您忘记了一个非常关键的事情: node不是 web 服务器。**一旦任何流量开始访问你的应用程序, 你会发现事情开始出错: 连接被丢弃, 资源停止服务, 或在最坏的情况下, 你的服务器崩溃。你正在做的是试图让node处理所有复杂的事情, 而这些事情让一个已验证过了的 web 服务器来处理,再好也不会过。为什么要重新造轮子?It** +> **这只是为了一个请求, 为了一个图像, 并铭记在脑海中, 您的应用程序可以用于重要的东西, 如读取数据库或处理复杂的逻辑; 为了方便起见, 你为什么要削弱你的应用?** -* From the blog [Argteam](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**… +* 摘自博客 [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进程**… From dc6eb37355b4c5b8dfcc83f25042306a2cc1dd91 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sun, 17 Dec 2017 15:43:35 +0800 Subject: [PATCH 40/75] [Chinese-translation]catchunhandledpromiserejection.chinese.md - add. --- .../catchunhandledpromiserejection.chinese.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 sections/errorhandling/catchunhandledpromiserejection.chinese.md diff --git a/sections/errorhandling/catchunhandledpromiserejection.chinese.md b/sections/errorhandling/catchunhandledpromiserejection.chinese.md new file mode 100644 index 000000000..76ad774f7 --- /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', function (reason, p) { + //我刚刚捕获了一个未处理的promise rejection, 因为我们已经有了对于未处理错误的后备的处理机制(见下面), 直接抛出,让它来处理 + throw reason; +}); +process.on('uncaughtException', function (error) { + //我刚收到一个从未被处理的错误,现在处理它,并决定是否需要重启应用 + errorManagement.handler.handleError(error); + if (!errorManagement.handler.isTrustedError(error)) + process.exit(1); +}); + +``` +

+### 博客引用: "如果你犯了错误,在某个时候你就会犯错误。" +摘自 James Nelson 的博客 + + > 让我们测试一下您的理解。下列哪一项是您期望错误将会打印到控制台的? + +```javascript +Promise.resolve(‘promised value’).then(function() { +throw new Error(‘error’); +}); + +Promise.reject(‘error value’).catch(function() { +throw new Error(‘error’); +}); + +new Promise(function(resolve, reject) { +throw new Error(‘error’); +}); +``` + +> 我不知道您的情况,但我的回答是我希望它们所有都能打印出一个错误。然而,现实是许多现代JavaScript环境不会为其中任何一个打印错误。做为人的问题是,如果你犯了错误,在某个时候你就会犯错误。记住这一点,很显然,我们应该设计这样一种方式,使错误尽可能少创造伤害,这意味着默认地处理错误,而不是丢弃错误。 From 35544dd8ae382620463305ebb7295073d139d2cd Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sun, 17 Dec 2017 17:03:27 +0800 Subject: [PATCH 41/75] [Chinese-translation] asyncerrorhandling.chinese.md, monitoring.chinese.md - add --- .../asyncerrorhandling.chinese.md | 56 +++++++++++++++++++ sections/errorhandling/monitoring.chinese.md | 18 ++++++ 2 files changed, 74 insertions(+) create mode 100644 sections/errorhandling/asyncerrorhandling.chinese.md create mode 100644 sections/errorhandling/monitoring.chinese.md diff --git a/sections/errorhandling/asyncerrorhandling.chinese.md b/sections/errorhandling/asyncerrorhandling.chinese.md new file mode 100644 index 000000000..ee9a533ef --- /dev/null +++ b/sections/errorhandling/asyncerrorhandling.chinese.md @@ -0,0 +1,56 @@ +# 对于异步的错误处理使用Async-Await或者promise + + +### 一段解释 + +回调不能形成一定规模,是由于对于大多数的程序员来说不熟悉,被迫随处检测错误,让人不快的代码内嵌和难以理解的代码流程。通过使用return和throw来控制程序流程,promise的库比如,BlueBird,async,和Q封装了一种标准的代码风格。具体来说,它们支持最受欢迎的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) + //you get the idea?  + }); +}); +``` + +### 博客引用: "We have a problem with promises" +摘自博客pouchdb.com + + > ……And in fact, callbacks do something even more sinister: they deprive us of the stack, which is something we usually take for granted in programming languages. Writing code without a stack is a lot like driving a car without a brake pedal: you don’t realize how badly you need it, until you reach for it and it’s not there. The whole point of promises is to give us back the language fundamentals we lost when we went async: return, throw, and the stack. But you have to know how to use promises correctly in order to take advantage of them. + +### 博客引用: "The promises method is much more compact" +摘自博客gosquared.com + + > ………The promises method is much more compact, clearer and quicker to write. If an error or exception occurs within any of the ops it is handled by the single .catch() handler. Having this single place to handle all errors means you don’t need to write error checking for each stage of the work. + +### 博客引用: "Promises are native ES6, can be used with generators" +摘自博客StrongLoop + + > ….Callbacks have a lousy error-handling story. Promises are better. Marry the built-in error handling in Express with promises and significantly lower the chances of an uncaught exception. Promises are native ES6, can be used with generators, and ES7 proposals like async/await through compilers like Babel + +### Blog Quote: "All those regular flow control constructs you are used to are completely broken" +摘自博客Benno’s + + > ……One of the best things about asynchronous, callback based programming is that basically all those regular flow control constructs you are used to are completely broken. However, the one I find most broken is the handling of exceptions. Javascript provides a fairly familiar try…catch construct for dealing with exceptions. The problems with exceptions is that they provide a great way of short-cutting errors up a call stack, but end up being completely useless of the error happens on a different stack… diff --git a/sections/errorhandling/monitoring.chinese.md b/sections/errorhandling/monitoring.chinese.md new file mode 100644 index 000000000..94948fe79 --- /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%,你的系统能处理更多的流量吗? +… From 46d6e72c9badc236991b09e288eb40b997605491 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sun, 17 Dec 2017 17:11:05 +0800 Subject: [PATCH 42/75] [Chinese-translation] testingerrorflows.chinese.md - add. --- .../testingerrorflows.chinese.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 sections/errorhandling/testingerrorflows.chinese.md diff --git a/sections/errorhandling/testingerrorflows.chinese.md b/sections/errorhandling/testingerrorflows.chinese.md new file mode 100644 index 000000000..acb26a02f --- /dev/null +++ b/sections/errorhandling/testingerrorflows.chinese.md @@ -0,0 +1,37 @@ +# 使用您喜欢的测试框架测试错误流 + + +### 一段解释 + +测试‘正确’路径并不比测试失败更好。良好的测试代码覆盖率要求测试异常路径。否则,异常确实处理正确是不可信的。每个单元测试框架,如Mocha和Chai,都支持异常测试(请看下面的代码示例)。如果您觉得测试每个内部函数和异常都很乏味,那么您可以只测试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 From 382482498c4212dad65f697a758abbfaeb6e3593 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Sun, 17 Dec 2017 23:02:07 +0800 Subject: [PATCH 43/75] [Chinese-translation] failfast.chinese.md & useonlythebuiltinerror.chinese.md - init. --- sections/errorhandling/failfast.chinese.md | 50 ++++++++++++ .../useonlythebuiltinerror.chinese.md | 77 +++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 sections/errorhandling/failfast.chinese.md create mode 100644 sections/errorhandling/useonlythebuiltinerror.chinese.md diff --git a/sections/errorhandling/failfast.chinese.md b/sections/errorhandling/failfast.chinese.md new file mode 100644 index 000000000..80e8c735c --- /dev/null +++ b/sections/errorhandling/failfast.chinese.md @@ -0,0 +1,50 @@ +# 快速察觉失败,使用专用库验证参数 + + +### 一段解释 + +我们都知道如何检查参数和快速失败对于避免隐藏的错误很重要(见下面的反模式代码示例)。如果没有,请阅读显式编程和防御性编程。在现实中,由于对其编码是件恼人的事情(比如考虑验证分层的JSON对象,它包含像email和日期这样的字段),我们倾向于避免做这样的事情 – 像Joi这样的库和验证器轻而易举的处理这个乏味的任务。 + +### Wikipedia: Defensive Programming + +Defensive programming is an approach to improve software and source code, in terms of: General quality – reducing the number of software bugs and problems. Making the source code comprehensible – the source code should be readable and understandable so it is approved in a code audit. Making the software behave in a predictable manner despite unexpected inputs or user actions. + + + +### Code example: validating complex JSON input using ‘Joi’ + +```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 +} + +``` + +### Anti-pattern: no validation yields nasty bugs + +```javascript +//if the discount is positive let's then redirect the user to pring his discount coupons +function redirectToPrintDiscount(httpResponse, member, discount) +{ + if(discount != 0) + httpResponse.redirect(`/discountPrintView/${member.id}`); +} + +redirectToPrintDiscount(httpResponse, someMember); +//forgot to pass the parameter discount, why the heck was the user redirected to the discount screen? + +``` + +### Blog Quote: "You should throw these errors immediately" + From the blog: Joyent + + > A degenerate case is where someone calls an asynchronous function but doesn’t pass a callback. You should throw these errors immediately, since the program is broken and the best chance of debugging it involves getting at least a stack trace and ideally a core file at the point of the error. To do this, we recommend validating the types of all arguments at the start of the function. \ No newline at end of file diff --git a/sections/errorhandling/useonlythebuiltinerror.chinese.md b/sections/errorhandling/useonlythebuiltinerror.chinese.md new file mode 100644 index 000000000..bf304df0e --- /dev/null +++ b/sections/errorhandling/useonlythebuiltinerror.chinese.md @@ -0,0 +1,77 @@ +# 仅使用内建的错误对象 + + +### 一段解释 + +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作为一种语言,似乎不符合基于构造函数的错误捕获。因此,区分对象属性似乎比在构造函数类型上区分要容易得多… + + + +### Code Example – doing it right + +```javascript +//throwing an Error from typical function, whether sync or async + if(!productToAdd) + throw new Error("How can I add new product when no value provided?"); + +//'throwing' an Error from EventEmitter +const myEmitter = new MyEmitter(); +myEmitter.emit('error', new Error('whoops!')); + +//'throwing' an Error from a 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?")); + +``` + +### Code example – Anti Pattern + +```javascript +//throwing a String lacks any stack trace information and other important properties +if(!productToAdd) + throw ("How can I add new product when no value provided?"); + +``` + +### Code example – doing it even better + +```javascript +//centralized error object that derives from Node’s Error +function appError(name, httpCode, description, isOperational) { + Error.call(this); + Error.captureStackTrace(this); + this.name = name; + //...other properties assigned here +}; + +appError.prototype.__proto__ = Error.prototype; + +module.exports.appError = appError; + +//client throwing an exception +if(user == null) + throw new appError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, "further explanation", true) +``` + + +### Blog Quote: "A string is not an error" +From the blog devthought.com, ranked 6 for the keywords “Node.JS error object” + + > …传递字符串而不是错误导致模块间协作性降低。它打破了和API的约定,可能是执行instanceof Error这样的检查,或想了解更多关于错误的信息。正如我们将看到的,错误对象在现代JavaScript引擎中拥有非常有趣的属性,同时保留传递给构造函数的消息… + +Blog Quote: “All JavaScript and System errors raised by Node.js inherit from Error” + +### Blog Quote: "Inheriting from Error doesn’t add too much value" +From the blog machadogj + + > …One problem that I have with the Error class is that is not so simple to extend. Of course you can inherit the class and create your own Error classes like HttpError, DbError, etc. However that takes time, and doesn’t add too much value unless you are doing something with types. Sometimes, you just want to add a message, and keep the inner error, and sometimes you might want to extend the error with parameters, and such… + + ### Blog Quote: "All JavaScript and System errors raised by Node.js inherit from Error" +From Node.JS official documentation + + > …All JavaScript and System errors raised by Node.js inherit from, or are instances of, the standard JavaScript Error class and are guaranteed to provide at least the properties available on that class. A generic JavaScript Error object that does not denote any specific circumstance of why the error occurred. Error objects capture a “stack trace” detailing the point in the code at which the Error was instantiated, and may provide a text description of the error.All errors generated by Node.js, including all System and JavaScript errors, will either be instances of, or inherit from, the Error class… From 88c436eacc2c8682c348eedebad86c9163b77df4 Mon Sep 17 00:00:00 2001 From: songxianjin Date: Mon, 18 Dec 2017 10:06:15 +0800 Subject: [PATCH 44/75] [chinese-translation]sections\production\monitoring.chinese.md --- sections/production/monitoring.chinese.md | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 sections/production/monitoring.chinese.md diff --git a/sections/production/monitoring.chinese.md b/sections/production/monitoring.chinese.md new file mode 100644 index 000000000..71e6d6475 --- /dev/null +++ b/sections/production/monitoring.chinese.md @@ -0,0 +1,35 @@ + +监控 +

+解释 +
+基本来说,监控意味着在生产环境中当发生意外时你能够很容易识别。比如,通过电子邮件或Slack获得通知。 +最大的难题是选择既能满足你的需求又不会破坏储库的比较合适的工具集。我建议,首先定义必须监视的一组核心指标,来保证CPU,服务器RAM,Node进程RAM(小于1.4GB),最后一分钟的错误数量,进程重启次数,平均响应时间在正常状态。然后去看看你可能喜欢的一些高级功能,并添加到你的愿望清单。 + +一些高级监控功能的例子:DB分析,跨服务测量(即测量业务事务),前端集成,将原始数据展示给自定义BI客户端,延缓通知等等。 +要实现高级功能需要冗长的设置或购买诸如Datadog,newrelic之类的商业产品。不幸的是,实现基本功能也并不容易,因为一些测量标准是与硬件相关的(CPU),而其他标准是在node进程内(内部错误)因此所有简单的工具都需要一些额外的设置。例如,云供应商监控解决方案(例如[AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/))能立即告诉您硬件度量标准,但不涉及内部应用程序行为。 + +另一方面,基于日志的解决方案(如ElasticSearch)默认缺少硬件视图。解决方案是通过缺少的指标来增加您的选择,例如,流行的选择是将应用程序日志发送到Elastic堆栈并配置一些额外的代理(例如Beat)来共享硬件相关信息以获得完整的图像。 + +

+###监控示例: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]博客: + +> 我们建议您监听所有服务的这些信号: +> 错误率:因为错误是面向用户的,并且会立即影响您的客户。 +> 响应时间:因为延迟会直接影响您的客户和业务。 +> 吞吐量:流量可帮助您了解增加的错误率和延迟的情况。 +> 饱和度:饱和度告诉你你的服务有多满。如果CPU使用率是90%,您的系统可以处理更多的流量吗? From 041a38c269d426d678542e001002d8b9949aae19 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Mon, 18 Dec 2017 22:10:28 +0800 Subject: [PATCH 45/75] [Chinese-translation]failfast.chinese.md - add. --- sections/errorhandling/failfast.chinese.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sections/errorhandling/failfast.chinese.md b/sections/errorhandling/failfast.chinese.md index 80e8c735c..6cc704d7f 100644 --- a/sections/errorhandling/failfast.chinese.md +++ b/sections/errorhandling/failfast.chinese.md @@ -5,13 +5,13 @@ 我们都知道如何检查参数和快速失败对于避免隐藏的错误很重要(见下面的反模式代码示例)。如果没有,请阅读显式编程和防御性编程。在现实中,由于对其编码是件恼人的事情(比如考虑验证分层的JSON对象,它包含像email和日期这样的字段),我们倾向于避免做这样的事情 – 像Joi这样的库和验证器轻而易举的处理这个乏味的任务。 -### Wikipedia: Defensive Programming +### 维基百科: 防御性编程 -Defensive programming is an approach to improve software and source code, in terms of: General quality – reducing the number of software bugs and problems. Making the source code comprehensible – the source code should be readable and understandable so it is approved in a code audit. Making the software behave in a predictable manner despite unexpected inputs or user actions. +防御性编程是一种改进软件和源代码的方法, 在以下方面: 一般质量 – 减少软件 bug 和问题的数量。使源代码可理解 – 源代码应该是可读的和可理解的, 以便在代码审核中得到批准。尽管会有意外输入或用户操作, 但使软件的行为具有可预知的方式。 -### Code example: validating complex JSON input using ‘Joi’ +### 代码示例: 使用‘Joi’验证复杂的JSON输入 ```javascript var memberSchema = Joi.object().keys({ @@ -29,10 +29,10 @@ function addNewMember(newMember) ``` -### Anti-pattern: no validation yields nasty bugs +### 反模式: 没有验证会产生令人讨厌的错误 ```javascript -//if the discount is positive let's then redirect the user to pring his discount coupons +//假如折扣为正,重定向用户去打印他的折扣优惠劵 function redirectToPrintDiscount(httpResponse, member, discount) { if(discount != 0) @@ -40,11 +40,11 @@ function redirectToPrintDiscount(httpResponse, member, discount) } redirectToPrintDiscount(httpResponse, someMember); -//forgot to pass the parameter discount, why the heck was the user redirected to the discount screen? +//忘记传递参数discount, 为什么用户被重定向到折扣页面? ``` -### Blog Quote: "You should throw these errors immediately" - From the blog: Joyent +### 博客引用: "您应该立即抛出这些错误" + 摘自博客: Joyent - > A degenerate case is where someone calls an asynchronous function but doesn’t pass a callback. You should throw these errors immediately, since the program is broken and the best chance of debugging it involves getting at least a stack trace and ideally a core file at the point of the error. To do this, we recommend validating the types of all arguments at the start of the function. \ No newline at end of file + > 一个退化情况是有人调用一个异步函数但没有传递一个回调方法。你应该立即抛出这些错误, 因为程序有了错误, 最好的调试它的时机包括获得至少stack trace和理想情况下,核心文件里错误的点。为此, 我们建议在函数开始时验证所有参数的类型。 \ No newline at end of file From 03c0d61147a45c7849b4f92b7d65aad946f46dc3 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Mon, 18 Dec 2017 22:39:28 +0800 Subject: [PATCH 46/75] [Chinese-translation]usematurelogger.chinese.md - add. --- .../errorhandling/usematurelogger.chinese.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 sections/errorhandling/usematurelogger.chinese.md diff --git a/sections/errorhandling/usematurelogger.chinese.md b/sections/errorhandling/usematurelogger.chinese.md new file mode 100644 index 000000000..2150d2528 --- /dev/null +++ b/sections/errorhandling/usematurelogger.chinese.md @@ -0,0 +1,51 @@ +# 使用成熟的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写入到一个文件中, 但遇到错误时, 请写入同一文件, 然后写入到错误日志文件,并同时发送电子邮件… From 9b7dc98d76ee4839abb7f497b25287e74a1459b3 Mon Sep 17 00:00:00 2001 From: matt_jin Date: Tue, 19 Dec 2017 22:51:42 +0800 Subject: [PATCH 47/75] [Chinese-translation]apmproducts.chinese.md & operationalvsprogrammererror.chinese.md -- add --- sections/errorhandling/apmproducts.chinese.md | 29 +++++++++++ .../operationalvsprogrammererror.chinese.md | 51 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 sections/errorhandling/apmproducts.chinese.md create mode 100644 sections/errorhandling/operationalvsprogrammererror.chinese.md diff --git a/sections/errorhandling/apmproducts.chinese.md b/sections/errorhandling/apmproducts.chinese.md new file mode 100644 index 000000000..b1227ece8 --- /dev/null +++ b/sections/errorhandling/apmproducts.chinese.md @@ -0,0 +1,29 @@ +# 使用 APM 产品发现错误和宕机时间 + + +### 一段解释 + +异常 != 错误。传统的错误处理假定存在异常, 但应用程序错误可能以代码路径慢、API 停机、缺少计算资源等形式出现。因为APM产品允许使用最小的设置来先前一步地检测各种各样 "深埋" 的问题,这是运用它们方便的地方。APM 产品的常见功能包括: 当 HTTP API 返回错误时报警, 在 api 响应时间低于某个阈值时能检测到, 觉察到 "code smells"、监视服务器资源、操作智能仪表板以及 IT 度量和其他许多有用的功能。大多数供应商提供免费方案。 + +### 关于 APM 的维基百科 + +在信息技术和系统管理领域, 应用程序性能管理 (APM) 是对软件应用程序的性能和可用性的监视和管理。APM 努力检测和诊断复杂的应用程序性能问题, 以维护预期的服务级别。APM 是 "将 IT 度量标准转换为业务含义 ([i.e.] value)" +主要产品和部分 + +### 了解 APM 市场 + +APM 产品由3个主要部分构成: + +1. 网站或API监控 – 通过 HTTP 请求不断监视正常运行时间和性能的外部服务。可以在几分钟内安装。以下是少数选定的竞争者: Pingdom, Uptime Robot, 和 New Relic; + +2. 代码检测 – 产品系列需要在应用程序中嵌入代理, 以实现功能如检测运行缓慢的代码、异常统计、性能监视等。以下是少数选定的竞争者: New Relic, App Dynamics; + +3. 操作智能仪表板 – 这些产品系列侧重于为 ops 团队提供度量和管理内容, 帮助他们轻松地保持应用程序性能的最高水平。这通常涉及聚合多个信息源 (应用程序日志、DB 日志、服务器日志等) 和前期仪表板设计工作。以下是少数选定的竞争者: Datadog, Splunk; + + + + ### Example: UpTimeRobot.Com – 网站监控仪表板 +![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") + + ### Example: 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/operationalvsprogrammererror.chinese.md b/sections/errorhandling/operationalvsprogrammererror.chinese.md new file mode 100644 index 000000000..cbbbabf21 --- /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的地方, 在面对一个瞬态程序型错误, 崩溃是最快的方式来恢复可靠的服务… + + ### 博客引用: "No safe way to leave without creating some undefined brittle state" +摘自Node.JS官方文档 + + > …By the very nature of how throw works in JavaScript, there is almost never any way to safely “pick up where you left off”, without leaking references, or creating some other sort of undefined brittle state. The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else. The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker. + + + ### Blog Quote: "Otherwise you risk the state of your application" +From the blog debugable.com, ranked 3 for the keywords “Node.JS uncaught exception” + + > …So, unless you really know what you are doing, you should perform a graceful restart of your service after receiving an “uncaughtException” exception event. Otherwise you risk the state of your application, or that of 3rd party libraries to become inconsistent, leading to all kinds of crazy bugs… + + ### Blog Quote: "Blog Quote: There are three schools of thoughts on error handling" +From the blog: JS Recipes + + > …There are primarily three schools of thoughts on error handling: +1. Let the application crash and restart it. +2. Handle all possible errors and never crash. +3. Balanced approach between the two From a01580020ebdef2d549c44dbcfbd855cab2a2e40 Mon Sep 17 00:00:00 2001 From: lilanlan Date: Thu, 21 Dec 2017 14:46:41 +0800 Subject: [PATCH 48/75] translation measure memory --- sections/production/measurememory.chinese.md | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 sections/production/measurememory.chinese.md diff --git a/sections/production/measurememory.chinese.md b/sections/production/measurememory.chinese.md new file mode 100644 index 000000000..5da8a84b2 --- /dev/null +++ b/sections/production/measurememory.chinese.md @@ -0,0 +1,24 @@ +# 测量和防范内存使用情况 + +

+ + +### 段落解释 + +在一个完美的开发过程中, Web开发人员不应该处理内存泄漏问题。 实际上,内存问题是一个必须了解的Node已知的问题。 首先,内存使用必须不断监视.在开发和小型生产站点,您可以使用Linux命令或NPM工具和库(如节点检查器和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): +> ... “虽然这个例子导致了明显的结果,但这个过程总是一样的:用一些时间和相当数量的内存分配创建堆转储,比较几个转储,以找出正在增长的东西。” + +* 来自博客 [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 From 46c57ec2ad309cbddc665a48be8ef54e5fd60988 Mon Sep 17 00:00:00 2001 From: jin jing Date: Thu, 21 Dec 2017 19:49:42 +0800 Subject: [PATCH 49/75] [Chinese-translation] asyncerrorhandling.chinese.md & centralizedhandling.chinese.md & operationalvsprogrammererror.chinese.md - add. --- .../asyncerrorhandling.chinese.md | 16 ++++++------ .../centralizedhandling.chinese.md | 18 ++++++------- .../operationalvsprogrammererror.chinese.md | 26 +++++++++---------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/sections/errorhandling/asyncerrorhandling.chinese.md b/sections/errorhandling/asyncerrorhandling.chinese.md index ee9a533ef..96a3415a4 100644 --- a/sections/errorhandling/asyncerrorhandling.chinese.md +++ b/sections/errorhandling/asyncerrorhandling.chinese.md @@ -35,22 +35,22 @@ getData(someParameter, function(err, result){ }); ``` -### 博客引用: "We have a problem with promises" +### 博客引用: "我们使用promise有问题" 摘自博客pouchdb.com - > ……And in fact, callbacks do something even more sinister: they deprive us of the stack, which is something we usually take for granted in programming languages. Writing code without a stack is a lot like driving a car without a brake pedal: you don’t realize how badly you need it, until you reach for it and it’s not there. The whole point of promises is to give us back the language fundamentals we lost when we went async: return, throw, and the stack. But you have to know how to use promises correctly in order to take advantage of them. + > ……实际上, 回调会做一些更险恶的事情: 他们剥夺了我们的stack, 这是我们通常在编程语言中想当然的事情。编写没有堆栈的代码很像驾驶一辆没有刹车踏板的汽车: 你没有意识到你有多么需要它, 直到你伸手去找它, 而它不在那里。promise的全部目的是让我们回到我们在异步时丢失的语言基础: return,throw和stack。但你必须知道如何正确使用promise, 以便利用他们。 -### 博客引用: "The promises method is much more compact" +### 博客引用: "promise方法更加紧凑" 摘自博客gosquared.com - > ………The promises method is much more compact, clearer and quicker to write. If an error or exception occurs within any of the ops it is handled by the single .catch() handler. Having this single place to handle all errors means you don’t need to write error checking for each stage of the work. + > ………promise的方法更紧凑, 更清晰, 写起来更快速。如果在任何 ops 中发生错误或异常, 则由单个 .catch () 处理程序操作处理。有这个单一的地方来处理所有的错误意味着你不需要为每个阶段的工作写错误检查。 -### 博客引用: "Promises are native ES6, can be used with generators" +### 博客引用: "原生ES6支持promise,可以和generator一起使用" 摘自博客StrongLoop - > ….Callbacks have a lousy error-handling story. Promises are better. Marry the built-in error handling in Express with promises and significantly lower the chances of an uncaught exception. Promises are native ES6, can be used with generators, and ES7 proposals like async/await through compilers like Babel + > ….回调有一个糟糕的错误处理的报道。promise更好。将express内置的错误处理与promise结合起来, 大大降低了uncaught exception的几率。原生ES6支持promise, 通过编译器babel,它可以与generator,ES7提议的技术(比如async/await) 一起使用。 -### Blog Quote: "All those regular flow control constructs you are used to are completely broken" +### 博客引用: "所有那些您所习惯的常规的流量控制结构, 完全被打破" 摘自博客Benno’s - > ……One of the best things about asynchronous, callback based programming is that basically all those regular flow control constructs you are used to are completely broken. However, the one I find most broken is the handling of exceptions. Javascript provides a fairly familiar try…catch construct for dealing with exceptions. The problems with exceptions is that they provide a great way of short-cutting errors up a call stack, but end up being completely useless of the error happens on a different stack… + > ……关于基于异步、回调编程的最好的事情之一是, 基本上您所习惯的所有那些常规的流量控制结构, 是可以完全被打破。然而, 我发现最易打破的是处理例外。Javascript 提供了一个相当熟悉的尝试... 捕获处理异常的构造函数。异常的问题是, 它们提供了在一个调用堆栈上 short-cutting 错误的很好的方法, 但最终由于不同堆栈上发生的错误导致完全无用… diff --git a/sections/errorhandling/centralizedhandling.chinese.md b/sections/errorhandling/centralizedhandling.chinese.md index 6ebdee842..3b7cd8ebd 100644 --- a/sections/errorhandling/centralizedhandling.chinese.md +++ b/sections/errorhandling/centralizedhandling.chinese.md @@ -64,20 +64,20 @@ app.use(function (err, req, res, next) { ``` -### 博客引用: "Sometimes lower levels can’t do anything useful except propagate the error to their caller" - From the blog Joyent, ranked 1 for the keywords “Node.JS error handling” +### 博客引用: "有时较低的级别不能做任何有用的事情, 除非将错误传播给他们的调用者" + 摘自博客 Joyent, 对应关键字 “Node.JS error handling” 排名第一 - > …You may end up handling the same error at several levels of the stack. This happens when lower levels can’t do anything useful except propagate the error to their caller, which propagates the error to its caller, and so on. Often, only the top-level caller knows what the appropriate response is, whether that’s to retry the operation, report an error to the user, or something else. But that doesn’t mean you should try to report all errors to a single top-level callback, because that callback itself can’t know in what context the error occurred… + > …您可能会在stack的多个级别上处理相同的错误。当较低级别不能执行任何有用的操作时, 就会发生这种情况, 除非将错误传播给其调用方, 从而将错误传播到其调用方, 等等。通常, 只有 top-level 调用方知道适当的响应是什么, 无论是重试操作、向用户报告错误还是其他事情。但这并不意味着您应该尝试将所有错误报告给单个 top-level 回调, 因为该回调本身无法知道错误发生在什么上下文中… -### Blog Quote: "Handling each err individually would result in tremendous duplication" - From the blog JS Recipes, ranked 17 for the keywords “Node.JS error handling” +### 博客引用: "单独处理每个错误将导致大量的重复" + 摘自博客 JS Recipes, 对应关键字 “Node.JS error handling” 排名17 - > ……In Hackathon Starter api.js controller alone, there are over 79 occurences of error objects. Handling each err individually would result in tremendous amount of code duplication. The next best thing you can do is to delegate all error handling logic to an Express middleware… + > ……仅仅在Hackathon 启动 api.js 控制器中, 有超过79处重复的错误对象。单独处理每个错误将导致大量的代码重复。您可以做的下一个最好的事情是将所有错误处理逻辑委派给一个express中间件… -### Blog Quote: "HTTP errors have no place in your database code" - From the blog Daily JS, ranked 14 for the keywords “Node.JS error handling” +### 博客引用: "HTTP errors have no place in your database code" + 摘自博客 Daily JS, 对应关键字 “Node.JS error handling” 排名14 - > ……You should set useful properties in error objects, but use such properties consistently. And, don’t cross the streams: HTTP errors have no place in your database code. Or for browser developers, Ajax errors have a place in code that talks to the server, but not code that processes Mustache templates… + > ……您应该在 error 对象中设置有用的属性, 但使用此类属性时应保持一致。而且, 不要越过流: HTTP 错误在您的数据库代码中没有一席之地。或者对于浏览器开发人员来说, Ajax 错误在与服务器对话的代码中有一席之地, 而不是处理Mustache模板的代码… diff --git a/sections/errorhandling/operationalvsprogrammererror.chinese.md b/sections/errorhandling/operationalvsprogrammererror.chinese.md index cbbbabf21..dd524b07b 100644 --- a/sections/errorhandling/operationalvsprogrammererror.chinese.md +++ b/sections/errorhandling/operationalvsprogrammererror.chinese.md @@ -27,25 +27,25 @@ throw new appError(errorManagement.commonErrors.InvalidInput, "Describe here wha ``` ### 博客引用: "程序型错误是程序中的 bug" -摘自博客 Joyent, 对于关键字“Node.JS error handling”排名第一 + 摘自博客 Joyent, 对于关键字“Node.JS error handling”排名第一 > …从程序型错误中恢复的最好方法是立即崩溃。您应该使用restarter运行程序, 以便在发生崩溃时自动重新启动程序。在一个使用了restarter的地方, 在面对一个瞬态程序型错误, 崩溃是最快的方式来恢复可靠的服务… - ### 博客引用: "No safe way to leave without creating some undefined brittle state" -摘自Node.JS官方文档 + ### 博客引用: "不伴随着创建一些未定义的脆性状态,没有安全的方式可以离开" + 摘自Node.JS官方文档 - > …By the very nature of how throw works in JavaScript, there is almost never any way to safely “pick up where you left off”, without leaking references, or creating some other sort of undefined brittle state. The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else. The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker. + > …在 JavaScript 中, throw的工作性质, 没有泄漏引用, 或者创建一些其他类型的未定义的脆性状态,几乎没有任何方法可以安全地 "在你离开的地方重新捡起"。对引发的错误进行响应的最安全方法是关闭进程。当然, 在普通的 web 服务器中, 您可能会打开许多连接, 并且由于其他人触发了错误而突然关闭这些连接是不合理的。更好的方法是向触发错误的请求发送错误响应, 同时让其他人在正常时间内完成, 并停止侦听该工作人员中的新请求。 - ### Blog Quote: "Otherwise you risk the state of your application" -From the blog debugable.com, ranked 3 for the keywords “Node.JS uncaught exception” + ### 博客引用: "否则,您置您应用的状态于风险之中" + 摘自博客 debugable.com, 对于关键字“Node.JS uncaught exception”排名第3 - > …So, unless you really know what you are doing, you should perform a graceful restart of your service after receiving an “uncaughtException” exception event. Otherwise you risk the state of your application, or that of 3rd party libraries to become inconsistent, leading to all kinds of crazy bugs… + > …所以, 除非你真的知道你在做什么, 否则你应该在收到一个 "uncaughtException" 异常事件之后, 对你的服务进行一次优雅的重新启动。否则, 您应用的状态, 或和第三方库的状态变得不一致, 都被置于风险之中,导致各种荒唐的错误… - ### Blog Quote: "Blog Quote: There are three schools of thoughts on error handling" -From the blog: JS Recipes + ### 博客引用: "对于错误处理,有三种学院派想法" + 摘自博客: JS Recipes - > …There are primarily three schools of thoughts on error handling: -1. Let the application crash and restart it. -2. Handle all possible errors and never crash. -3. Balanced approach between the two + > …对于错误处理,主要有三种学院派想法: +1. 让应用崩溃并重启. +2. 处理所有可能的错误,从不崩溃. +3. 两者之间的折中方案 From 9c3b5ddd47efd4cc5c0465adb5fbf6d477ebe8b1 Mon Sep 17 00:00:00 2001 From: jin jing Date: Fri, 22 Dec 2017 10:17:03 +0800 Subject: [PATCH 50/75] [Chinese-translation] useonlythebuiltinerror.chinese.md - add. --- .../useonlythebuiltinerror.chinese.md | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/sections/errorhandling/useonlythebuiltinerror.chinese.md b/sections/errorhandling/useonlythebuiltinerror.chinese.md index bf304df0e..e84c2dd12 100644 --- a/sections/errorhandling/useonlythebuiltinerror.chinese.md +++ b/sections/errorhandling/useonlythebuiltinerror.chinese.md @@ -10,18 +10,18 @@ js天生的宽容性及其多变的代码流选项(例如 EventEmitter, Callba -### Code Example – doing it right +### 代码示例 – 正确处理它 ```javascript -//throwing an Error from typical function, whether sync or async +//从典型函数抛出错误, 无论是同步还是异步 if(!productToAdd) throw new Error("How can I add new product when no value provided?"); -//'throwing' an Error from EventEmitter +//从EventEmitter抛出错误 const myEmitter = new MyEmitter(); myEmitter.emit('error', new Error('whoops!')); -//'throwing' an Error from a Promise +//从promise抛出错误 return new promise(function (resolve, reject) { Return DAL.getProduct(productToAdd.id).then((existingProduct) =>{ if(existingProduct != null) @@ -29,49 +29,47 @@ myEmitter.emit('error', new Error('whoops!')); ``` -### Code example – Anti Pattern +### 代码示例 – 反模式 ```javascript -//throwing a String lacks any stack trace information and other important properties +//抛出字符串错误缺少任何stack trace信息和其他重要属性 if(!productToAdd) throw ("How can I add new product when no value provided?"); ``` -### Code example – doing it even better +### 代码示例 – 更好处理它 ```javascript -//centralized error object that derives from Node’s Error +//从node错误派生的集中错误对象 function appError(name, httpCode, description, isOperational) { Error.call(this); Error.captureStackTrace(this); this.name = name; - //...other properties assigned here + //...在这赋值其它属性 }; appError.prototype.__proto__ = Error.prototype; module.exports.appError = appError; -//client throwing an exception +//客户端抛出一个错误 if(user == null) throw new appError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, "further explanation", true) ``` -### Blog Quote: "A string is not an error" -From the blog devthought.com, ranked 6 for the keywords “Node.JS error object” +### 博客引用: "字符串不是错误" + 摘自博客 devthought.com, 对于关键字 “Node.JS error object” 排名第6 > …传递字符串而不是错误导致模块间协作性降低。它打破了和API的约定,可能是执行instanceof Error这样的检查,或想了解更多关于错误的信息。正如我们将看到的,错误对象在现代JavaScript引擎中拥有非常有趣的属性,同时保留传递给构造函数的消息… -Blog Quote: “All JavaScript and System errors raised by Node.js inherit from Error” - -### Blog Quote: "Inheriting from Error doesn’t add too much value" -From the blog machadogj +### 博客引用: "从Error对象继承不会增加太多的值" + 摘自博客 machadogj - > …One problem that I have with the Error class is that is not so simple to extend. Of course you can inherit the class and create your own Error classes like HttpError, DbError, etc. However that takes time, and doesn’t add too much value unless you are doing something with types. Sometimes, you just want to add a message, and keep the inner error, and sometimes you might want to extend the error with parameters, and such… + > …我对Error类的一个问题是不太容易扩展。当然, 您可以继承该类并创建自己的Error类, 如 HttpError、DbError 等。然而, 这需要时间, 并且不会增加太多的价值, 除非你是在做一些关于类型的事情。有时, 您只想添加一条消息, 并保留内部错误, 有时您可能希望使用参数扩展该错误, 等等… - ### Blog Quote: "All JavaScript and System errors raised by Node.js inherit from Error" -From Node.JS official documentation + ### 博客引用: "所有由node.js引发的 JavaScript 和系统错误继承自Error对象" + 摘自 Node.JS 官方文档 - > …All JavaScript and System errors raised by Node.js inherit from, or are instances of, the standard JavaScript Error class and are guaranteed to provide at least the properties available on that class. A generic JavaScript Error object that does not denote any specific circumstance of why the error occurred. Error objects capture a “stack trace” detailing the point in the code at which the Error was instantiated, and may provide a text description of the error.All errors generated by Node.js, including all System and JavaScript errors, will either be instances of, or inherit from, the Error class… + > …所有由node.js引发的 JavaScript 和系统错误继承自,或是标准 JavaScript 错误类的实例, 这保证至少提供了该类的可用属性。一个通用的 JavaScript 错误对象, 它不表示为什么发生错误的任何特定环境。错误对象捕获一个 "stack trace", 详细说明了错误被实例化的代码中的点, 并可能提供错误的文本描述。由node.js生成的所有错误, 包括所有的系统和 JavaScript 错误, 都将是Errir类的实例, 或继承自Error类… From 48d27b495f94a4347fff6e70f4554c28ffe08d84 Mon Sep 17 00:00:00 2001 From: jin jing Date: Fri, 22 Dec 2017 10:56:08 +0800 Subject: [PATCH 51/75] [Chinese-translation]documentingusingswagger.chinese.md - add. --- .../documentingusingswagger.chinese.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 sections/errorhandling/documentingusingswagger.chinese.md diff --git a/sections/errorhandling/documentingusingswagger.chinese.md b/sections/errorhandling/documentingusingswagger.chinese.md new file mode 100644 index 000000000..79f3406d7 --- /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 From d46c3910dbd6b735cf1ef54973f660faed4dab90 Mon Sep 17 00:00:00 2001 From: jin jing Date: Sat, 23 Dec 2017 15:41:01 +0800 Subject: [PATCH 52/75] [Chinese-translation]apmproducts.chinese.md, detectvulnerabilities.chinese.md and frontendout.chinese.md - add. --- sections/production/apmproducts.chinese.md | 26 ++++++++++++ .../detectvulnerabilities.chinese.md | 17 ++++++++ sections/production/frontendout.chinese.md | 41 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 sections/production/apmproducts.chinese.md create mode 100644 sections/production/detectvulnerabilities.chinese.md create mode 100644 sections/production/frontendout.chinese.md diff --git a/sections/production/apmproducts.chinese.md b/sections/production/apmproducts.chinese.md new file mode 100644 index 000000000..007ccdcf5 --- /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/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..5efe1db72 --- /dev/null +++ b/sections/production/frontendout.chinese.md @@ -0,0 +1,41 @@ +# 在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配置 + +```javascript +gzip on; +#defining gzip compression +keepalive 64; +}#defining web server +server { +listen 80; +listen 443 ssl;#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; +} +``` + +

+ +### 其它博主说了什么 +摘自博客 [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应用中服务文件,这是优化了的。更佳的选择是使用反向代理来服务静态文件; 有关详细信息, 请参阅使用反向代理… + +

From 3d2acac0c409af8b74075f7444d4aa613f466094 Mon Sep 17 00:00:00 2001 From: iamphr <353721401@qq.com> Date: Sun, 24 Dec 2017 16:42:59 +0800 Subject: [PATCH 53/75] smartlogging.chinese.md smartlogging.chinese --- sections/production/smartlogging.chinese.md | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 sections/production/smartlogging.chinese.md diff --git a/sections/production/smartlogging.chinese.md b/sections/production/smartlogging.chinese.md new file mode 100644 index 000000000..d0941d7a9 --- /dev/null +++ b/sections/production/smartlogging.chinese.md @@ -0,0 +1,35 @@ +# 使用智能日志使你的应用程序变得透明 + +

+ + +### 一个段落解释 + +无论如何,您要打印日志语句,显然需要一些可以在其中跟踪错误和核心指标的接口来包装生产信息(在最慢的API端点,每小时发生了多少错误)为什么不在健壮的日志框架中进行一些适度的尝试呢?要实现这一目标,需要在三个步骤上做出深思熟虑的决定: +**1. 智能日志** -在最基本的情况下,您需要使用像[Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan)这样有信誉的日志库,在每个事务开始和结束时编写有意义的信息。还可以考虑将日志语句格式化为JSON,并提供所有上下文属性(如用户id、操作类型等)。这样操作团队就可以在这些字段上操作。在每个日志行中还包含一个唯一的事务ID,因为更多的信息引用下面的例子“写事务ID到日志”。最后要考虑的一点还包括一个代理,它记录系统资源,如内存和CPU,比如弹性节拍。 +**2. 智能聚合** - 一旦您在服务器文件系统中有了全面的信息,就应该定期将这些信息推送到一个聚合、设施和可视化数据的系统中。例如,弹性堆栈是一种流行的、自由的选择,它提供所有组件来聚合和可视化数据。许多商业产品提供了类似的功能,只是它们大大减少了安装时间,不需要主机托管。 +**3. 智能可视化** -现在,这些信息是聚合和搜索的,只有通过轻松搜索日志的能力才能满足这一要求,但如果不编码或花费大量的精力,这就会变得更加困难。 +

+ + +### 可视化示例:Kibana(弹性栈的一部分)促进了对日志内容的高级搜索 +![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") + +

+ +### 可视化示例:Kibana(弹性堆栈的一部分)基于日志来可视化数据 +![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") + +

+ +### 博客:记录器的要求 +来自博客 [Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/): +> 让我们识别一些需求(对于一个日志记录器来说): +> 1. 时间戳每个日志线。这个很好解释,您应该能够判断每个日志条目出现的时间。 +> 2. 日志格式应该很容易被人类和机器消化。 +> 3. 允许多个可配置的目标流。例如,您可能在一个文件中写入跟踪日志,但是当遇到错误时,将其写入相同的文件,然后进入错误文件并同时发送电子邮件。 +

+ + + +

From 20c3fb1ed9a0c7c10d230c1faca4282912833a4c Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 25 Dec 2017 11:38:27 +0800 Subject: [PATCH 54/75] [Chinese-translation]citools.chinese.md -- add. --- sections/testingandquality/citools.chinese.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 sections/testingandquality/citools.chinese.md 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") + + +

From 4b44ae0fc0d2e9285140f0f4ed96a0490cd6f171 Mon Sep 17 00:00:00 2001 From: lilanlan Date: Wed, 27 Dec 2017 17:19:05 +0800 Subject: [PATCH 55/75] translation guardprocess-->>lilanlan~~ --- sections/production/guardprocess.chinese.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 sections/production/guardprocess.chinese.md diff --git a/sections/production/guardprocess.chinese.md b/sections/production/guardprocess.chinese.md new file mode 100644 index 000000000..842344c66 --- /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))中作为第一个守护层是有充分的理由的 - 重新启动 处理并在主机容器要求正常重启时向代码提供特定于节点的功能。其他选择可能会避免不必要的图层。总而言之,没有一个解决方案适合所有人,但了解这些选择是最重要的。 + +

+ + +### 其他博客作者怎么说? + +* 来自[快速正产最佳实践](https://expressjs.com/en/advanced/best-practice-performance.html): +> ... 在开发中,您只需从命令行使用node.js或类似的东西启动您的应用程序。**但是在生产中这样做是一种灾难。 如果应用程序崩溃,它将掉线**,直到您重新启动它。要确保应用程序在崩溃时重新启动,请使用进程管理器。流程管理器是便于部署的应用程序的“容器”,提供高可用性,并使您能够在运行时管理应用程序。 + +* 从中篇博客文章中 [了解节点集群](https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.cssigr5z3): +> ...了解Docker-Land中的NodeJS集群“Docker容器是流线型的轻量级虚拟环境,旨在将流程简化为最低限度。管理和协调自己资源的流程不再有价值。**相反,像Kubernetes,Mesos和Cattle这样的管理层已经普及了这些资源应该在整个基础设施范围进行管理的概念**。CPU和内存资源由“调度器”分配,网络资源由堆栈提供的负载均衡器管理。 From ea7433bba06b2ba1d4a94c002fb7304fb54f8b31 Mon Sep 17 00:00:00 2001 From: leijingyun Date: Tue, 2 Jan 2018 15:56:46 +0800 Subject: [PATCH 56/75] add [chinese_translate] \production\lockdependencies.chinese.md --- .../production/lockdependencies.chinese.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 sections/production/lockdependencies.chinese.md diff --git a/sections/production/lockdependencies.chinese.md b/sections/production/lockdependencies.chinese.md new file mode 100644 index 000000000..d9e9d7896 --- /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使用精确的版本 + +```javascript +//save this as .npmrc file on the project directory +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=" + } + } + } + } +} +``` From f6a4bfdaea4da8b185759937ff7c91dd02b6783d Mon Sep 17 00:00:00 2001 From: jin jing Date: Tue, 2 Jan 2018 15:59:33 +0800 Subject: [PATCH 57/75] [Chinese-translation] add eslint_prettier.chinese.md --- .../eslint_prettier.chinese.md | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 sections/codestylepractices/eslint_prettier.chinese.md diff --git a/sections/codestylepractices/eslint_prettier.chinese.md b/sections/codestylepractices/eslint_prettier.chinese.md new file mode 100644 index 000000000..a8a0756ba --- /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). From 289a78d399a3580c5abf1ad079d44ebb948203fa Mon Sep 17 00:00:00 2001 From: matt_jin Date: Tue, 9 Jan 2018 23:00:00 +0800 Subject: [PATCH 58/75] [Chinese-translation] update and work on breakintcomponents.chinese.md --- README.chinese.md | 14 +++++++------- .../projectstructre/breakintcomponents.chinese.md | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index d574dbfe5..d1616d282 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -18,9 +18,9 @@
# 欢迎! 首先您应该知道的三件事情: -**1. 当您读到这里,实际上您读了很多关于Node.JS的优秀文章 -** 这里是关于Node JS 最佳实践的优质内容的总结和管理 +**1. 当您读到这里,实际上您读了很多关于Node.JS的优秀文章 -** 这是对Node JS 最佳实践中排名最高的内容的总结和分享 -**2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。我们欢迎议题和PR使这本在线书籍不断更新。我们也乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是建议卓越的新想法 - 作为Node.JS最佳实践这本书中的一部分 +**2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。每天都有新的issue和PR被创建,以使这本在线书籍不断更新。我们很乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是提出绝妙的新想法。请查看我们的[milestones 这里](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open) **3. 大部分的条目包含额外的信息 -** 大部分的最佳实践条目的旁边,您将发现 **🔗Read More** 链接,它将呈现给您示例代码,博客引用和更多信息 @@ -31,17 +31,17 @@ 2. [异常处理实践 (11) ](#2-error-handling-practices) 3. [编码规范实践 (12) ](#3-code-style-practices) 4. [测试和总体质量实践 (8) ](#4-testing-and-overall-quality-practices) -5. [Going To Production Practices (16) ](#5-going-to-production-practices) -6. Security Practices (coming soon) -7. Performance Practices (coming soon) +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 组件式构建你的解决方案Structure your solution by components +## ![✔] 1.1 组件式构建你的解决方案 - **TL;DR:** 最大的项目隐患就是维护一个巨大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。 + **TL;DR:** 最坏的大型项目隐患就是维护一个庞大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。 **否则:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展 diff --git a/sections/projectstructre/breakintcomponents.chinese.md b/sections/projectstructre/breakintcomponents.chinese.md index 91cc30ec5..40f2b8866 100644 --- a/sections/projectstructre/breakintcomponents.chinese.md +++ b/sections/projectstructre/breakintcomponents.chinese.md @@ -1,11 +1,11 @@ -# 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、服务、数据访问、测试等),因此很容易理解它。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.

From a239788153eed98eb12a8de36c791a4c4d3737e6 Mon Sep 17 00:00:00 2001 From: jin jing Date: Wed, 10 Jan 2018 10:21:09 +0800 Subject: [PATCH 59/75] [Chinese-translation]update README.chinese.md and add breakintcomponents.chinese.md --- README.chinese.md | 62 +++++++++---------- .../breakintcomponents.chinese.md | 22 +++++-- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index d1616d282..15bb4035a 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -55,7 +55,7 @@ **否则:** 对于混淆了网络层和其它层的应用,将不易于测试,执行CRON的任务,其它非-Express的调用者无法使用 -🔗 [**更多: 应用分层**](/sections/projectstructre/createlayers.md) +🔗 [**更多: 应用分层**](/sections/projectstructre/createlayers.chinese.md)

@@ -65,7 +65,7 @@ **否则:** 您将不得不重造部署和依赖的轮子 -🔗 [**更多: 通过需求构建**](/sections/projectstructre/wraputilities.md) +🔗 [**更多: 通过需求构建**](/sections/projectstructre/wraputilities.chinese.md)

@@ -75,7 +75,7 @@ **否则:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。 -🔗 [**更多: 分离 Express 'app' and 'server'**](/sections/projectstructre/separateexpress.md) +🔗 [**更多: 分离 Express 'app' and 'server'**](/sections/projectstructre/separateexpress.chinese.md)

@@ -85,7 +85,7 @@ **TL;DR:** 一个完美无瑕的配置安装应该确保 (a) 元素可以从文件中,也可以从环境变量中读取 (b) 密码排除在提交的代码之外 (c) 为了易于检索,配置是分级的。仅有几个包可以满足这样的条件,比如[nconf](https://www.npmjs.com/package/nconf) 和 [config](https://www.npmjs.com/package/config)。 **否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。 -🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.md) +🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.chinese.md)


@@ -100,7 +100,7 @@ **否则:** Node.JS 回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。 -🔗 [**更多: 避免回调**](/sections/errorhandling/asyncerrorhandling.md) +🔗 [**更多: 避免回调**](/sections/errorhandling/asyncerrorhandling.chinese.md)

@@ -111,7 +111,7 @@ **否则:** 调用某些模块,将不确定哪种错误类型会返回 - 这将会使恰当的错误处理更加困难。更坏的情况是,使用特定的类型描述错误,会导致重要的错误信息缺失,比如stack trace! -🔗 [**更多: 使用内建错误对象**](/sections/errorhandling/useonlythebuiltinerror.md) +🔗 [**更多: 使用内建错误对象**](/sections/errorhandling/useonlythebuiltinerror.chinese.md)

@@ -121,7 +121,7 @@ **否则:** 当一个错误产生的时候,您总是得重启应用,但为什么要让 ~5000 个在线用户不能访问,仅仅是因为一个细微的,可以预测的,运行时错误?相反的方案,也不完美 – 当未知的问题(程序问题)产生的时候,使应用依旧可以访问,可能导致不可预测行为。区分两者会使处理更有技巧,并在给定的上下文下给出一个平衡的对策。 -🔗 [**更多: 运行错误和程序设计错误**](/sections/errorhandling/operationalvsprogrammererror.md) +🔗 [**更多: 运行错误和程序设计错误**](/sections/errorhandling/operationalvsprogrammererror.chinese.md)

@@ -131,7 +131,7 @@ **否则:** 错误处理的逻辑不放在一起将会导致代码重复和非常可能不恰当的错误处理。 -🔗 [**更多: 集中处理错误**](/sections/errorhandling/centralizedhandling.md) +🔗 [**更多: 集中处理错误**](/sections/errorhandling/centralizedhandling.chinese.md)

@@ -141,7 +141,7 @@ **否则:** 任何API的客户端可能决定崩溃并重启,仅仅因为它收到一个不能处理的错误。注意:API的调用者可能是你(在微服务环境中非常典型)。 -🔗 [**更多: 使用Swagger记录错误**](/sections/errorhandling/documentingusingswagger.md) +🔗 [**更多: 使用Swagger记录错误**](/sections/errorhandling/documentingusingswagger.chinese.md)

@@ -151,7 +151,7 @@ **否则:** 当一个未知的异常被抛出,意味着某些对象包含错误的状态(例如某个全局事件发生器由于某些内在的错误,不在产生事件),未来的请求可能失败或者行为异常。 -🔗 [**更多: 停掉服务**](/sections/errorhandling/shuttingtheprocess.md) +🔗 [**更多: 停掉服务**](/sections/errorhandling/shuttingtheprocess.chinese.md)

@@ -163,7 +163,7 @@ **否则:** 浏览console的log,和不通过查询工具或者一个好的日志查看器,手动浏览繁琐的文本文件,会使你忙于工作到很晚。 -🔗 [**更多: 使用好用的日志工具**](/sections/errorhandling/usematurelogger.md) +🔗 [**更多: 使用好用的日志工具**](/sections/errorhandling/usematurelogger.chinese.md)

@@ -176,7 +176,7 @@ **否则:** 没有测试,不管自动还是手动,您不可能依赖代码去返回正确的错误。而没有可以理解的错误,那将毫无错误处理可言。 -🔗 [**更多: 测试错误流向**](/sections/errorhandling/testingerrorflows.md) +🔗 [**更多: 测试错误流向**](/sections/errorhandling/testingerrorflows.chinese.md)

@@ -187,7 +187,7 @@ **否则:** 您花了很多的力气在测量API的性能和错误,但可能您从来没有意识到真实场景下您最慢的代码块和他们对UX的影响。 -🔗 [**更多: 使用APM产品**](/sections/errorhandling/apmproducts.md) +🔗 [**更多: 使用APM产品**](/sections/errorhandling/apmproducts.chinese.md)

@@ -199,7 +199,7 @@ **否则:** 您的错误将被回收,无踪迹可循。没有什么可以需要考虑。 -🔗 [**更多: 捕获未处理的promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.md) +🔗 [**更多: 捕获未处理的promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.chinese.md)

@@ -209,7 +209,7 @@ **否则:** 考虑这种情况 – 您的功能期望一个数字参数 “Discount” ,然而调用者忘记传值,之后在您的代码中检查是否 Discount!=0 (允许的折扣值大于零),这样它将允许用户使用一个折扣。OMG,多么不爽的一个漏洞。你能明白吗? -🔗 [**更多: 快速查错**](/sections/errorhandling/failfast.md) +🔗 [**更多: 快速查错**](/sections/errorhandling/failfast.chinese.md)


@@ -414,7 +414,7 @@ null == undefined // true **否则:** 一旦您需要一些高级定制,选择一些细分市场供应商可能会让您停滞不前。另一方面,伴随着jenkins,可能会在基础设施设置上浪费宝贵的时间。 -🔗 [**更多: 挑选 CI 平台**](/sections/testingandquality/citools.md) +🔗 [**更多: 挑选 CI 平台**](/sections/testingandquality/citools.chinese.md)

@@ -472,7 +472,7 @@ null == undefined // true **否则:** 错误 === 失望的客户. 非常简单. -🔗 [**更多: 监控!**](/sections/production/monitoring.md) +🔗 [**更多: 监控!**](/sections/production/monitoring.chinese.md)

@@ -483,7 +483,7 @@ null == undefined // true **否则:** 您最终像是面对一个黑盒,不知道发生了什么事情,然后你开始重新写日志语句添加额外的信息。 -🔗 [**更多: Increase transparency using smart logging**](/sections/production/smartlogging.md) +🔗 [**更多: Increase transparency using smart logging**](/sections/production/smartlogging.chinese.md)

@@ -494,7 +494,7 @@ null == undefined // true **否则:** 单线程的node服务器将不幸地忙于处理网络任务,而不是处理应用程序核心,性能会相应降低。 -🔗 [**更多: 委托一切可能的(例如:gzip,SSL)给反向代理**](/sections/production/delegatetoproxy.md) +🔗 [**更多: 委托一切可能的(例如:gzip,SSL)给反向代理**](/sections/production/delegatetoproxy.chinese.md)

@@ -505,7 +505,7 @@ null == undefined // true **否则:** QA测试通过的代码和批准的版本,在生产中表现不一致。更糟糕的是,同一生产集群中的不同服务器可能运行不同的代码。 -🔗 [**更多: 锁住依赖**](/sections/production/lockdependencies.md) +🔗 [**更多: 锁住依赖**](/sections/production/lockdependencies.chinese.md)

@@ -516,7 +516,7 @@ null == undefined // true **否则:** 运行几十个实例没有明确的战略和太多的工具(集群管理,docker,PM2)可能导致一个DevOps混乱 -🔗 [**更多: 使用正确的工具保护进程正常运行**](/sections/production/guardprocess.md) +🔗 [**更多: 使用正确的工具保护进程正常运行**](/sections/production/guardprocess.chinese.md)

@@ -528,7 +528,7 @@ null == undefined // true **否则:** 您的应用可能只是使用了其可用资源中的25% (!),甚至更少。注意,一台典型的服务器有4个或更多的CPU,默认的Node.JS部署仅仅用了一个CPU(甚至使用PaaS服务,比如AWS beanstalk,也一样)。 -🔗 [**更多: 利用所有的CPU**](/sections/production/utilizecpu.md) +🔗 [**更多: 利用所有的CPU**](/sections/production/utilizecpu.chinese.md)

@@ -539,7 +539,7 @@ null == undefined // true **否则:** 您会发现,您正在执行许多“诊断部署” — 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。 -🔗 [**更多: 创建一个 ‘维护端点’ **](/sections/production/createmaintenanceendpoint.md) +🔗 [**更多: 创建一个 ‘维护端点’ **](/sections/production/createmaintenanceendpoint.chinese.md)

@@ -550,7 +550,7 @@ null == undefined // true **否则:** 你可能会花大力气测量API性能和停机时间,也许你永远不会知道,真实场景下哪个是你最慢的代码部分,这些怎么影响用户体验。 -🔗 [**更多: 使用APM产品发现错误和宕机时间**](/sections/production/apmproducts.md) +🔗 [**更多: 使用APM产品发现错误和宕机时间**](/sections/production/apmproducts.chinese.md)

@@ -563,7 +563,7 @@ null == undefined // true **否则:** 一个世界冠军级别的IT/运维人员也不能拯救一个编码低劣的系统。 -🔗 [**更多: 使您的代码保持生产环境就绪**](/sections/production/productoncode.md) +🔗 [**更多: 使您的代码保持生产环境就绪**](/sections/production/productoncode.chinese.md)

@@ -574,7 +574,7 @@ null == undefined // true **否则:** 您的内存可能一天泄漏一百兆,就像曾发生在沃尔玛的一样。 -🔗 [**更多: 测量和保护内存使用**](/sections/production/measurememory.md) +🔗 [**更多: 测量和保护内存使用**](/sections/production/measurememory.chinese.md)

@@ -586,7 +586,7 @@ null == undefined // true **否则:** 您的单个node线程将忙于传输成百上千的html/图片/angular/react文件,而不是分配其所有的资源为了其擅长的任务 – 服务动态内容 -🔗 [**更多: Node外管理您的前端资源**](/sections/production/frontendout.md) +🔗 [**更多: Node外管理您的前端资源**](/sections/production/frontendout.chinese.md)

@@ -598,7 +598,7 @@ null == undefined // true **否则:** 某个服务器上的故障将导致应用程序宕机,而不仅仅是停用故障机器。此外,由于依赖特定服务器,伸缩弹性会变得更具挑战性。 -🔗 [**Read More: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.md) +🔗 [**Read More: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.chinese.md)

@@ -611,7 +611,7 @@ null == undefined // true **否则:** 否则: 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物。相当繁琐。 -🔗 [**更多: 使用自动检测漏洞的工具**](/sections/production/detectvulnerabilities.md) +🔗 [**更多: 使用自动检测漏洞的工具**](/sections/production/detectvulnerabilities.chinese.md)

@@ -623,7 +623,7 @@ null == undefined // true **否则:** 在没有上下文的情况下查看生产错误日志,这会使问题变得更加困难和缓慢去解决。 -🔗 [**更多: 在每一个log语句中指明 ‘TransactionId’**](/sections/production/assigntransactionid.md) +🔗 [**更多: 在每一个log语句中指明 ‘TransactionId’**](/sections/production/assigntransactionid.chinese.md)

@@ -635,7 +635,7 @@ null == undefined // true **否则:** 遗漏这个简单的属性可能大幅减弱性能。例如,在使用Express作为服务端渲染页面的时候,如果未设置NODE_ENV,性能将会减慢大概三分之一! -🔗 [**更多: 设置NODE_ENV=production**](/sections/production/setnodeenv.md) +🔗 [**更多: 设置NODE_ENV=production**](/sections/production/setnodeenv.chinese.md)

diff --git a/sections/projectstructre/breakintcomponents.chinese.md b/sections/projectstructre/breakintcomponents.chinese.md index 40f2b8866..9704dd025 100644 --- a/sections/projectstructre/breakintcomponents.chinese.md +++ b/sections/projectstructre/breakintcomponents.chinese.md @@ -5,22 +5,32 @@ ### 一段解释 -对于中等规模的应用程序及以上,一个代码库是非常糟糕的 - 一个包含很多依赖的大型软件很难理解,往往导致代码混乱。即使是那些擅长解决负责问题和 "模块化" 的聪明架构师 - 在设计上花费了很大的脑力, 每一个变化都需要仔细评估对其他依赖对象的影响。最终的解决方案是开发小型软件:将整个堆栈划分为独立的组件,这些组件不与其他组件共享文件,每个组件由很少的文件构成(例如API、服务、数据访问、测试等),因此很容易理解它。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") From fa9d4ede972c57894116cbdd8e821c11f560f097 Mon Sep 17 00:00:00 2001 From: jin jing Date: Wed, 10 Jan 2018 12:54:39 +0800 Subject: [PATCH 60/75] [Chinese-translation] add format. --- sections/projectstructre/configguide.chinese.md | 10 ++++++---- sections/projectstructre/createlayers.chinese.md | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/sections/projectstructre/configguide.chinese.md b/sections/projectstructre/configguide.chinese.md index 10b65e5e5..9a9eb60a3 100644 --- a/sections/projectstructre/configguide.chinese.md +++ b/sections/projectstructre/configguide.chinese.md @@ -1,17 +1,18 @@ -使用环境感知,安全,分层的配置 +# 使用环境感知,安全,分层的配置

-解释 +### 一段解释 当我们处理配置参数时,常常会很慢并且很烦躁:(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 +28,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") From 0b87157b67ad56bfd4bd5c12e0e91d423f921520 Mon Sep 17 00:00:00 2001 From: jin jing Date: Thu, 11 Jan 2018 15:40:24 +0800 Subject: [PATCH 61/75] [Chinese-translation] modify some strings. --- README.chinese.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 15bb4035a..28e14836b 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -27,7 +27,7 @@


## 目录 -1. [项目结构实践 (5)](#1-project-structure-practices) +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) @@ -90,7 +90,7 @@


-

⬆ Return to top

+

⬆ 返回顶部

# `2. 错误处理最佳实践` @@ -213,7 +213,7 @@


-

⬆ Return to top

+

⬆ 返回顶部

# `3. 编码风格实践` @@ -310,7 +310,7 @@

-## ![✔] 3.8 Requires come first, and not inside functions +## ![✔] 3.8 先require, 而不是在方法内部 **TL;DR:** 在每个文件的起始位置,在任何函数的前面和外部 require 模块。这种简单的最佳实践,不仅能帮助您轻松快速地在文件顶部辨别出依赖关系,而且避免了一些潜在的问题。 @@ -386,7 +386,7 @@ null == undefined // true


-

⬆ Return to top

+

⬆ 返回顶部

# `4. 测试和总体的质量实践` @@ -444,11 +444,11 @@ null == undefined // true

-## ![✔] 4.7 Inspect for outdated packages +## ![✔] 4.7 检查过期的依赖包 -**TL;DR:** Use your preferred tool (e.g. 'npm outdated' or [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) to detect installed packages which are outdated, inject this check into your CI pipeline and even make a build fail in a severe scenario. For example, a severe scenario might be when an installed package is 5 patch commits behind (e.g. local version is 1.3.1 and repository version is 1.3.8) or it is tagged as deprecated by its author - kill the build and prevent deploying this version +**TL;DR:** 使用您的首选工具 (例如 'npm outdated' or [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) 来检测已安装的过期依赖包, 将此检查注入您的 CI 管道, 甚至在严重的情况下使构建失败。例如, 当一个已安装的依赖包滞后5个补丁时 (例如:本地版本是1.3.1 的, 存储库版本是1.3.8 的), 或者它被其作者标记为已弃用, 可能会出现严重的情况 - 停掉这次构建并防止部署此版本。 -**Otherwise:** Your production will run packages that have been explicitly tagged by their author as risky +**否则:** 您的生产环境将运行已被其作者明确标记为有风险的依赖包

@@ -462,7 +462,7 @@ null == undefined // true


-

⬆ Return to top

+

⬆ 返回顶部

# `5. 上线实践` ## ![✔] 5.1. 监控! @@ -649,7 +649,7 @@ null == undefined // true


-

⬆ Return to top

+

⬆ 返回顶部

# `Security Practices` From 68fd1505b125ce750c55a8e9f8b1f69bcc977368 Mon Sep 17 00:00:00 2001 From: jin jing Date: Fri, 12 Jan 2018 10:01:46 +0800 Subject: [PATCH 62/75] [Chinese-translation]some changes. --- .../eslint_prettier.chinese.md | 2 +- sections/errorhandling/apmproducts.chinese.md | 16 ++++++------- .../asyncerrorhandling.chinese.md | 22 +++++++++--------- .../catchunhandledpromiserejection.chinese.md | 22 +++++++++--------- .../centralizedhandling.chinese.md | 12 +++++----- .../documentingusingswagger.chinese.md | 6 ++--- sections/errorhandling/failfast.chinese.md | 6 ++--- sections/errorhandling/monitoring.chinese.md | 8 +++---- .../operationalvsprogrammererror.chinese.md | 8 +++---- .../shuttingtheprocess.chinese.md | 4 ++-- .../testingerrorflows.chinese.md | 2 +- .../errorhandling/usematurelogger.chinese.md | 23 +++++++++++-------- .../useonlythebuiltinerror.chinese.md | 6 ++--- 13 files changed, 69 insertions(+), 68 deletions(-) diff --git a/sections/codestylepractices/eslint_prettier.chinese.md b/sections/codestylepractices/eslint_prettier.chinese.md index a8a0756ba..c8f32b8f5 100644 --- a/sections/codestylepractices/eslint_prettier.chinese.md +++ b/sections/codestylepractices/eslint_prettier.chinese.md @@ -23,4 +23,4 @@ Source: [https://github.com/prettier/prettier-eslint/issues/101](https://github. ### 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). +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 index b1227ece8..50441b732 100644 --- a/sections/errorhandling/apmproducts.chinese.md +++ b/sections/errorhandling/apmproducts.chinese.md @@ -3,27 +3,25 @@ ### 一段解释 -异常 != 错误。传统的错误处理假定存在异常, 但应用程序错误可能以代码路径慢、API 停机、缺少计算资源等形式出现。因为APM产品允许使用最小的设置来先前一步地检测各种各样 "深埋" 的问题,这是运用它们方便的地方。APM 产品的常见功能包括: 当 HTTP API 返回错误时报警, 在 api 响应时间低于某个阈值时能检测到, 觉察到 "code smells"、监视服务器资源、操作智能仪表板以及 IT 度量和其他许多有用的功能。大多数供应商提供免费方案。 +异常 != 错误。传统的错误处理假定存在异常,但应用程序错误可能以代码路径慢,API停机,缺少计算资源等形式出现。因为APM产品允许使用最小的设置来先前一步地检测各种各样 "深埋" 的问题,这是运用它们方便的地方。APM产品的常见功能包括: 当HTTP API返回错误时报警, 在API响应时间低于某个阈值时能被检测, 觉察到‘code smells’,监视服务器资源,包含IT度量的操作型智能仪表板以及其他许多有用的功能。大多数供应商提供免费方案。 ### 关于 APM 的维基百科 -在信息技术和系统管理领域, 应用程序性能管理 (APM) 是对软件应用程序的性能和可用性的监视和管理。APM 努力检测和诊断复杂的应用程序性能问题, 以维护预期的服务级别。APM 是 "将 IT 度量标准转换为业务含义 ([i.e.] value)" -主要产品和部分 +在信息技术和系统管理领域, 应用程序性能管理(APM)是对软件应用程序的性能和可用性的监视和管理。APM努力检测和诊断复杂的应用程序性能问题, 以维护预期的服务级别。APM是"将IT度量标准转换为业务含义" ### 了解 APM 市场 APM 产品由3个主要部分构成: -1. 网站或API监控 – 通过 HTTP 请求不断监视正常运行时间和性能的外部服务。可以在几分钟内安装。以下是少数选定的竞争者: Pingdom, Uptime Robot, 和 New Relic; +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; +2. 代码检测 – 这类产品需要在应用程序中嵌入代理, 以实现如检测运行缓慢的代码、异常统计、性能监视等功能。以下是少数选定的竞争者: New Relic, App Dynamics; -3. 操作智能仪表板 – 这些产品系列侧重于为 ops 团队提供度量和管理内容, 帮助他们轻松地保持应用程序性能的最高水平。这通常涉及聚合多个信息源 (应用程序日志、DB 日志、服务器日志等) 和前期仪表板设计工作。以下是少数选定的竞争者: Datadog, Splunk; +3. 操作型智能仪表板 – 这些产品系列侧重于为ops团队提供度量和管理内容, 帮助他们轻松地保持应用程序性能维持在最佳状态。这通常涉及聚合多个信息源 (应用程序日志、DB日志、服务器日志等) 和前期仪表板设计工作。以下是少数选定的竞争者: [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/); - - ### Example: UpTimeRobot.Com – 网站监控仪表板 + ### 示例: UpTimeRobot.Com – 网站监控仪表板 ![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") - ### Example: AppDynamics.Com – 与代码检测结合的端到端监视 + ### 示例: 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 index 96a3415a4..f168a4500 100644 --- a/sections/errorhandling/asyncerrorhandling.chinese.md +++ b/sections/errorhandling/asyncerrorhandling.chinese.md @@ -1,9 +1,9 @@ -# 对于异步的错误处理使用Async-Await或者promise +# 对于异步的错误处理,请使用Async-Await或者promise ### 一段解释 -回调不能形成一定规模,是由于对于大多数的程序员来说不熟悉,被迫随处检测错误,让人不快的代码内嵌和难以理解的代码流程。通过使用return和throw来控制程序流程,promise的库比如,BlueBird,async,和Q封装了一种标准的代码风格。具体来说,它们支持最受欢迎的try-catch错误处理风格,它允许主流程代码从在每一个方法中处理错误的方式中释放出来。 +由于回调对于大多数的程序员来说不熟悉,被迫随处检测错误,让人不快的代码内嵌和难以理解的代码流程,它没有形成一定规模。promise的库,比如BlueBird,async,和Q封装了一种标准的代码风格, 它通过使用return和throw来控制程序流程。具体来说,它们支持最受欢迎的try-catch错误处理风格,这使得主流程代码从在每一个方法中处理错误的方式中解放出来。 ### 代码示例 – 使用promise捕获错误 @@ -30,27 +30,27 @@ getData(someParameter, function(err, result){ getMoreData(b, function(c){ getMoreData(d, function(e){ if(err != null) - //you get the idea?  + //你有什么想法?  }); }); ``` -### 博客引用: "我们使用promise有问题" -摘自博客pouchdb.com +### 博客引用: "我们使用promise有一个问题" + 摘自博客pouchdb.com > ……实际上, 回调会做一些更险恶的事情: 他们剥夺了我们的stack, 这是我们通常在编程语言中想当然的事情。编写没有堆栈的代码很像驾驶一辆没有刹车踏板的汽车: 你没有意识到你有多么需要它, 直到你伸手去找它, 而它不在那里。promise的全部目的是让我们回到我们在异步时丢失的语言基础: return,throw和stack。但你必须知道如何正确使用promise, 以便利用他们。 ### 博客引用: "promise方法更加紧凑" -摘自博客gosquared.com + 摘自博客gosquared.com - > ………promise的方法更紧凑, 更清晰, 写起来更快速。如果在任何 ops 中发生错误或异常, 则由单个 .catch () 处理程序操作处理。有这个单一的地方来处理所有的错误意味着你不需要为每个阶段的工作写错误检查。 + > ………promise的方法更紧凑, 更清晰, 写起来更快速。如果在任何ops中发生错误或异常,则由单个.catch()处理程序处理。有这个单一的地方来处理所有的错误意味着你不需要为每个阶段的工作写错误检查。 ### 博客引用: "原生ES6支持promise,可以和generator一起使用" -摘自博客StrongLoop + 摘自博客StrongLoop - > ….回调有一个糟糕的错误处理的报道。promise更好。将express内置的错误处理与promise结合起来, 大大降低了uncaught exception的几率。原生ES6支持promise, 通过编译器babel,它可以与generator,ES7提议的技术(比如async/await) 一起使用。 + > ….回调有一个糟糕的错误处理的报道。promise更好。将express内置的错误处理与promise结合起来, 大大降低了uncaught exception的几率。原生ES6支持promise, 通过编译器babel,它可以与generator,ES7提议的技术(比如async/await)一起使用。 ### 博客引用: "所有那些您所习惯的常规的流量控制结构, 完全被打破" -摘自博客Benno’s + 摘自博客Benno’s - > ……关于基于异步、回调编程的最好的事情之一是, 基本上您所习惯的所有那些常规的流量控制结构, 是可以完全被打破。然而, 我发现最易打破的是处理例外。Javascript 提供了一个相当熟悉的尝试... 捕获处理异常的构造函数。异常的问题是, 它们提供了在一个调用堆栈上 short-cutting 错误的很好的方法, 但最终由于不同堆栈上发生的错误导致完全无用… + > ……关于基于异步、回调编程的最好的事情之一是, 基本上所有那些您习惯的常规流量控制结构, 完全被打破。然而, 我发现最易打破的是处理异常。Javascript提供了一个相当熟悉的try...catch结构来处理异常。异常的问题是, 它们提供了在一个调用堆栈上 short-cutting错误的很好的方法, 但最终由于不同堆栈上发生的错误导致完全无用… diff --git a/sections/errorhandling/catchunhandledpromiserejection.chinese.md b/sections/errorhandling/catchunhandledpromiserejection.chinese.md index 76ad774f7..830d4bbd0 100644 --- a/sections/errorhandling/catchunhandledpromiserejection.chinese.md +++ b/sections/errorhandling/catchunhandledpromiserejection.chinese.md @@ -4,7 +4,7 @@ ### 一段解释 -通常,大部分的现代node.js/express应用代码运行在promise里 – 或者是在.then里处理,一个回调函数中,或者在一个catch块中。令人惊讶的是,除非开发者记得添加.catch语句,在这些地方抛出的错误都不会被uncaughtException事件处理程序来处理,然后消失掉。当未处理的rejection出现,node最近的版本增加了一个警告消息,尽管当事情出错的时候这可能有助于发现问题,但这显然不是一个适当的错误处理。简单明了的解决方案是永远不要忘记在每个promise链式调用中添加.catch语句,并重定向到一个集中的错误处理程序。然而,只在开发人员的规程上构建错误处理策略是有些脆弱的。因此,使用优美的回退和订阅到process.on('unhandledrejection',callback)是高度推荐的 – 这将确保任何promise错误,如果不是本地处理,将在这处理。 +通常,大部分的现代node.js/express应用代码运行在promise里 – 或者是在.then里处理,一个回调函数中,或者在一个catch块中。令人惊讶的是,除非开发者记得添加.catch语句,在这些地方抛出的错误都不会被uncaughtException事件处理程序来处理,然后消失掉。当未处理的rejection出现,node最近的版本增加了一个警告消息,尽管当事情出错的时候这可能有助于发现问题,但这显然不是一个适当的错误处理方法。简单明了的解决方案是永远不要忘记在每个promise链式调用中添加.catch语句,并重定向到一个集中的错误处理程序。然而,只在开发人员的规程上构建错误处理策略是有些脆弱的。因此,使用一个优雅的回调并订阅到process.on('unhandledrejection',callback)是高度推荐的 – 这将确保任何promise错误,如果不是本地处理,将在这处理。

@@ -13,7 +13,7 @@ ```javascript DAL.getUserById(1).then((johnSnow) => { - //this error will just vanish + //this error will just vanish if(johnSnow.isAlive == false) throw new Error('ahhhh'); }); @@ -23,11 +23,11 @@ DAL.getUserById(1).then((johnSnow) => ### 代码示例: 捕获 unresolved 和 rejected 的 promise ```javascript -process.on('unhandledRejection', function (reason, p) { +process.on('unhandledRejection', (reason, p) => { //我刚刚捕获了一个未处理的promise rejection, 因为我们已经有了对于未处理错误的后备的处理机制(见下面), 直接抛出,让它来处理 throw reason; }); -process.on('uncaughtException', function (error) { +process.on('uncaughtException', (error) => { //我刚收到一个从未被处理的错误,现在处理它,并决定是否需要重启应用 errorManagement.handler.handleError(error); if (!errorManagement.handler.isTrustedError(error)) @@ -37,21 +37,21 @@ process.on('uncaughtException', function (error) { ```

### 博客引用: "如果你犯了错误,在某个时候你就会犯错误。" -摘自 James Nelson 的博客 + 摘自 James Nelson 的博客 > 让我们测试一下您的理解。下列哪一项是您期望错误将会打印到控制台的? ```javascript -Promise.resolve(‘promised value’).then(function() { -throw new Error(‘error’); +Promise.resolve(‘promised value’).then(() => { + throw new Error(‘error’); }); -Promise.reject(‘error value’).catch(function() { -throw new Error(‘error’); +Promise.reject(‘error value’).catch(() => { + throw new Error(‘error’); }); -new Promise(function(resolve, reject) { -throw new Error(‘error’); +new Promise((resolve, reject) => { + throw new Error(‘error’); }); ``` diff --git a/sections/errorhandling/centralizedhandling.chinese.md b/sections/errorhandling/centralizedhandling.chinese.md index 3b7cd8ebd..1f7d4214d 100644 --- a/sections/errorhandling/centralizedhandling.chinese.md +++ b/sections/errorhandling/centralizedhandling.chinese.md @@ -1,9 +1,9 @@ -# 集中处理错误,通过但不是在中间件里处理错误Ha +# 集中处理错误,通过但不是在中间件里处理错误 ### 一段解释 -如果没有一个专用的错误处理对象,那么由于操作不当,隐藏在雷达下的重要错误的可能性更大。错误处理对象负责使错误可见,例如通过写入一个格式话良好的logger,通过电子邮件将事件发送到某个监控产品或管理员。一个典型的错误处理流程可能是:一些模块抛出一个错误 -> API路由器捕获错误 -> 它传播错误给负责捕获错误的中间件(如Express,KOA)-> 集中式错误处理程序被调用 -> 中间件正在被告之这个错误是否是一个不可信的错误(不是操作型错误),这样可以优雅的重新启动应用程序。注意,在Express中间件中处理错误是一种常见但又错误的做法,这样做不会覆盖在非Web接口中抛出的错误。 +如果没有一个专用的错误处理对象,那么由于操作不当,在雷达下重要错误被隐藏的可能性就会更大。错误处理对象负责使错误可见,例如通过写入一个格式化良好的logger,通过电子邮件将事件发送到某个监控产品或管理员。一个典型的错误处理流程可能是:一些模块抛出一个错误 -> API路由器捕获错误 -> 它传播错误给负责捕获错误的中间件(如Express,KOA)-> 集中式错误处理程序被调用 -> 中间件正在被告之这个错误是否是一个不可信的错误(不是操作型错误),这样可以优雅的重新启动应用程序。注意,在Express中间件中处理错误是一种常见但又错误的做法,这样做不会覆盖在非Web接口中抛出的错误。 @@ -67,17 +67,17 @@ app.use(function (err, req, res, next) { ### 博客引用: "有时较低的级别不能做任何有用的事情, 除非将错误传播给他们的调用者" 摘自博客 Joyent, 对应关键字 “Node.JS error handling” 排名第一 - > …您可能会在stack的多个级别上处理相同的错误。当较低级别不能执行任何有用的操作时, 就会发生这种情况, 除非将错误传播给其调用方, 从而将错误传播到其调用方, 等等。通常, 只有 top-level 调用方知道适当的响应是什么, 无论是重试操作、向用户报告错误还是其他事情。但这并不意味着您应该尝试将所有错误报告给单个 top-level 回调, 因为该回调本身无法知道错误发生在什么上下文中… + > …您可能会在stack的多个级别上处理相同的错误。这发生在当较低级别不能执行任何有用的操作,除了将错误传播给它们的调用方, 从而将错误传播到其调用方, 等等。通常, 只有top-level调用方知道适当的响应是什么, 无论是重试操作、向用户报告错误还是其他事情。但这并不意味着您应该尝试将所有错误报告给单个top-level回调, 因为该回调本身无法知道错误发生在什么上下文中… ### 博客引用: "单独处理每个错误将导致大量的重复" 摘自博客 JS Recipes, 对应关键字 “Node.JS error handling” 排名17 - > ……仅仅在Hackathon 启动 api.js 控制器中, 有超过79处重复的错误对象。单独处理每个错误将导致大量的代码重复。您可以做的下一个最好的事情是将所有错误处理逻辑委派给一个express中间件… + > ……仅仅在Hackathon启动api.js控制器中, 有超过79处重复的错误对象。单独处理每个错误将导致大量的代码重复。您可以做的下一个最好的事情是将所有错误处理逻辑委派给一个express中间件… -### 博客引用: "HTTP errors have no place in your database code" +### 博客引用: "HTTP错误不会在数据库代码中出现" 摘自博客 Daily JS, 对应关键字 “Node.JS error handling” 排名14 - > ……您应该在 error 对象中设置有用的属性, 但使用此类属性时应保持一致。而且, 不要越过流: HTTP 错误在您的数据库代码中没有一席之地。或者对于浏览器开发人员来说, Ajax 错误在与服务器对话的代码中有一席之地, 而不是处理Mustache模板的代码… + > ……您应该在error对象中设置有用的属性, 但使用此类属性时应保持一致。而且, 不要越过流: HTTP错误不会在数据库代码中出现。或者对于浏览器开发人员来说, Ajax 错误在与服务器交互的代码中有一席之地, 而不是处理Mustache模板的代码… diff --git a/sections/errorhandling/documentingusingswagger.chinese.md b/sections/errorhandling/documentingusingswagger.chinese.md index 79f3406d7..57db0bcf5 100644 --- a/sections/errorhandling/documentingusingswagger.chinese.md +++ b/sections/errorhandling/documentingusingswagger.chinese.md @@ -1,14 +1,14 @@ -# 使用Swagger对 API 错误文档化 +# 使用Swagger对API错误文档化 ### 一段解释 -REST API 使用 HTTP 代码返回结果, API 用户不仅绝对需要了解 API schema, 而且还要注意潜在错误 – 调用方可能会捕获错误并巧妙地处理它。例如, 您的 api 文档可能提前指出, 当客户名称已经存在时, HTTP 状态409将返回 (假设 api 注册新用户), 因此调用方可以相应地呈现给定情况下的最佳 UX。Swagger是一个标准, 它定义了 API 文档的schema, 提供了一个生态系统的工具, 允许在线轻松创建文档, 请参阅下面的打印屏幕。 +REST API使用HTTP代码返回结果, API用户不仅绝对需要了解API schema, 而且还要注意潜在错误 – 调用方可能会捕获错误并巧妙地处理它。例如, 您的api文档可能提前指出, 当客户名称已经存在时, HTTP状态409将返回 (假设api注册新用户), 因此调用方可以相应地呈现给定情况下的最佳UX。Swagger是一个标准, 它定义了 API 文档的schema, 提供了一个生态系统的工具, 允许在线轻松创建文档, 请参阅下面的打印屏幕。 ### 博客引用: "您必须告诉您的调用者什么错误可能发生" 摘自博客 Joyent, 对于关键字 “Node.JS logging” , 排名第一 - > 我们已经讨论了如何处理错误, 但是在编写新函数时, 如何将错误传递给调用函数的代码? + > 我们已经讨论了如何处理错误, 但是在编写新函数时, 如何将错误传递给调用您的函数的代码? ...如果你不知道会发生什么错误或者不知道他们的意思, 那么你的程序就不可能是正确的, 除非是偶然的。所以, 如果你正在写一个新的函数, 你必须告诉你的调用者什么错误可以发生, 它们的意思是什么… diff --git a/sections/errorhandling/failfast.chinese.md b/sections/errorhandling/failfast.chinese.md index 6cc704d7f..5055d1ad5 100644 --- a/sections/errorhandling/failfast.chinese.md +++ b/sections/errorhandling/failfast.chinese.md @@ -1,9 +1,9 @@ -# 快速察觉失败,使用专用库验证参数 +# 快速报错,使用专用库验证参数 ### 一段解释 -我们都知道如何检查参数和快速失败对于避免隐藏的错误很重要(见下面的反模式代码示例)。如果没有,请阅读显式编程和防御性编程。在现实中,由于对其编码是件恼人的事情(比如考虑验证分层的JSON对象,它包含像email和日期这样的字段),我们倾向于避免做这样的事情 – 像Joi这样的库和验证器轻而易举的处理这个乏味的任务。 +我们都知道如何检查参数和快速报错对于避免隐藏的错误很重要(见下面的反模式代码示例)。如果没有,请阅读显式编程和防御性编程。在现实中,由于对其编码是件恼人的事情(比如考虑验证分层的JSON对象,它包含像email和日期这样的字段),我们倾向于避免做这样的事情 – 像Joi这样的库和验证器轻而易举的处理这个乏味的任务。 ### 维基百科: 防御性编程 @@ -47,4 +47,4 @@ redirectToPrintDiscount(httpResponse, someMember); ### 博客引用: "您应该立即抛出这些错误" 摘自博客: Joyent - > 一个退化情况是有人调用一个异步函数但没有传递一个回调方法。你应该立即抛出这些错误, 因为程序有了错误, 最好的调试它的时机包括获得至少stack trace和理想情况下,核心文件里错误的点。为此, 我们建议在函数开始时验证所有参数的类型。 \ No newline at end of file + > 一个退化情况是有人调用一个异步函数但没有传递一个回调方法。你应该立即抛出这些错误, 因为程序有了错误, 最好的调试它的时机包括,获得至少一个stack trace, 和理想情况下,核心文件里错误的点。为此, 我们建议在函数开始时验证所有参数的类型。 \ No newline at end of file diff --git a/sections/errorhandling/monitoring.chinese.md b/sections/errorhandling/monitoring.chinese.md index 94948fe79..724dc913e 100644 --- a/sections/errorhandling/monitoring.chinese.md +++ b/sections/errorhandling/monitoring.chinese.md @@ -3,14 +3,14 @@ ### 一段解释 -> 在最基本的层面上,监控意味着您可以很*容易地识别出在生产环境中发生了什么不好的事情,例如,通过电子邮件或Slack通知。挑战在于选择合适的工具集来满足您的需求而不会破坏您的防护。我建议,从确定核心的指标集开始,这些指标必须被监控以确保一个健康的状态 – CPU,服务器的RAM,node进程RAM(小于1.4gb),在最后一分钟的错误量,重新启动的进程数量,平均响应时间。然后浏览一些你可能喜欢的高级功能并添加到你的愿望清单中。一些豪华的监控功能的例子:数据库分析,跨服务的测量(即测量业务交易),前端整合,暴露原始数据给自定义的BI clients,Slack通知及其他。 +> 在最基本的层面上,监控意味着您可以很*容易地识别出在生产环境中发生了什么不好的事情,例如,通过电子邮件或Slack通知。挑战在于选择合适的工具集来满足您的需求而不会破坏您的防护。我建议,从确定核心的指标集开始,这些指标必须被监控以确保一个健康的状态 – CPU,服务器的RAM,node进程RAM(小于1.4GB),在最后一分钟的错误量,进程重新启动的数量,平均响应时间。然后浏览一些你可能喜欢的高级功能并添加到你的愿望清单中。一些豪华的监控功能的例子:数据库分析,跨服务的测量(即测量业务交易),前端整合,暴露原始数据给自定义的BI clients,Slack通知及其他。 -实现高级功能需要冗长的设置或购买商业产品如datadog,NewRelic和相似产品。不幸的是,即使是基本的实现也不像在公园散步那么简单,因为一些度量指标是硬件相关的(CPU),而其他的则在node进程内(内部错误),因此所有直接了当的工具都需要一些额外的设置。例如,云供应商监控解决方案(如AWS CloudWatch,谷歌Stackdriver)将立即告诉你关于硬件度量但对内部应用程序的行为却无可奉告。在另一端,基于日志的解决方案如Elasticsearch默认情况下缺少hardware view。解决方案是用缺少的指标来增加您的选择,例如,一个流行的选择是将应用程序日志发送到Elastic stack,并配置一些额外的代理(如Beat)来共享与硬件相关的信息以获得完整的画面。 +实现高级功能需要冗长的设置或购买商业产品如datadog,NewRelic和相似产品。不幸的是,即使是基本的实现也不像在公园散步那么简单,因为一些度量指标是硬件相关的(CPU),而其他的则在node进程内(内部错误),因此所有直接了当的工具都需要一些额外的设置。例如,云供应商监控解决方案(如AWS CloudWatch,谷歌Stackdriver)将立即告诉你关于硬件度量,但对内部应用程序的行为却无可奉告。在另一端,基于日志的解决方案如Elasticsearch默认情况下缺少hardware view。解决方案是用缺少的指标来增加您的选择,例如,一个流行的选择是将应用程序日志发送到Elastic stack,并配置一些额外的代理(如Beat)来共享与硬件相关的信息以获得完整的画面。 ### 博客引用: "我们对于promise有一个问题" -摘自博客 pouchdb.com, 对于关键字“node promises”,排名11 + 摘自博客 pouchdb.com, 对于关键字“node promises”,排名11 - > … 我们建议您为所有服务检测这些信号: + > … 我们建议您为所有服务监视这些信号: 错误率:因为错误是面向用户的,并且会立即影响您的客户。 响应时间:因为延迟直接影响您的客户和业务。 吞吐量:流量有助于您了解错误率增加和延迟的上下文。 diff --git a/sections/errorhandling/operationalvsprogrammererror.chinese.md b/sections/errorhandling/operationalvsprogrammererror.chinese.md index dd524b07b..a68f94151 100644 --- a/sections/errorhandling/operationalvsprogrammererror.chinese.md +++ b/sections/errorhandling/operationalvsprogrammererror.chinese.md @@ -2,7 +2,7 @@ ### 一段解释 -区分以下两种错误类型将最大限度地减少应用程序停机时间并帮助避免出现荒唐的错误: 操作型错误指的是您了解发生了什么情况及其影响的情形 – 例如, 由于连接问题而导致对某些 HTTP 服务的查询失败问题。另一方面, 程序型错误指的是您不知道原因, 有时是错误不知道来自何处的情况 – 可能是一些代码试图读取未定义的值或 DB 连接池泄漏内存。操作型错误相对容易处理 – 通常记录错误就足够了。当程序型错误出现,事情变得难以应付, 应用程序可能处于不一致状态, 你可以做的,没有什么比优雅的重新启动更好了。 +区分以下两种错误类型将最大限度地减少应用程序停机时间并帮助避免出现荒唐的错误: 操作型错误指的是您了解发生了什么情况及其影响的情形 – 例如, 由于连接问题而导致对某些 HTTP 服务的查询失败问题。另一方面, 程序型错误指的是您不知道原因, 有时是错误不知道来自何处的情况 – 可能是一些代码试图读取未定义的值或 DB 连接池内存泄漏。操作型错误相对容易处理 – 通常记录错误就足够了。当程序型错误出现,事情变得难以应付, 应用程序可能处于不一致状态, 你可以做的,没有什么比优雅的重新启动更好了。 @@ -34,13 +34,13 @@ throw new appError(errorManagement.commonErrors.InvalidInput, "Describe here wha ### 博客引用: "不伴随着创建一些未定义的脆性状态,没有安全的方式可以离开" 摘自Node.JS官方文档 - > …在 JavaScript 中, throw的工作性质, 没有泄漏引用, 或者创建一些其他类型的未定义的脆性状态,几乎没有任何方法可以安全地 "在你离开的地方重新捡起"。对引发的错误进行响应的最安全方法是关闭进程。当然, 在普通的 web 服务器中, 您可能会打开许多连接, 并且由于其他人触发了错误而突然关闭这些连接是不合理的。更好的方法是向触发错误的请求发送错误响应, 同时让其他人在正常时间内完成, 并停止侦听该工作人员中的新请求。 + > …在 JavaScript 中, throw的工作性质, 几乎没有任何方法可以安全地"在你离开的地方重新捡起",没有泄漏引用, 或者创建一些其他形式的未定义的脆性状态,。对引发的错误进行响应的最安全方法是关闭进程。当然, 在普通的 web 服务器中, 您可能会打开许多连接, 并且由于其他人触发了错误而突然关闭这些连接是不合理的。更好的方法是向触发错误的请求发送错误响应, 同时让其他人在正常时间内完成, 并停止侦听该工作人员中的新请求。 ### 博客引用: "否则,您置您应用的状态于风险之中" - 摘自博客 debugable.com, 对于关键字“Node.JS uncaught exception”排名第3 + 摘自博客 debugable.com, 对于关键字“Node.JS uncaught exception”排名第3 - > …所以, 除非你真的知道你在做什么, 否则你应该在收到一个 "uncaughtException" 异常事件之后, 对你的服务进行一次优雅的重新启动。否则, 您应用的状态, 或和第三方库的状态变得不一致, 都被置于风险之中,导致各种荒唐的错误… + > …所以, 除非你真的知道你在做什么, 否则你应该在收到一个"uncaughtException"异常事件之后, 对你的服务进行一次优雅的重新启动。否则, 您应用的状态, 或和第三方库的状态变得不一致, 都被置于风险之中,导致各种荒唐的错误… ### 博客引用: "对于错误处理,有三种学院派想法" 摘自博客: JS Recipes diff --git a/sections/errorhandling/shuttingtheprocess.chinese.md b/sections/errorhandling/shuttingtheprocess.chinese.md index 45e17af0b..5de0faaba 100644 --- a/sections/errorhandling/shuttingtheprocess.chinese.md +++ b/sections/errorhandling/shuttingtheprocess.chinese.md @@ -1,9 +1,9 @@ -# 特殊情况产生时,优雅地停掉服务 +# 特殊情况产生时,优雅地退出服务 ### 一段解释 -在您的代码的某个地方,当一个错误抛出的时候,错误处理对象负责决定如何进行时 – 如果错误是可信的(即操作型错误,在最佳实践# 3了解进一步的解释),写入日志文件可能是足够的。如果错误不熟悉,事情就变得棘手了 – 这意味着某些组件可能处于故障状态,所有将来的请求都可能失败。例如,假设一个单例(singleton)的、有状态的令牌发行者服务抛出异常并失去它的状态 — 从现在起,它可能会出现意外行为并导致所有请求失败。在这种情况下,杀进程,使用“重启”的工具(像Forever,PM2,等等)重新开始。 +在您的代码的某个地方,当一个错误抛出的时候,错误处理对象负责决定如何进行时 – 如果错误是可信的(即操作型错误,在最佳实践#3了解进一步的解释),写入日志文件可能是足够的。如果错误不熟悉,事情就变得棘手了 – 这意味着某些组件可能处于故障状态,所有将来的请求都可能失败。例如,假设一个单例(singleton)的,有状态的令牌发行者服务抛出异常并失去它的状态 — 从现在起,它可能会出现意外行为并导致所有请求失败。在这种情况下,杀进程,使用“重启”的工具(像Forever,PM2,等等)重新开始。 diff --git a/sections/errorhandling/testingerrorflows.chinese.md b/sections/errorhandling/testingerrorflows.chinese.md index acb26a02f..eadd073e3 100644 --- a/sections/errorhandling/testingerrorflows.chinese.md +++ b/sections/errorhandling/testingerrorflows.chinese.md @@ -3,7 +3,7 @@ ### 一段解释 -测试‘正确’路径并不比测试失败更好。良好的测试代码覆盖率要求测试异常路径。否则,异常确实处理正确是不可信的。每个单元测试框架,如Mocha和Chai,都支持异常测试(请看下面的代码示例)。如果您觉得测试每个内部函数和异常都很乏味,那么您可以只测试REST API HTTP错误。 +测试‘正确’路径并不比测试失败更好。良好的测试代码覆盖率要求测试异常路径。否则,异常确实被处理正确是不可信的。每个单元测试框架,如[Mocha](https://mochajs.org/) & [Chai](http://chaijs.com/),都支持异常测试(请看下面的代码示例)。如果您觉得测试每个内部函数和异常都很乏味,那么您可以只测试REST API HTTP错误。 diff --git a/sections/errorhandling/usematurelogger.chinese.md b/sections/errorhandling/usematurelogger.chinese.md index 2150d2528..1dd751119 100644 --- a/sections/errorhandling/usematurelogger.chinese.md +++ b/sections/errorhandling/usematurelogger.chinese.md @@ -2,8 +2,7 @@ ### 一段解释 -我们都特别喜欢(loovve)console.log,但显而易见地,对于严肃的项目, 有信誉和持久的Logger是必需的,比如[Winston][winston], [Bunyan][bunyan] (非常流行) or [Pino][pino](专注于性能的新库)。一套实践和工具将有助于更快速地解释错误 – (1) 使用不同的级别(debug, info, error)频繁地log,(2) 在记录日志时, 以 JSON 对象的方式提供上下文信息, 请参见下面的示例。(3) 使用日志查询 API (在大多数logger中内置) 或日志查看程序软件监视和筛选日志 -(4) 使用操作智能工具 (如 Splunk) 为操作团队公开和管理日志语句。 +我们都特别喜欢(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 @@ -14,12 +13,12 @@ ```javascript //您的集中式logger对象 var logger = new winston.Logger({ - level: 'info', - transports: [ - new (winston.transports.Console)(), - new (winston.transports.File)({ filename: 'somefile.log' }) - ] - }); + 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' }); @@ -30,8 +29,12 @@ logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', ```javascript var options = { - from: new Date - 24 * 60 * 60 * 1000, until: new Date, limit: 10, start: 0, - order: 'desc', fields: ['message'] + from: new Date - 24 * 60 * 60 * 1000, + until: new Date, + limit: 10, + start: 0, + order: 'desc', + fields: ['message'] }; diff --git a/sections/errorhandling/useonlythebuiltinerror.chinese.md b/sections/errorhandling/useonlythebuiltinerror.chinese.md index e84c2dd12..0ec2218c3 100644 --- a/sections/errorhandling/useonlythebuiltinerror.chinese.md +++ b/sections/errorhandling/useonlythebuiltinerror.chinese.md @@ -23,7 +23,7 @@ myEmitter.emit('error', new Error('whoops!')); //从promise抛出错误 return new promise(function (resolve, reject) { - Return DAL.getProduct(productToAdd.id).then((existingProduct) =>{ + Return DAL.getProduct(productToAdd.id).then((existingProduct) => { if(existingProduct != null) reject(new Error("Why fooling us and trying to add an existing product?")); @@ -67,9 +67,9 @@ if(user == null) ### 博客引用: "从Error对象继承不会增加太多的值" 摘自博客 machadogj - > …我对Error类的一个问题是不太容易扩展。当然, 您可以继承该类并创建自己的Error类, 如 HttpError、DbError 等。然而, 这需要时间, 并且不会增加太多的价值, 除非你是在做一些关于类型的事情。有时, 您只想添加一条消息, 并保留内部错误, 有时您可能希望使用参数扩展该错误, 等等… + > …我对Error类的一个问题是不太容易扩展。当然, 您可以继承该类并创建自己的Error类, 如HttpError、DbError等。然而, 这需要时间, 并且不会增加太多的价值, 除非你是在做一些关于类型的事情。有时, 您只想添加一条消息, 并保留内部错误, 有时您可能希望使用参数扩展该错误, 等等… ### 博客引用: "所有由node.js引发的 JavaScript 和系统错误继承自Error对象" 摘自 Node.JS 官方文档 - > …所有由node.js引发的 JavaScript 和系统错误继承自,或是标准 JavaScript 错误类的实例, 这保证至少提供了该类的可用属性。一个通用的 JavaScript 错误对象, 它不表示为什么发生错误的任何特定环境。错误对象捕获一个 "stack trace", 详细说明了错误被实例化的代码中的点, 并可能提供错误的文本描述。由node.js生成的所有错误, 包括所有的系统和 JavaScript 错误, 都将是Errir类的实例, 或继承自Error类… + > …所有由node.js引发的JavaScript和系统错误继承自,或是JavaScript标准错误类的实例, 这保证至少提供了该类的可用属性。一个通用的JavaScript错误对象, 它不表示错误为什么发生的任何特定环境。错误对象捕获一个"stack trace", 详细说明了错误被实例化时在代码中的点, 并可能提供错误的文本描述。由node.js生成的所有错误, 包括所有的系统和JavaScript错误, 都将是Error类的实例, 或继承自Error类… From 1c9af71dc4c182e60f7a8450563eef75be3f29ab Mon Sep 17 00:00:00 2001 From: jin jing Date: Sat, 13 Jan 2018 11:33:31 +0800 Subject: [PATCH 63/75] [Chinese-translation]review and make some changes. --- sections/production/apmproducts.chinese.md | 2 +- .../production/assigntransactionid.chinese.md | 17 ++++--- sections/production/bestateless.chinese.md | 11 +++-- .../production/delegatetoproxy.chinese.md | 16 ++++--- sections/production/frontendout.chinese.md | 13 +++--- sections/production/guardprocess.chinese.md | 14 +++--- .../production/lockdependencies.chinese.md | 10 ++--- sections/production/measurememory.chinese.md | 16 +++---- sections/production/monitoring.chinese.md | 44 ++++++++++--------- sections/production/productoncode.chinese.md | 15 +++---- sections/production/setnodeenv.chinese.md | 18 ++++---- sections/production/smartlogging.chinese.md | 31 +++++++------ sections/production/utilizecpu.chinese.md | 22 +++++----- 13 files changed, 125 insertions(+), 104 deletions(-) diff --git a/sections/production/apmproducts.chinese.md b/sections/production/apmproducts.chinese.md index 007ccdcf5..ebe06b011 100644 --- a/sections/production/apmproducts.chinese.md +++ b/sections/production/apmproducts.chinese.md @@ -5,7 +5,7 @@ ### 一段解释 -APM, 应用程序性能监视指的是一个产品系列, 目的是从端到端,也从客户的角度监控应用程序的性能。虽然传统的监控解决方案侧重于异常和独立的技术指标 (例如错误跟踪、检测慢速服务器端点等), 在现实世界中, 我们的应用程序可能会在没有任何代码异常的情况下让用户使用起来感到失望, 例如, 如果某些中间件服务执行得非常慢。APM 产品从端到端检测用户体验, 例如, 给定一个包含前端 UI 和多个分布式服务的系统 – 一些 APM 产品可以告诉您, 一个跨过多个层的事务的速度有多快。它可以判断用户体验是否可靠, 并指出问题所在。这种诱人的产品通常有一个相对较高的价格标签, 因此, 对于需要超越一般的监测的,大规模的和复杂的产品, 它们是值得推荐的。 +APM(应用程序性能监视)指的是一个产品系列, 目的是从端到端,也从客户的角度监控应用程序的性能。虽然传统的监控解决方案侧重于异常和独立的技术指标 (例如错误跟踪、检测慢速服务器端点等), 在现实世界中, 我们的应用程序可能会在没有任何代码异常的情况下让用户使用起来感到失望, 例如, 如果某些中间件服务执行得非常慢。APM 产品从端到端检测用户体验, 例如, 给定一个包含前端 UI 和多个分布式服务的系统 – 一些 APM 产品可以告诉您, 一个跨过多个层的事务的速度有多快。它可以判断用户体验是否可靠, 并指出问题所在。这种诱人的产品通常有一个相对较高的价格标签, 因此, 对于需要超越一般的监测的,大规模的和复杂的产品, 它们是值得推荐的。

diff --git a/sections/production/assigntransactionid.chinese.md b/sections/production/assigntransactionid.chinese.md index 7469931e7..e0319aa7b 100644 --- a/sections/production/assigntransactionid.chinese.md +++ b/sections/production/assigntransactionid.chinese.md @@ -15,21 +15,24 @@ ```javascript //当接收到一个新的要求,开始一个新的隔离的上下文和设置一个事务transaction id。下面的例子是使用NPM库continuation-local-storage去隔离请求 -var createNamespace = require('continuation-local-storage').createNamespace; +const { createNamespace } = require('continuation-local-storage'); var session = createNamespace('my session'); - router.get('/:id', (req, res, next) => { + +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'); -} -//Now any other service or components can have access to the contextual, per-request, data +}); + +//现在, 任何其他服务或组件都可以访问上下文、每个请求、数据 class someService { getById(id) { logger.info(“Starting now to get something by Id”); - //other logic comes here + //其它逻辑 } } -//Logger can now append transaction-id to each entry, so that entries from the same request will have the same value + +//Logger现在可以将事务 id 追加到每个条目, 以便同一请求中的项将具有相同的值 class logger{ info (message) {console.log(`${message} ${session.get('transactionId')}`);} @@ -38,6 +41,6 @@ class logger{

-### What Other Bloggers Say +### 其他博主说什么 摘自博客 [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 index 8f0a484de..045a4ad46 100644 --- a/sections/production/bestateless.chinese.md +++ b/sections/production/bestateless.chinese.md @@ -1,4 +1,4 @@ -# 保存无状态,几乎每天都要停掉服务器 +# 保存无状态,几乎每天停掉服务器

@@ -7,8 +7,8 @@ 你曾经有没有遇到一类严重的线上问题,比如一个服务器丢失了一些配置或数据?这可能是由于对于不属于部署部分的本地资源的一些不必要的依赖。许多成功的产品对待服务器就像凤凰鸟–它周期性地死亡和重生不带来任何损伤。换句话说,服务器只是一个硬件,执行你的代码一段时间后,可以更换。 这个方法: -1. 允许动态添加和删除服务器,无任何负面影响; -2. 简化了维护,因为它使我们不必费精力对每个服务器状态进行评估。 +- 允许动态添加和删除服务器,无任何负面影响; +- 简化了维护,因为它使我们不必费精力对每个服务器状态进行评估。

@@ -17,15 +17,18 @@ ```javascript //典型错误1: 保存上传文件在本地服务器上 -var multer = require('multer') //express middleware for fetching uploads +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} ``` diff --git a/sections/production/delegatetoproxy.chinese.md b/sections/production/delegatetoproxy.chinese.md index 0b0eb7dd5..7c3c210d5 100644 --- a/sections/production/delegatetoproxy.chinese.md +++ b/sections/production/delegatetoproxy.chinese.md @@ -5,31 +5,35 @@ ### 一段解释 -这是非常诱人的去过度使用(cargo-cult)Express和使用其丰富的中间件提供网络相关的任务, 如服务静态文件, gzip 编码, throttling requests, SSL termination等。由于它的单线程模型将使 CPU 长时间处于忙碌状态 (请记住, node的执行模型针对短任务或异步 IO 相关任务进行了优化), 因此这是一个性能消耗。一个更好的方法是使用一个专注于处理网络任务的工具 – 最流行的是 nginx 和 HAproxy, 也被最大的云供应商使用, 以减轻在node.js进程上的面临的负载。 +这是非常诱人的 —— 去过度使用(cargo-cult)Express和使用其丰富的中间件提供网络相关的任务, 如服务静态文件, gzip 编码, throttling requests, SSL termination等。由于它的单线程模型将使 CPU 长时间处于忙碌状态 (请记住, node的执行模型针对短任务或异步 IO 相关任务进行了优化), 因此这是一个性能消耗。一个更好的方法是使用一个专注于处理网络任务的工具 – 最流行的是 nginx 和 HAproxy, 也被最大的云供应商使用, 以减轻在node.js进程上的面临的负载。

-### 代码示例 – 说明 +### 代码示例 – 使用 nginx 压缩服务器响应 -```javascript +``` +# 配置 gzip 压缩 gzip on; -#defining gzip compression gzip_comp_level 6; gzip_vary on; + +# 配置 upstream upstream myApplication { server 127.0.0.1:3000; server 127.0.0.1:3001; keepalive 64; } -#defining web server +#定义 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 + + # 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; diff --git a/sections/production/frontendout.chinese.md b/sections/production/frontendout.chinese.md index 5efe1db72..f904829c9 100644 --- a/sections/production/frontendout.chinese.md +++ b/sections/production/frontendout.chinese.md @@ -9,21 +9,24 @@ 您的最佳解决方案可能是以下形式之一: 1. 反向代理 – 您的静态文件将位于您的node应用的旁边, 只有对静态文件文件夹的请求才会由位于您的node应用前面的代理 (如 nginx) 提供服务。使用这种方法, 您的node应用负责部署静态文件, 而不是为它们提供服务。你的前端的同事会喜欢这种方法, 因为它可以防止 cross-origin-requests 的前端请求。 -2. 云存储 – 您的静态文件将不会是您的node应用内容的一部分, 否则他们将被上传到服务, 如 AWS S3, Azure BlobStorage, 或其他类似的服务, 这些服务为这个任务而生。使用这种方法, 您的node应用即不负责部署静态文件, 也不为它们服务, 因此, 在node和前端资源之间完全解耦, 这是由不同的团队处理。 +2. 云存储 – 您的静态文件将不会是您的node应用内容的一部分, 他们将被上传到服务, 如 AWS S3, Azure BlobStorage, 或其他类似的服务, 这些服务为这个任务而生。使用这种方法, 您的node应用即不负责部署静态文件, 也不为它们服务, 因此, 在node和前端资源之间完全解耦, 这是由不同的团队处理。

### 代码示例: 对于静态文件,典型的nginx配置 -```javascript +``` +# configure gzip compression gzip on; -#defining gzip compression keepalive 64; -}#defining web server + +# defining web server server { listen 80; -listen 443 ssl;#handling static content +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; diff --git a/sections/production/guardprocess.chinese.md b/sections/production/guardprocess.chinese.md index 842344c66..52ec578a9 100644 --- a/sections/production/guardprocess.chinese.md +++ b/sections/production/guardprocess.chinese.md @@ -1,19 +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进程并在出现故障时重新启动。简单地说, 对于那些小应用和不使用容器的应用 – 像这样的工具 [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的功能比如向代码发送信号。其他选择可能会避免不必要的层。总而言之,没有一个解决方案适合所有人,但了解这些选择是最重要的。

-### 其他博客作者怎么说? +### 其它博主说了什么 -* 来自[快速正产最佳实践](https://expressjs.com/en/advanced/best-practice-performance.html): +* 来自[Express 生成最佳实践](https://expressjs.com/en/advanced/best-practice-performance.html): > ... 在开发中,您只需从命令行使用node.js或类似的东西启动您的应用程序。**但是在生产中这样做是一种灾难。 如果应用程序崩溃,它将掉线**,直到您重新启动它。要确保应用程序在崩溃时重新启动,请使用进程管理器。流程管理器是便于部署的应用程序的“容器”,提供高可用性,并使您能够在运行时管理应用程序。 -* 从中篇博客文章中 [了解节点集群](https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.cssigr5z3): -> ...了解Docker-Land中的NodeJS集群“Docker容器是流线型的轻量级虚拟环境,旨在将流程简化为最低限度。管理和协调自己资源的流程不再有价值。**相反,像Kubernetes,Mesos和Cattle这样的管理层已经普及了这些资源应该在整个基础设施范围进行管理的概念**。CPU和内存资源由“调度器”分配,网络资源由堆栈提供的负载均衡器管理。 +* 摘自 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 index d9e9d7896..82633c03b 100644 --- a/sections/production/lockdependencies.chinese.md +++ b/sections/production/lockdependencies.chinese.md @@ -3,21 +3,21 @@

-### 段落解释 +### 一段解释 -您的代码依赖于许多外部包,假设它“需要”和使用momentjs-2.1.4,默认情况下,当布署到生产中时,NPM可能会获得momentjs 2.1.5,但不幸的是,这将带来一些新的bug。使用NPM配置文件和设置–save–exact=true指示NPM去完成安装,以便下次运行“NPM install”(在生产或在Docker容器中,您计划将其用于测试)时,将获取相同的依赖版本。另一种可选择受欢迎的方法是使用一个shrinkwrap文件(很容易使用NPM生成)指出应该安装哪些包和版本,这样就不需要环境来获取新版本了。 +您的代码依赖于许多外部包,假设它“需要”和使用momentjs-2.1.4,默认情况下,当布署到生产中时,NPM可能会获得momentjs 2.1.5,但不幸的是,这将带来一些新的bug。使用NPM配置文件和设置 ```–save-exact=true``` 指示NPM去完成安装,以便下次运行```npm install```(在生产或在Docker容器中,您计划将其用于测试)时,将获取相同的依赖版本。另一种可选择受欢迎的方法是使用一个shrinkwrap文件(很容易使用NPM生成)指出应该安装哪些包和版本,这样就不需要环境来获取新版本了。 -** *更新:* * 在NPM5中,使用shrinkwrap命令依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。 +** *更新:* * 在NPM5中,使用.shrinkwrap依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。

### 代码示例: .npmrc文件指示NPM使用精确的版本 -```javascript -//save this as .npmrc file on the project directory +``` +// 在项目目录上保存这个为.npmrc 文件 save-exact:true ``` diff --git a/sections/production/measurememory.chinese.md b/sections/production/measurememory.chinese.md index 5da8a84b2..c23f81fc3 100644 --- a/sections/production/measurememory.chinese.md +++ b/sections/production/measurememory.chinese.md @@ -5,20 +5,20 @@ ### 段落解释 -在一个完美的开发过程中, Web开发人员不应该处理内存泄漏问题。 实际上,内存问题是一个必须了解的Node已知的问题。 首先,内存使用必须不断监视.在开发和小型生产站点,您可以使用Linux命令或NPM工具和库(如节点检查器和MemWatch)来手动测量。 这个活动指南的主要缺点是它们需要一个人进行积极的监控 - 对于正规的生产场所来说,使用鲁棒性监控工具是非常重要的。 (AWS CloudWatch,DataDog或任何类似的主动系统),当泄漏发生时提醒。 防止泄漏的开发指南也很少:避免将数据存储在全局级别,使用流数据的动态大小,使用let和const限制变量范围。 +在一个完美的开发过程中, 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://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): -> ... “虽然这个例子导致了明显的结果,但这个过程总是一样的:用一些时间和相当数量的内存分配创建堆转储,比较几个转储,以找出正在增长的东西。” +* 摘自博客 [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的内存。这是预期的行为,垃圾收集是一个代价很高的操作。 +* 摘自博客 [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 index 71e6d6475..ac23b193f 100644 --- a/sections/production/monitoring.chinese.md +++ b/sections/production/monitoring.chinese.md @@ -1,35 +1,39 @@ -监控 +# 监控! +

-解释 -
-基本来说,监控意味着在生产环境中当发生意外时你能够很容易识别。比如,通过电子邮件或Slack获得通知。 -最大的难题是选择既能满足你的需求又不会破坏储库的比较合适的工具集。我建议,首先定义必须监视的一组核心指标,来保证CPU,服务器RAM,Node进程RAM(小于1.4GB),最后一分钟的错误数量,进程重启次数,平均响应时间在正常状态。然后去看看你可能喜欢的一些高级功能,并添加到你的愿望清单。 -一些高级监控功能的例子:DB分析,跨服务测量(即测量业务事务),前端集成,将原始数据展示给自定义BI客户端,延缓通知等等。 -要实现高级功能需要冗长的设置或购买诸如Datadog,newrelic之类的商业产品。不幸的是,实现基本功能也并不容易,因为一些测量标准是与硬件相关的(CPU),而其他标准是在node进程内(内部错误)因此所有简单的工具都需要一些额外的设置。例如,云供应商监控解决方案(例如[AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/))能立即告诉您硬件度量标准,但不涉及内部应用程序行为。 +### 一段解释 + +基本来说,当在生产环境中发生意外时,监控意味着你能够很*容易*识别它们。比如,通过电子邮件或Slack获得通知。挑战在于选择既能满足你的需求又不会破坏防护的合适的工具集。我建议, 首先定义一组核心的度量标准, 这些指标必须被监视, 以确保健康状态 – CPU, 服务器RAM, Node进程RAM(小于1.4GB),最后一分钟的错误数量,进程重启次数,平均响应时间。然后去看看你可能喜欢的一些高级功能,并添加到你的愿望清单。一些高级监控功能的例子:DB分析,跨服务测量(即测量业务事务),前端集成,将原始数据展示给自定义BI客户端,Slack 通知等等。 -另一方面,基于日志的解决方案(如ElasticSearch)默认缺少硬件视图。解决方案是通过缺少的指标来增加您的选择,例如,流行的选择是将应用程序日志发送到Elastic堆栈并配置一些额外的代理(例如Beat)来共享硬件相关信息以获得完整的图像。 +要实现高级功能需要冗长的设置或购买诸如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默认仪表板。很难提取应用内指标 + ![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) +

-###监控示例:StackDriver默认仪表板。很难提取应用内指标 -
+### 监控示例:StackDriver默认仪表板。很难提取应用内指标 + ![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) +

-###监控示例:Grafana作为可视化原始数据的UI层 -
+ +### 监控示例:Grafana作为可视化原始数据的UI层 + + ![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) +

-###其他博客观点 - [Rising Stack]博客: +### 其他博主说了什么 + 摘自博客 [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): -> 我们建议您监听所有服务的这些信号: -> 错误率:因为错误是面向用户的,并且会立即影响您的客户。 +> ...我们建议您为所有服务监听这些信号: +> 错误率:因为错误是用户面对的,并立即会影响您的客户。 > 响应时间:因为延迟会直接影响您的客户和业务。 -> 吞吐量:流量可帮助您了解增加的错误率和延迟的情况。 -> 饱和度:饱和度告诉你你的服务有多满。如果CPU使用率是90%,您的系统可以处理更多的流量吗? +> 吞吐量:流量可帮助您了解增加的错误率和延迟的上下文。 +> 饱和度:饱和度告诉你你的服务有多“满”。如果CPU使用率是90%,您的系统可以处理更多的流量吗?... diff --git a/sections/production/productoncode.chinese.md b/sections/production/productoncode.chinese.md index 2ec9634ad..c5b97d24b 100644 --- a/sections/production/productoncode.chinese.md +++ b/sections/production/productoncode.chinese.md @@ -3,16 +3,15 @@

-### 段落解释 +### 一段解释 以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性: * 十二因素指南 — 熟悉[12因素](https://12factor.net/)指南 -* 无状态 — 在一个特定的web服务器上不保存本地数据(请参阅独立项目-“Be Stateless”) -* 高速缓存 — 大量使用缓存,但不会因为缓存不匹配而失败 +* 无状态 — 在一个特定的web服务器上不保存本地数据(请参阅相关条目 - “Be Stateless”) +* 高速缓存 — 大量使用缓存,但不会因为缓存不匹配而产生错误 * 测试内存 — 测量内存的使用和泄漏,是作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务 -* 命名函数 — 将匿名函数(即内联callbabk)的使用最小化,作为一个典型的内存分析器为每个方法名提供内存使用 -* 使用CI工具 — 在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用- trace-sync-io来识别用了同步的api代 -码(而不是异步版本) -* 明确的日志 — 包括在每个日志语句中希望用json格式记录上下文信息,以便于日志聚合工具,如Elastic可以在这些属性上搜索(请参阅独立项目 — 使 使用智能日志增加可见性)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅 — “Include Transaction-ID”) -* 错误管理 — 错误处理是Node.js生产站点的致命弱点——许多节点进程由于小错误而崩溃,然而其他节点则会在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的,在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) \ No newline at end of file +* 命名函数 — 将匿名函数(例如,内联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 index 1be86e700..a89061df5 100644 --- a/sections/production/setnodeenv.chinese.md +++ b/sections/production/setnodeenv.chinese.md @@ -3,7 +3,7 @@

-### 段落解释 +### 一段解释 进程的环境变量是一组键值对,可用于任何运行程序,通常用于配置。虽然可以使用其他任何变量,但Node鼓励使用一个名为NODE_ENV的变量来标记我们是否正在开发。这一决定允许组件在开发过程中能提供更好的诊断,例如禁用缓存或发出冗长的日志语句。任何现代部署工具 — Chef、Puppet、CloudFormation等 — 在部署时都支持设置环境变量。 @@ -13,8 +13,9 @@ ### 代码实例:配置和读取NODE_ENV环境变量 ```javascript -//Using a command line, initializing node process and setting before environment variables -Set NODE_ENV=development&& set otherVariable=someValue&& node +//在启动node进程前,在bash中设置环境变量 +$ NODE_ENV=development +$ node //使用代码读取环境变量 If(process.env.NODE_ENV === “production”) @@ -24,14 +25,13 @@ If(process.env.NODE_ENV === “production”)

-### 其他博客作者说什么 -来自这篇博客[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来生成请求node.js的数量可以处理大约三分之二的跳转,尽管CPU的使用率会略有下降。 *让我强调一下:设置NODE_ENV去开发可以让你的应用程序快3倍!* +### 其他博主说了什么 +摘自这篇博客[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倍!* -![Set NODE_ENV = production](/assets/images/setnodeenv1.png "Set NODE_ENV = production") +![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") + -

diff --git a/sections/production/smartlogging.chinese.md b/sections/production/smartlogging.chinese.md index d0941d7a9..2b51ca8dc 100644 --- a/sections/production/smartlogging.chinese.md +++ b/sections/production/smartlogging.chinese.md @@ -1,33 +1,38 @@ -# 使用智能日志使你的应用程序变得透明 +# 使用智能日志使你的应用程序变得清晰

-### 一个段落解释 +### 一段解释 + +无论如何,您要打印日志,显然需要一些可以在其中跟踪错误和核心指标的接口来包装生产环境信息(例如,每小时发生了多少错误,最慢的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使用, 在过去一小时内有多少新用户选择, 以及任何其他有助于管理和改进我们应用程序的指标。 -无论如何,您要打印日志语句,显然需要一些可以在其中跟踪错误和核心指标的接口来包装生产信息(在最慢的API端点,每小时发生了多少错误)为什么不在健壮的日志框架中进行一些适度的尝试呢?要实现这一目标,需要在三个步骤上做出深思熟虑的决定: -**1. 智能日志** -在最基本的情况下,您需要使用像[Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan)这样有信誉的日志库,在每个事务开始和结束时编写有意义的信息。还可以考虑将日志语句格式化为JSON,并提供所有上下文属性(如用户id、操作类型等)。这样操作团队就可以在这些字段上操作。在每个日志行中还包含一个唯一的事务ID,因为更多的信息引用下面的例子“写事务ID到日志”。最后要考虑的一点还包括一个代理,它记录系统资源,如内存和CPU,比如弹性节拍。 -**2. 智能聚合** - 一旦您在服务器文件系统中有了全面的信息,就应该定期将这些信息推送到一个聚合、设施和可视化数据的系统中。例如,弹性堆栈是一种流行的、自由的选择,它提供所有组件来聚合和可视化数据。许多商业产品提供了类似的功能,只是它们大大减少了安装时间,不需要主机托管。 -**3. 智能可视化** -现在,这些信息是聚合和搜索的,只有通过轻松搜索日志的能力才能满足这一要求,但如果不编码或花费大量的精力,这就会变得更加困难。

-### 可视化示例:Kibana(弹性栈的一部分)促进了对日志内容的高级搜索 +### 可视化示例: Kibana(Elastic stack的一部分)促进了对日志内容的高级搜索 ![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")

-### 可视化示例:Kibana(弹性堆栈的一部分)基于日志来可视化数据 +### 可视化示例: Kibana(Elastic stack的一部分)基于日志来可视化数据 ![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")

-### 博客:记录器的要求 -来自博客 [Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/): +### 博客应用: Logger的需求 +摘自博客 [Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/): + > 让我们识别一些需求(对于一个日志记录器来说): -> 1. 时间戳每个日志线。这个很好解释,您应该能够判断每个日志条目出现的时间。 -> 2. 日志格式应该很容易被人类和机器消化。 -> 3. 允许多个可配置的目标流。例如,您可能在一个文件中写入跟踪日志,但是当遇到错误时,将其写入相同的文件,然后进入错误文件并同时发送电子邮件。 +> 1. 每条日志对应一个时间戳。这个很好解释 – 您应该能够判断每个日志条目出现的时间。 +> 2. 日志格式应该很容易被人和机器消化理解。 +> 3. 允许多个可配置的目标流。例如,您可能在一个文件中写入trace日志,但是当遇到错误时,将其写入相同的文件,然后写入错误日志文件并同时发送电子邮件...

diff --git a/sections/production/utilizecpu.chinese.md b/sections/production/utilizecpu.chinese.md index 793b90d29..8fb0072a1 100644 --- a/sections/production/utilizecpu.chinese.md +++ b/sections/production/utilizecpu.chinese.md @@ -3,26 +3,26 @@

-### 段落解释 +### 一段解释 -nodejs的基本形式可能不会让人感到意外,是一个运行于单进程单线程单个CPU的服务器引擎。负担一个强大的硬件需要用4个或8个CPU,只使用一个听起来是不可思议的,对吗?适合中型应用程序最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和流程之间的路由请求产生一个循环样式的过程。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给集群模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用程序。对于那些高级的用例,考虑使用自定义部署脚本复制节点流程,并使用像nginx -这样的特殊工具进行平衡,或者使用像AWS、ECS或kubernet这样的容器引擎,这些工具具有放置和复制进程的高级特性。 +这应该不会让人感到意外, 在其基本形式上,Node运行在单进程,单线程,单个CPU上。购买了一个强大的包含4个或8个CPU的硬件,只使用一个听起来是不可思议的,对吗?适合中型应用最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和路由请求产生一个进程,进程之间以round-robin的形式存在。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给cluster模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用。对于那些高级的用例,考虑使用自定义部署脚本复制NODE进程,并使用像nginx +这样的专门的工具进行负载均衡,或者使用像AWS ECS或Kubernetees这样的容器引擎,这些工具具有部署和复制进程的高级特性。

-### 比较:均衡使用Node的clustre和nginx +### 比较:使用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): -> ... 理论上第二种方法应该是效率最佳的,但在实际情况下,由于操作系统调度机制的难以捉摸,会使分发变得不稳定。我们遇到过这种情况:8个进程中的2个,分担了70%的负载... +### 其他博主说什么 +* 摘自[Node.JS documentation](https://nodejs.org/api/cluster.html#cluster_how_it_works): +> ... 理论上第二种方法, Node clusters,应该是性能最佳的。然而, 在实践中, 由于操作系统调度程序的反复无常, 分布往往非常不平衡。观察负载, 所有连接中,超过70%在两个进程中处理, 而总共有八个进程... -* 来自博客[StrongLoop](From the blog StrongLoop): -> ...通过Node的集群模块实现集群化。这使一个主进程能够产生工作进程,并在工作人员之间分配传入的连接。然而,与其直接使用这个模块,不如使用其中的一个工具自动完成它;例如,node-pm或cluster-service... +* 摘自博客[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的领域内进行操作。请记住,你的主进程将会工作几乎和你的工作进程一样多,并且有较少的请求率,然后其他的解决方案... \ No newline at end of file +* 摘自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 From 86434127f09ac164cb2a5a8c6d9e657d30624a73 Mon Sep 17 00:00:00 2001 From: jin jing Date: Sat, 13 Jan 2018 11:38:36 +0800 Subject: [PATCH 64/75] [Chinese-translation]format. --- sections/projectstructre/configguide.chinese.md | 1 + sections/projectstructre/thincomponents.chinese.md | 9 ++++++--- sections/projectstructre/wraputilitie.chinese.md | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sections/projectstructre/configguide.chinese.md b/sections/projectstructre/configguide.chinese.md index 9a9eb60a3..90bddc18c 100644 --- a/sections/projectstructre/configguide.chinese.md +++ b/sections/projectstructre/configguide.chinese.md @@ -8,6 +8,7 @@ 当我们处理配置参数时,常常会很慢并且很烦躁:(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))这些库可以满足这些要求中的许多要求。 +

### 代码示例 – 分层配置有助于查找条目和维护庞大的配置文件 diff --git a/sections/projectstructre/thincomponents.chinese.md b/sections/projectstructre/thincomponents.chinese.md index 0e9bb58a8..65a0cf3be 100644 --- a/sections/projectstructre/thincomponents.chinese.md +++ b/sections/projectstructre/thincomponents.chinese.md @@ -1,23 +1,26 @@ # 用组件来构造你的解决方案 +

### 一段解释 对于中型应用以上来说,按部就班的写在一起真是太糟糕了-当一个有很多依赖的大型的软件会导致我们理解起来非常困难并且导致我们的代码杂乱不堪。甚至像那些能够熟练地驯服野兽的聪明的设计师一样,他们在设计上花费大量的精力用来"模块化"代码,每一次改动都需要仔细的评估对于其他依赖对象的影响。构建小型项目的最终方法是:将整体的项目分享一个个不与其他组件共享文件的独立组件,每个组件由很少的文件组成(例如API、服务、数据访问、测试等),所以这是比较容易理解的。一些被称为"microservices"的架构,去理解"microservices"不是你必须遵守的规范而是一套原则是非常重要的。你可以将许多原则应用到一个成熟的微服务体系结构中,或者只采用少数几个原则。只要你把软件的复杂性保持在低水平,两者都是好的。您至少应该做的是在组件之间创建一个基本的边界,在项目根中为每个业务组件分配一个文件夹,并让它自己做到其他组件只允许通过它的公共接口或API来实现它的功能。这是让你的组件保持简单的基础,避免依赖关系,在你的应用程序成长后,为将来成熟的微服务铺平道路。 +

### 引用博客: "扩展需要整个应用的扩展" - 来自博客 MartinFowler.com + 摘自博客 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/wraputilitie.chinese.md b/sections/projectstructre/wraputilitie.chinese.md index b0fbd030a..5b99915f5 100644 --- a/sections/projectstructre/wraputilitie.chinese.md +++ b/sections/projectstructre/wraputilitie.chinese.md @@ -3,7 +3,7 @@

-### 段落解释 +### 一段解释 一旦你开始在不同的服务器上增加不同的组件并使用不同的服务器,这些服务器会消耗类似的工具,那么你应该开始管理依赖关系 - 你如何保留实用工具代码的一个副本,并让多个使用组件者使用和部署? 好吧,有一个这样的框架,它被称为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) From 1f5def29a5bf8d2180f17ff5b50f3c257981d1c9 Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 13:22:40 +0800 Subject: [PATCH 65/75] [Chinese-translation]fix error. --- README.chinese.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 28e14836b..8dfbbeaa1 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -85,7 +85,9 @@ **TL;DR:** 一个完美无瑕的配置安装应该确保 (a) 元素可以从文件中,也可以从环境变量中读取 (b) 密码排除在提交的代码之外 (c) 为了易于检索,配置是分级的。仅有几个包可以满足这样的条件,比如[nconf](https://www.npmjs.com/package/nconf) 和 [config](https://www.npmjs.com/package/config)。 **否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。 -🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.chinese.md) + +🔗 [**更多: 配置最佳实践**] +(/sections/projectstructre/configguide.chinese.md)


@@ -476,14 +478,14 @@ null == undefined // true

-## ![✔] 5.2. 使用智能日志增加透明度Increase transparency using smart logging +## ![✔] 5.2. 使用智能日志增加透明度 **TL;DR:** 日志可以是调试语句的一个不能说话的仓库,或者表述应用运行过程的一个漂亮仪表板的驱动。从第1天计划您的日志平台:如何收集、存储和分析日志,以确保所需信息(例如,错误率、通过服务和服务器等完成整个事务)都能被提取出来。 **否则:** 您最终像是面对一个黑盒,不知道发生了什么事情,然后你开始重新写日志语句添加额外的信息。 -🔗 [**更多: Increase transparency using smart logging**](/sections/production/smartlogging.chinese.md) +🔗 [**更多: 使用智能日志增加透明度**](/sections/production/smartlogging.chinese.md)

@@ -539,7 +541,7 @@ null == undefined // true **否则:** 您会发现,您正在执行许多“诊断部署” — 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。 -🔗 [**更多: 创建一个 ‘维护端点’ **](/sections/production/createmaintenanceendpoint.chinese.md) +🔗 [**更多: 创建一个 '维护端点'**](/sections/production/createmaintenanceendpoint.chinese.md)

@@ -598,7 +600,7 @@ null == undefined // true **否则:** 某个服务器上的故障将导致应用程序宕机,而不仅仅是停用故障机器。此外,由于依赖特定服务器,伸缩弹性会变得更具挑战性。 -🔗 [**Read More: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.chinese.md) +🔗 [**更多: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.chinese.md)

From db4e96655e83915d69497f85b53c424f0f12d585 Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 13:24:18 +0800 Subject: [PATCH 66/75] [Chinese-translation]fix error. --- README.chinese.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 8dfbbeaa1..5a7522cbc 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -86,9 +86,7 @@ **否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。 -🔗 [**更多: 配置最佳实践**] -(/sections/projectstructre/configguide.chinese.md) - +🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.md)


From 333c297109fac5b635c3dfad91ae18afbdfd57fd Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 13:28:26 +0800 Subject: [PATCH 67/75] [Chinese-translation]use right words. --- README.chinese.md | 2 +- sections/projectstructre/breakintcomponents.chinese.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 5a7522cbc..c9fa17b41 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -20,7 +20,7 @@ # 欢迎! 首先您应该知道的三件事情: **1. 当您读到这里,实际上您读了很多关于Node.JS的优秀文章 -** 这是对Node JS 最佳实践中排名最高的内容的总结和分享 -**2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。每天都有新的issue和PR被创建,以使这本在线书籍不断更新。我们很乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是提出绝妙的新想法。请查看我们的[milestones 这里](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open) +**2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。每天都有新的issue和PR被创建,以使这本在线书籍不断更新。我们很乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是提出绝妙的新想法。请查看我们的[milestones](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open) **3. 大部分的条目包含额外的信息 -** 大部分的最佳实践条目的旁边,您将发现 **🔗Read More** 链接,它将呈现给您示例代码,博客引用和更多信息 diff --git a/sections/projectstructre/breakintcomponents.chinese.md b/sections/projectstructre/breakintcomponents.chinese.md index 9704dd025..1da60edcc 100644 --- a/sections/projectstructre/breakintcomponents.chinese.md +++ b/sections/projectstructre/breakintcomponents.chinese.md @@ -26,11 +26,11 @@

- ### 好: 通过独立组件构建解决方案 + ### 推荐: 通过独立组件构建解决方案 ![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") From 94bd1a1cae5c97c563cbe9c68a65f3550454bbfe Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 13:37:53 +0800 Subject: [PATCH 68/75] [Chinese-translation]fix file name. --- .../{wraputilitie.chinese.md => wraputilities.chinese.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sections/projectstructre/{wraputilitie.chinese.md => wraputilities.chinese.md} (100%) diff --git a/sections/projectstructre/wraputilitie.chinese.md b/sections/projectstructre/wraputilities.chinese.md similarity index 100% rename from sections/projectstructre/wraputilitie.chinese.md rename to sections/projectstructre/wraputilities.chinese.md From db5a1505403772802327b9914d47c18d3a0fe270 Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 16:04:54 +0800 Subject: [PATCH 69/75] fix error. --- README.chinese.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index c9fa17b41..0d42a64cf 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -41,7 +41,7 @@ ## ![✔] 1.1 组件式构建你的解决方案 - **TL;DR:** 最坏的大型项目隐患就是维护一个庞大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。 + **TL;DR:** 最坏的大型项目的隐患就是维护一个庞大的,含有几百个依赖的代码库 - 当开发人员准备整合新的需求的时候,这样一个庞然大物势必减缓了开发效率。反之,把您的代码拆分成组件,每一个组件有它自己的文件夹和代码库,并且确保每一个组件小而简单。查看正确的项目结构的例子请访问下面的 ‘更多’ 链接。 **否则:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展 @@ -138,6 +138,7 @@ ## ![✔] 2.5 对API错误使用Swagger文档化 **TL;DR:** 让你的API调用者知道哪种错误会返回,这样他们就能完全的处理这些错误,而不至于系统崩溃。Swagger,REST API的文档框架,通常处理这类问题。 + **否则:** 任何API的客户端可能决定崩溃并重启,仅仅因为它收到一个不能处理的错误。注意:API的调用者可能是你(在微服务环境中非常典型)。 @@ -267,7 +268,7 @@ ## ![✔] 3.5 命名您的方法 -**TL;DR:** 命名所有的方法,包含闭包和回调。避免匿名方法。当剖析一个node应用的时候,这是特别有用的。命名所有的方法将会使您非常容易的理解内存快照中您正在查看的内容。 +**TL;DR:** 命名所有的方法,包含闭包和回调, 避免匿名方法。当剖析一个node应用的时候,这是特别有用的。命名所有的方法将会使您非常容易的理解内存快照中您正在查看的内容。 **否则:** 使用一个核心dump(内存快照)调试线上问题,会是一项非常挑战的事项,因为你注意到的严重内存泄漏问题极有可能产生于匿名的方法。 @@ -275,7 +276,7 @@ ## ![✔] 3.6 变量、常量、函数和类的命名约定 -**TL;DR:** 当命名变量和方法的时候,使用 ***lowerCamelCase*** , 当命名类的时候,使用***UpperCamelCase*** (首字母大写),对于常量,则***UPPERCASE***。这将帮助您轻松地区分普通变量/函数和需要实例化的类。使用描述性名称,但使它们尽量简短。 +**TL;DR:** 当命名变量和方法的时候,使用 ***lowerCamelCase*** ,当命名类的时候,使用 ***UpperCamelCase*** (首字母大写),对于常量,则 ***UPPERCASE*** 。这将帮助您轻松地区分普通变量/函数和需要实例化的类。使用描述性名称,但使它们尽量简短。 **否则:** JavaScript是世界上唯一一门不需要实例化,就可以直接调用构造函数("Class")的编码语言。因此,类和函数的构造函数由采用UpperCamelCase开始区分。 @@ -321,8 +322,7 @@ ## ![✔] 3.9 在文件夹上 require ,而不是直接在文件上 **TL;DR:** 当在一个文件夹中开发库/模块,放置一个文件index.js暴露模块的 -内部,这样每个消费者都会通过它。这将作为您模块的一个接口,并使 -未来的变化简单而不违反规则。 +内部,这样每个消费者都会通过它。这将作为您模块的一个接口,并使未来的变化简单而不违反规则。 **否则:** 更改文件内部结构或签名可能会破坏与客户端的接口。 @@ -367,7 +367,7 @@ null == undefined // true ## ![✔] 3.11 使用 Async Await, 避免回调 -**TL;DR:** Node 8 LTS现已全面支持异步等待。这是一种新的方式处理异步请求,取代回调和promise。Async-await是非阻塞的,它使异步代码看起来像是同步的。你可以给你的代码的最好的礼物是用async-await提供了一个更紧凑的,熟悉的,类似try catch的代码语法。 +**TL;DR:** Node 8 LTS现已全面支持异步等待。这是一种新的方式处理异步请求,取代回调和promise。Async-await是非阻塞的,它使异步代码看起来像是同步的。您可以给你的代码的最好的礼物是用async-await提供了一个更紧凑的,熟悉的,类似try catch的代码语法。 **否则:** 使用回调的方式处理异步错误可能是陷入困境最快的方式 - 这种方式必须面对不停地检测错误,处理别扭的代码内嵌,难以推理编码流。 @@ -381,7 +381,7 @@ null == undefined // true **否则:** 更长的代码(在ES5方法中)更易于产生缺陷,并读起来很是笨重。 -🔗 [**更多: It’s Time to Embrace Arrow Functions**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) +🔗 [**更多: 这是拥抱箭头函数的时刻**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75)


@@ -422,7 +422,7 @@ null == undefined // true **TL;DR:** 即使是那些最有名的依赖模块,比如Express,也有已知的漏洞。使用社区和商业工具,比如 🔗 [nsp](https://github.com/nodesecurity/nsp) ,集成在您的CI平台上,在每一次构建的时候都会被调用,这样可以很容易地解决漏洞问题。 -**否则:** 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物。相当繁琐。 +**否则:** 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物,相当繁琐。

@@ -446,7 +446,7 @@ null == undefined // true ## ![✔] 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 的), 或者它被其作者标记为已弃用, 可能会出现严重的情况 - 停掉这次构建并防止部署此版本。 +**TL;DR:** 使用您的首选工具 (例如 “npm outdated” or [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) 来检测已安装的过期依赖包, 将此检查注入您的 CI 管道, 甚至在严重的情况下使构建失败。例如, 当一个已安装的依赖包滞后5个补丁时 (例如:本地版本是1.3.1 的, 存储库版本是1.3.8 的), 或者它被其作者标记为已弃用, 可能会出现严重的情况 - 停掉这次构建并防止部署此版本。 **否则:** 您的生产环境将运行已被其作者明确标记为有风险的依赖包 @@ -536,7 +536,7 @@ null == undefined // true **TL;DR:** 在一个安全的API中暴露一组系统相关的信息,比如内存使用情况和REPL等等。尽管这里强烈建议依赖标准和作战测试工具,但一些有价值的信息和操作更容易使用代码完成。 -**否则:** 您会发现,您正在执行许多“诊断部署” — 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。 +**否则:** 您会发现,您正在执行许多“诊断部署” – 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。 🔗 [**更多: 创建一个 '维护端点'**](/sections/production/createmaintenanceendpoint.chinese.md) From ec41ecc82a7d291ae5f490172f187182dac7654b Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 18:45:48 +0800 Subject: [PATCH 70/75] [Chinese-translation]little change. --- README.chinese.md | 6 +++--- sections/errorhandling/useonlythebuiltinerror.chinese.md | 1 + sections/projectstructre/separateexpress.chinese.md | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index 0d42a64cf..d770ad6a7 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -71,7 +71,7 @@ ## ![✔] 1.4 分离 Express 'app' and 'server' -**TL;DR:** 避免定义整个[Express](https://expressjs.com/)应用在一个单独的大文件的不好习惯 - 分离您的 'Express' 定义至少在两个文件中: API声明(app.js) 和 网络相关(WWW)。对于更好的结构,是把你的API声明放在组件中。 +**TL;DR:** 避免定义整个[Express](https://expressjs.com/)应用在一个单独的大文件里, 这是一个不好的习惯 - 分离您的 'Express' 定义至少在两个文件中: API声明(app.js) 和 网络相关(WWW)。对于更好的结构,是把你的API声明放在组件中。 **否则:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。 @@ -86,7 +86,7 @@ **否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。 -🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.md) +🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.chinese.md)


@@ -96,7 +96,7 @@ ## ![✔] 2.1 使用 Async-Await 和 promises 用于异步错误处理 -**TL;DR:** 使用回调的方式处理异步错误可能是导致灾难的最快的方式(a.k.a the pyramid of doom)。对您的代码来说,最好的礼物就是使用规范的promise库或async-await来替代,这会使其像try-catch一样更加简洁,熟悉的代码结构。 +**TL;DR:** 使用回调的方式处理异步错误可能是导致灾难的最快的方式(a.k.a the pyramid of doom)。对您的代码来说,最好的礼物就是使用规范的promise库或async-await来替代,这会使其像try-catch一样更加简洁,具有熟悉的代码结构。 **否则:** Node.JS 回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。 diff --git a/sections/errorhandling/useonlythebuiltinerror.chinese.md b/sections/errorhandling/useonlythebuiltinerror.chinese.md index 0ec2218c3..05fc39437 100644 --- a/sections/errorhandling/useonlythebuiltinerror.chinese.md +++ b/sections/errorhandling/useonlythebuiltinerror.chinese.md @@ -5,6 +5,7 @@ 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作为一种语言,似乎不符合基于构造函数的错误捕获。因此,区分对象属性似乎比在构造函数类型上区分要容易得多… diff --git a/sections/projectstructre/separateexpress.chinese.md b/sections/projectstructre/separateexpress.chinese.md index 0c8771985..8b8a2d703 100644 --- a/sections/projectstructre/separateexpress.chinese.md +++ b/sections/projectstructre/separateexpress.chinese.md @@ -3,9 +3,9 @@

-### 段落解释 +### 一段解释 -最新的Express生成器有一个值得保留的伟大实践--API声明与网络相关配置(端口、协议等)是分开的。这样就可以在不执行网络调用的情况下对API进行在线测试,它所带来的好处是:快速执行测试操作和获取代码覆盖率。它还允许在灵活多样的网络条件下部署相同的AP。额外好处:更好的关注点分离和更清晰的代码结构。 +最新的Express生成器有一个值得保留的伟大实践--API声明与网络相关配置(端口、协议等)是分开的。这样就可以在不执行网络调用的情况下对API进行在线测试,它所带来的好处是:快速执行测试操作和获取代码覆盖率。它还允许在灵活多样的网络条件下部署相同的API。额外好处:更好的关注点分离和更清晰的代码结构。

@@ -43,7 +43,7 @@ var server = http.createServer(app); ``` -### 示例: 使用超快的流行的测试包在线测试你的代码 +### 示例代码: 使用超快的流行的测试包在线测试你的代码 ```javascript const app = express(); From ee4148d3c743aa451c438656bf1e4b9d42e345b7 Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 18:50:20 +0800 Subject: [PATCH 71/75] [Chinese-translation]little changes. --- sections/errorhandling/useonlythebuiltinerror.chinese.md | 4 +++- sections/production/lockdependencies.chinese.md | 4 ++-- sections/production/measurememory.chinese.md | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sections/errorhandling/useonlythebuiltinerror.chinese.md b/sections/errorhandling/useonlythebuiltinerror.chinese.md index 05fc39437..6473ff196 100644 --- a/sections/errorhandling/useonlythebuiltinerror.chinese.md +++ b/sections/errorhandling/useonlythebuiltinerror.chinese.md @@ -4,10 +4,12 @@ ### 一段解释 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作为一种语言,似乎不符合基于构造函数的错误捕获。因此,区分对象属性似乎比在构造函数类型上区分要容易得多… diff --git a/sections/production/lockdependencies.chinese.md b/sections/production/lockdependencies.chinese.md index 82633c03b..a30a87b5a 100644 --- a/sections/production/lockdependencies.chinese.md +++ b/sections/production/lockdependencies.chinese.md @@ -7,9 +7,9 @@ -您的代码依赖于许多外部包,假设它“需要”和使用momentjs-2.1.4,默认情况下,当布署到生产中时,NPM可能会获得momentjs 2.1.5,但不幸的是,这将带来一些新的bug。使用NPM配置文件和设置 ```–save-exact=true``` 指示NPM去完成安装,以便下次运行```npm install```(在生产或在Docker容器中,您计划将其用于测试)时,将获取相同的依赖版本。另一种可选择受欢迎的方法是使用一个shrinkwrap文件(很容易使用NPM生成)指出应该安装哪些包和版本,这样就不需要环境来获取新版本了。 +您的代码依赖于许多外部包,假设它“需要”和使用momentjs-2.1.4,默认情况下,当布署到生产中时,NPM可能会获得momentjs 2.1.5,但不幸的是,这将带来一些新的bug。使用NPM配置文件和设置 ```–save-exact=true``` 指示NPM去完成安装,以便下次运行 ```npm install```(在生产或在Docker容器中,您计划将其用于测试)时,将获取相同的依赖版本。另一种可选择受欢迎的方法是使用一个shrinkwrap文件(很容易使用NPM生成)指出应该安装哪些包和版本,这样就不需要环境来获取新版本了。 -** *更新:* * 在NPM5中,使用.shrinkwrap依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。 +***更新:** 在NPM5中,使用.shrinkwrap依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。

diff --git a/sections/production/measurememory.chinese.md b/sections/production/measurememory.chinese.md index c23f81fc3..9bab948b6 100644 --- a/sections/production/measurememory.chinese.md +++ b/sections/production/measurememory.chinese.md @@ -3,7 +3,7 @@

-### 段落解释 +### 一段解释 在一个完美的开发过程中, Web开发人员不应该处理内存泄漏问题。 实际上,内存问题是一个必须了解的Node已知的问题。首先,内存使用必须不断监视.在开发和小型生产站点上,您可以使用Linux命令或NPM工具和库(如node-inspector和memwatch)来手动测量。 这个人工操作的主要缺点是它们需要一个人进行积极的监控 - 对于正规的生产站点来说,使用鲁棒性监控工具是非常重要的,例如(AWS CloudWatch,DataDog或任何类似的主动系统),当泄漏发生时提醒。 防止泄漏的开发指南也很少:避免将数据存储在全局级别,使用动态大小的流数据,使用let和const限制变量范围。 From d9e65d9b19f1f23aaf6ce4706cc432bea6f8e579 Mon Sep 17 00:00:00 2001 From: jin jing Date: Mon, 15 Jan 2018 18:51:27 +0800 Subject: [PATCH 72/75] [Chinese-translation]little change. --- sections/production/lockdependencies.chinese.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sections/production/lockdependencies.chinese.md b/sections/production/lockdependencies.chinese.md index a30a87b5a..f01121832 100644 --- a/sections/production/lockdependencies.chinese.md +++ b/sections/production/lockdependencies.chinese.md @@ -9,7 +9,7 @@ 您的代码依赖于许多外部包,假设它“需要”和使用momentjs-2.1.4,默认情况下,当布署到生产中时,NPM可能会获得momentjs 2.1.5,但不幸的是,这将带来一些新的bug。使用NPM配置文件和设置 ```–save-exact=true``` 指示NPM去完成安装,以便下次运行 ```npm install```(在生产或在Docker容器中,您计划将其用于测试)时,将获取相同的依赖版本。另一种可选择受欢迎的方法是使用一个shrinkwrap文件(很容易使用NPM生成)指出应该安装哪些包和版本,这样就不需要环境来获取新版本了。 -***更新:** 在NPM5中,使用.shrinkwrap依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。 +* **更新:** 在NPM5中,使用.shrinkwrap依赖项会被自动锁定。Yarn,一个新兴的包管理器,默认情况下也会锁定依赖项。

From aa689745bd728275ce0313fa6de87a7a42ac4329 Mon Sep 17 00:00:00 2001 From: jin jing Date: Tue, 16 Jan 2018 10:49:35 +0800 Subject: [PATCH 73/75] [Chinese-translation]update.. --- README.chinese.md | 63 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index d770ad6a7..b8845c172 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -661,10 +661,69 @@ null == undefined // true ## 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` -Developer & consultant, Backend expert, JavaScript enthusiast, focused on Node.JS. Many of the bullets was first published on his blog post [http://www.goldbergyoni.com](http://www.goldbergyoni.com) +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) + + + + +

+## :star: No Stars Yet, Waiting For The First To Suggest a New Bullet From f923b62d5fac18fe9ec5716edaf40157d9552c33 Mon Sep 17 00:00:00 2001 From: matt Date: Tue, 27 Feb 2018 08:14:31 +0800 Subject: [PATCH 74/75] [Chinese-translation]add writing guidelines --- writing-guidelines.chinese.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 writing-guidelines.chinese.md 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个月里至少更新一次 From 661c96f46f3c3a2a045cd2b182bb969835d217cf Mon Sep 17 00:00:00 2001 From: matt_jin Date: Tue, 27 Feb 2018 23:00:13 +0800 Subject: [PATCH 75/75] [Chinese-translation]update changes. --- README.chinese.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.chinese.md b/README.chinese.md index b8845c172..84f75b8e4 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -18,7 +18,7 @@
# 欢迎! 首先您应该知道的三件事情: -**1. 当您读到这里,实际上您读了很多关于Node.JS的优秀文章 -** 这是对Node JS 最佳实践中排名最高的内容的总结和分享 +**1. 当您读到这里,实际上您读了很多关于Node.js的优秀文章 -** 这是对Node JS 最佳实践中排名最高的内容的总结和分享 **2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。每天都有新的issue和PR被创建,以使这本在线书籍不断更新。我们很乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是提出绝妙的新想法。请查看我们的[milestones](https://github.com/i0natan/nodebestpractices/milestones?direction=asc&sort=due_date&state=open) @@ -98,7 +98,7 @@ **TL;DR:** 使用回调的方式处理异步错误可能是导致灾难的最快的方式(a.k.a the pyramid of doom)。对您的代码来说,最好的礼物就是使用规范的promise库或async-await来替代,这会使其像try-catch一样更加简洁,具有熟悉的代码结构。 -**否则:** Node.JS 回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。 +**否则:** Node.js 回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。 🔗 [**更多: 避免回调**](/sections/errorhandling/asyncerrorhandling.chinese.md) @@ -226,7 +226,7 @@

-## ![✔] 3.2 Node JS 特定的插件 +## ![✔] 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) @@ -399,11 +399,11 @@ null == undefined // true

-## ![✔] 4.2 检测代码问题使用ESLint + 特定node插件的规则 +## ![✔] 4.2 使用一个linter检测代码问题 -**TL;DR:** ESLint是检查代码风格的事实上的标准,不仅要查明实际的间距问题,也要检测严重的反模式问题,像开发者没有分类的抛出异常。除了仅仅涉及 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) 和 [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security) +**TL;DR:** 使用代码linter检查基本质量并及早检测反模式。在任何测试之前运行它, 并将其添加为预提交的git钩子, 以最小化审查和更正任何问题所需的时间。也可在[Section 3](https://github.com/i0natan/nodebestpractices#3-code-style-practices)中查阅编码样式实践 -**否则:** 许多错误的Node.js代码模式可能在检测下逃生。例如,开发人员可能需要某些文件,把一个变量作为路径名 (variableAsPath) ,这会导致攻击者可以执行任何JS脚本。Node.JS linters可以检测这类模式,并及早预警。 +**否则:** 您可能让一些反模式和易受攻击的代码传递到您的生产环境中。

@@ -525,7 +525,7 @@ null == undefined // true **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,也一样)。 +**否则:** 您的应用可能只是使用了其可用资源中的25% (!),甚至更少。注意,一台典型的服务器有4个或更多的CPU,默认的Node.js部署仅仅用了一个CPU(甚至使用PaaS服务,比如AWS beanstalk,也一样)。 🔗 [**更多: 利用所有的CPU**](/sections/production/utilizecpu.chinese.md) @@ -670,7 +670,7 @@ To maintain this guide and keep it up to date, we are constantly updating and im # 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 +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. @@ -720,7 +720,10 @@ This repository is being kept up to date thanks to the help from the community. 🌻 [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) +🌻 [Allen Fang](https://github.com/AllenFang), +🌻 [Leonardo Villela](https://github.com/leonardovillela), +🌻 [Michal Zalecki](https://github.com/MichalZalecki) +🌻 [Chris Nicola](https://github.com/chrisnicola)