本文主要讨论一些进行Node.js开发的最佳实践和建议,这些建议不仅仅适合开发者,还适合那些管理与维护Node.js基础架构的工作人员。遵循本文提供的这些建议,能够让你更好的进行日常的开发工作。

Statement

使用ES2015 
在2015年的夏天,ES2015的最终草案(即ES6)正式发布了。该版本为JavaScript语言增加了大量的新的语言特性,主要包括:

  • 箭头函数
  • 模版字符串
  • rest operator(不定参数), argument spreading
  • 生成器
  • promises
  • maps, sets
  • symbols

以及很多其他特性。一个更加完整的新特性的列表你可以从Kyle SimpsonES6 and Beyond中进行了解。并且它们中的绝大部分特性已经被加入到了Node.js v4中。

在客户端,你也可以借助Babel来使用ES6的所有新特性,Babel是一个JavaScript转译器。目前在服务器端,我们只倾向于使用那些被加入到最新的稳定版本的特性,这样无需转译代码,这可以避免出现那些令我们头疼的潜在问题。

对于Node.js中的ES6的更多信息,你可以访问官方站点:https://nodejs.org/en/docs/es6/

回调约定 – 同时支持Promise 
在去年,我们可能会推荐你为你的模块暴露错误优先的回调接口。但是随着生成器函数的正式标准化,并且异步函数也即将到来,因此我们现在建议你在编写模块的接口时应该暴露支持Promise的的错误优先的回调函数。

为什么需要这样?首先回调接口是为了提供向后兼容性,为了能够在未来能够获得更好的兼容性,需要同时提供Promise支持。

你可以参考下面的例子来进一步的理解具体应该如何进行编程。在这个例子中readPackage函数读取了package.json文件,并同时通过Promise和回调接口返回了它的内容。

  1. const fs = require('fs'); function readPackage (callback) { // as of now we do not have default values in Node.js callback = callback || function () {} return new Promise((resolve, reject) => { fs.readFile('./package.json', (err, data) => { if (err) { reject(err); return callback(err); } resolve(data); return callback(null, data); }) }) } module.exports.readPackage = readPackage;

异步模式 
在Node.js中,很长一段时间你只有两种方法来管理异步流:回调或者流(Stream)。对于回调函数而言, 
你可以使用类似于async这类库,对于流而言,有through、bl、highland等库可以选择。

但是随着Promise、生成器、异步函数等被逐渐引入进标准的ECMAScript,JS中的流程控制也得到了极大的改善。

引用
关于异步JavaScript的发展历史,你可以参考异步JavaScript的发展历程这篇博文。

错误处理 
错误处理在应用开发过程中起着至关重要的作用:确定应用崩溃的时间,或者仅仅是打印错误信息,确保应用继续运行都是有一定难度的。

为了能够更简单的说明这个问题,我们决定将其分为两种:程序员错误(programmer errors)和运算错误(operational errors)。

程序员错误就是我们所说的bug,由于你不知道程序运行的确切状态因此当出现错误时你最好立刻停止应用的运行(crash the process)。

另一方面,运算错误是由于系统或者远程服务本身所导致的问题。例如:请求超时和内存不足等。基于错误发生的特点,你可以对症下药,然后重试,例如文件丢失,你可以去创建相应的文件。

在回调中进行错误处理 
如果一个错误发生在异步操作的过程中,错误对象应该作为异步函数的第一个参数进行传递。你必须始终要检查该错误对象并进行错误处理。

在前面的有关回调约定的例子里面已经展示了如何在回调函数中进行错误的优先处理。

在Promise中进行错误处理 
如果是下面的代码片段会发生什么情况?

  1. Promise.resolve(() => 'John') .then(() => { throw new Error('ops'); }) .catch((ex) => { console.log(ex); }) .then(() => { throw new Error('ups'); console.log(Doe'); })
  • 在第3行会抛出一个异常。
  • catch会处理它,并且在stdout中打印出:[Error: ops]
  • 执行继续,并且在第9行会抛出一个新的错误
  • 没有了

的确没有什么了 – 最后一个被抛出的错误将会是静默的。你需要注意,你应该始终以一个catch语句作为promise链的最后一环。这会为你解决很多头疼的问题。像下面这样:

  1. Promise.resolve(() => 'John') .then(() => { throw new Error('ops'); }) .catch((ex) => { console.log(ex); }) .then(() => { throw new Error('ups'); console.log(Doe'); }) .catch((ex) => { console.log(ex); });

现在会输出如下内容:

  1. [Error: ops] [Error: ops]

使用JavaScript标准风格 
在过去几年中,我们会使用JSHint、JSCS、ESLint等非常有用的代码质量工具来尽可能的自动化检查我们的代码。

最近,当谈到代码风格的时候,我们使用ferossJavaScript标准风格。 
原因是它非常的简单:无需任何配置文件,只需要将其放到项目中。主要包括如下一些规则:

  • 使用2个空格作为缩进
  • 字符串使用单引号 – 除了为了避免转义
  • 不要包括没有被使用的变量
  • 没有分号
  • 永远不要以 ( 或者 [ 作为一行的开始
  • 关键字后加空格 if (condition) { … }
  • 函数名后加空格 function name (args) { … }
  • 始终使用===代替==,但是可以使用obj == null来检查null || undefined。
  • 始终要处理Node.js的err函数参数
  • 始终要为浏览器全局变量增加window前缀,除了document和navigator
  • 尽可能避免使用类似于open、length、evet、name等走位浏览器全局变量。

当然,如果你的 编辑器只支持ESLint的话,这里有一个ESLint的规则库用于使用标准风格,即eslint-plugin-standard。安装了这个插件后,你的.eslintrc文件可以是下面这样的:

  1. { "plugins": [ "standard" ], }

12-Factor应用(The Twelve-Factor Application) 
如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。 
12-Factor应用宣言描述了进行Web应用开发的最佳实践:

  • 基准代码:一份基准代码,多份部署
  • 依赖:显示声明依赖
  • 配置:在环境中存储配置
  • 后端服务:把后端服务当作附加资源
  • 构建、发布、运行:严格分离构建和运行
  • 进程:以一个或多个无状态进程运行应用
  • 端口绑定:通过端口绑定提供服务
  • 并发:通过进程模型进行扩展
  • 易处理:快速启动和优雅终止可最大化健壮性
  • 开发环境与线上环境等价:尽可能的保持开发、预发布、线上环境相同
  • 日志:把日志当作事件流
  • 管理进程:后端管理任务当作一次性进程运行

这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。 
开始新的项目 
始终通过npm init命令来开始一个新项目。这可以为你的项目创建一个初始的package.json。

如果你想跳过初始的提问并直接使用默认的配置,只需要运行npm init –yes即可。

监控你的应用 
当发生某个故障或是故障即将发生时,及时的通知你,能够为你挽回损失。

为了进行应用的监控,你可以使用类似的SaaS产品或是开源软件。在开源软件方面,主要包括:Zabbix, Collected, ElasticSearch和Logstash。

如果你不想要自己进行部署,可以考虑使用线上的服务,你可以尝试使用Trace, 
它是我们公司开发的Node.js和微服务监控解决方法。

使用构建系统 
尽可能的自动化一切东西。没有什么比让开发来做应该让grunt做的事情更无聊和令人恼火的了,这不仅浪费时间,而且没有意义。现如今JvavaScript的这类工具已经非常的丰富了,包括Grunt, Gulp, 和Webpack,你知道几个就行。在RisingStack,绝大部分的前端开发新项目都是使用Webpack来进行自动化构建,其他类型的则使用gulp实现自动化任务。对于新手而言,Webpack可能会花费大量的时间去理解,所以我强烈建议你去阅读一下Webpack Cookbook

使用最新的长期支持(LTS)的Node版本 
为了能够更好的获取稳定性和新特性,我们建议你使用最新的Node的LTS(长期支持)版本,它们是使用偶数发布编号的版本。当然,你也可以自由的使用最新的实验版本,即称为稳定发布版本的使用奇数发布编号的。

如果你需要为多个项目工作,并且使用了不同的Node.js版本,建议你最好使用一个Node版本管理器——nvm。

更多信息你可以参考Node.js官方网站的发布信息: 
What You Should Know about Node.js v5 and More 
每周更新你的项目依赖 
养成每周更新一次你的项目依赖的习惯。这方面,你可以使用npm outdated或者是ncu包。

选择合适的数据库 
当我们谈到Node.js和数据库的时候,可能你想到的第一个技术是MongoDB。当然这并没有什么错,但是你不应该直接就去使用它。在这么做之前你需要问你自己和你的团队几个问题。包括下面几个:

  • 应用会有结构化数据吗?
  • 应用会进行交易处理吗?
  • 数据需要存放多长时间?

可能你需要的仅仅是Redis,或者是如果你有结构化数据,那么你要用的可能是PostgrelSQL。 
如果你需要在Node.js中使用SQL的话,你可以看看knex。

使用语义版本控制(Semantic Versioning)

引用
语义版本控制是一种为了兼容性空啊率的使用三段式版本号的正式约定,即:major.minor.patch,分别为主版本,次版本,补丁。

如果是一个不会向后兼容(backward-compatible)的API变化使用主版本号。当添加新的特性且API变化是向后兼容的时候使用次版本号。如果只是对Bug进行修复可以使用包版本号。幸运的是,你可以使用semantic-release这个模块自动化你的JavaScript的模块发布。

如何在2016年成为一个更好的Node.js开发者的更多相关文章

  1. 打算写一个《重学Node.js》系列,希望大家多多支持

    先放上链接吧,项目已经开始2周了:https://github.com/hellozhangran/happy-egg-server 想法 现在是2019年11月24日,还有人要开始学习Node.js ...

  2. 创建一个提供数据 API 的 Node.js 网站

    创建站点目录 首先,创建一个文件夹用来保存你的站点文件,使用 mkdir 就可以了 PS C:\> mkdir mysite 然后,进入到这个文件夹进行下一步的操作. 创建包说明 使用记事本或者 ...

  3. 微软开放技术发布针对 Mac 和 Linux 的更新版 Azure Node.JS SDK 和命令行工具

    发布于 2013-12-04 作者 Eduard Koller 这次为我们使用Linux 的朋友带来了更多关于部署云上虚拟机的消息.今天,微软开放技术有限公司 (MS Open Tech),想与大家分 ...

  4. 一个类似ThinkPHP的Node.js框架——QuickNode

    QuickNode Node.js从QuickNode开始,让restful接口开发更简单! PHP的MVC 作为一名曾经的PHP开发者,我也有过三年多的thinkphp使用经验,那是我学习PHP接触 ...

  5. 使用express搭建第一个Web应用【Node.js初学】

    来源:http://jingyan.baidu.com/article/bad08e1ee501e009c8512106.html express是一个开源的node.js项目框架,初学者使用expr ...

  6. 如何开发一个产品级的Node.js 应用

    介绍 Node.js是一个开源的javascript运行时环境.非常简单可以快速开发一个网络应用.这个平台运行在Linux.OSX和Windows,而且运行在这个平台上的应用都是用javascript ...

  7. node.js的安装与第一个hello world、node.js的初始化

    1.下载node.js文件 2.windows下点击安装  重复下一步即可 3.编辑工具  EditPlus编辑器 4.新建保存目录的文件夹,并新建一个文本文档 5.打开EditPlus编辑器  打开 ...

  8. 一个超级简单的node.js爬虫(内附表情包)

    之所以会想到要写爬虫,并不是出于什么高大上的理由,仅仅是为了下载个表情包而已-- 容我先推荐一下西乔出品的神秘的程序员表情包. 这套表情包着实是抵御产品.对付测试.嘲讽队友.恐吓前任的良品, 不过不知 ...

  9. [译]How to Install Node.js on Ubuntu 14.04 如何在ubuntu14.04上安装node.js

    原文链接为 http://www.hostingadvice.com/how-to/install-nodejs-ubuntu-14-04/ 由作者Jacob Nicholson 发表于October ...

随机推荐

  1. 测试Open Live writer

    这个东西究竟是怎么用的啊,看起来好高端的样子...

  2. Android 反编译 -- apktool、dex2jar、jd-gui

    原文:http://blog.csdn.net/vipzjyno1/article/details/21039349/ apktool 最新官网: http://ibotpeaches.github. ...

  3. 在ubuntu上搭建开发环境10---英文版ubuntu安装中文输入法

    之前安装 ubuntu时候选择安装英文版,但是在查资料的时候难免的要输入中文所以自己弄了一下中文输入法的安装 我安装的是fcitx小企鹅输入法 下面介绍一下安装的过程.....   ubuntu默认的 ...

  4. 【JAVA多线程问题之死锁】

    一.死锁是什么? 举个例子:两个人一起吃饭,每个人都拿了一只筷子,双方都在等待对方将筷子让给自己,结果两个人都吃不了饭.这种情况和计算机中的死锁情况很相似. 假设有两个线程,互相等待对方释放占有的锁, ...

  5. Myeclipse的web工程和Eclipse互相转换

    eclipse的web工程转myeclipse的web工程1.原eclipse工程叫netschool 2.在myeclipse中新建一个工程叫netschool 并在新建的时修改 web root ...

  6. HDU1899 Sum the K-th's(树状数组)

    枚举,每次增加点,删除点 #include<cstdio> #include<iostream> #include<cstdlib> #include<cst ...

  7. linux驱动程序设计的硬件基础,王明学learn

    linux驱动程序设计的硬件基础(一) 本章讲总结学习linux设备程序设计的硬件基础. 一.处理器 1.1通用处理器 通用处理器(GPP)并不针对特定的应用领域进行体系结构和指令集的优化,它们具有一 ...

  8. 利用opencv进行相机标定程序

    #include "Stafx.h" ; //棋盘上有13个格子,那么角点的数目12 ; ; //图片的总张数 int main(int argc, char** argv) { ...

  9. Open judge C16H:Magical Balls 快速幂+逆元

    C16H:Magical Balls 总时间限制:  1000ms 内存限制:  262144kB 描述 Wenwen has a magical ball. When put on an infin ...

  10. json入门(二)

    背景 之前最早的时候,也见过类似于这样的字符串: {"list":[           {"ArticleId":7392749,"BlogId&q ...