首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >最佳Node实践之实用十式: Node大师带来的启迪

最佳Node实践之实用十式: Node大师带来的启迪

作者头像
疯狂的技术宅
发布2019-03-27 12:27:02
8830
发布2019-03-27 12:27:02
举报
文章被收录于专栏:京程一灯京程一灯

最佳Node实践之实用十式:受我们的客邀作者,Node大师Azat Mardan的启发。 SitePoint 的客座发帖旨在带给大家web社区里杰出的作者和宣讲者的优秀内容。

关于作者的其它文章:

  • 10 Tips to Become a Better Node Developer in 2017

在我之前的文章: 10 Tips to Become a Better Node Developer in 2017中,介绍了10个Node.js的技巧,现在你已经可以应用到自己的代码中。而这篇文章与此前的文章一脉相承,10个进一步的最佳实践技巧帮助你的Node技能更上一层。以下是我们将涉及到的内容:

  1. 使用 npm scripts — 那些bash脚本,当可以使用npm scripts和Node更好地组织它们的时候,就别再用写的了。 例如, npm run buildstarttest。npm scripts 就像Node开发人员接触一个新的项目的时去获取真相的唯一途径。
  2. 使用环境变量 —通过将 process.env.NODE_ENV设置为 developmentproduction来使用。 一些框架将也会使用这个变量,所以按游戏规则进行吧。
  3. 理解事件循环 — setImmediate()不是立即的,而 nextTick()不是指下一个。 使用 setImmediate()setTimeout()将CPU密集型任务卸放到下一个事件循环周期。
  4. 使用 functional inheritance — 避免陷入无脑的纷争,或者那些脑细胞流失的调试陷阱和对原型继承或类的理解过程,而是只使用functional inheritance,就像某些多产的Node贡献者那样。
  5. Name things appropriately — 提供有意义的名称,将来可以作为文档使用。 此外,请不要将文件名大写,如果需要可以使用中划线。 大写的文件名不只是看起来奇怪,而且会导致跨平台的问题。
  6. 考虑不使用JavaScript — ES6/7是经过六年会议后诞生的可悲的补丁,而同时已经有了更好的JavaScript——CoffeeScript。如果你希望代码交付更快,并且不再浪费时间在 var/ const/ let、分号、 class和其它方面的争议上。
  7. 提交源生代码 — 当使用转译器时,提交原生JS代码(build后的结果),所以你的项目不经过build就可以运行。
  8. 使用 gzip — 额。。。 npm i compression-S 和完整的日志记录 — 不多也不少地依赖于环境. npm i morgan-S
  9. 放大 — 从Node开发的第一天开始考虑聚集和无状态服务。使用pm2或者strongloop’s cluster control。
  10. 缓存请求 — 通过将它们藏在在静态文件服务器(如nginx)或者请求级缓存(如Varnish Cache和CDN缓存)的后面,可以从Node服务器获得最大的关联。

那么让我们一个个分开看看他们吧。走起!

使用 npm Scripts

创建并使用npm scripts 对应用进行构建、测试以及最重要的运行,几乎已经是标准了。这是Node开发人员在遇到一个新的Node项目时首先看到的。有人 (1, 2, 3, 4) 甚至已经放弃使用Grunt、Gulp,喜欢更低级但更可靠的npm script。我完全可以理解他们的观点。考虑到npm脚本有前缀和后缀,你可以达到非常复杂的自动化水平:

"scripts": {
  "preinstall": "node prepare.js",
  "postintall": "node clean.js",
  "build": "webpack",
  "postbuild": "node index.js",
  "postversion": "npm publish"
}

通常在前端开发中,需要运行两个以上的监视进程,以此来重建代码。例如,一个进程用于webpack,另一个用于nodemon。为此,你可以使用 &&,因为第一行不会输出提示。不过,有一个很便捷的模块叫做 concurrently ,它可以产生多个进程,并同时运行它们。

另外,请在局部使用命令行安装的开发工具,例如:webpack,nodemon,gulp,Mocha等。例如你的安装可以指向 ./node_modules/.bin/mocha或者将此行命令加入到你的bash/zsh文件夹(PATH!)

`export PATH="./node_modules/.bin:$PATH"`

使用 Env Vars (环境变量)

即使在项目的早期阶段也要使用环境变量,以确保没有泄漏敏感信息,从一开始就得正确地构建代码。此外,一些库和框架(我确定Express就是这么做的)将使用如NODE_ENV信息,来修正它们的行为。 将其设置为 production。 设置你的 MONGO_URIAPI_KEY值。 您可以创建一个shell文件(例如 start.sh')并将其添加到.gitignore`:

`NODE_ENV=production MONGO_URL=mongo://localhost:27017/accounts API_KEY=lolz nodemon index.js`

Nodemon还有一个配置文件,你可以在其中设置env变量: (例子戳此处):

{
  "env": {
    "NODE_ENV": "production",
    "MONGO_URL": "mongo://localhost:27017/accounts"
  }
}

理解事件循环

正是强大巧妙的事件循环使Node如此高速和辉煌,充分利用所有的时间,这些事件本会浪费在等待输入和输出任务完成。因此,Node非常适合优化绑定I/O操作的系统。

如果你需要执行某些CPU密集型(例如,计算,哈希密码或压缩),那么除了为这些CPU任务产生新进程之外,你可能想到使用 setImmediate()setTimeout()——它们回调函数中的代码会在下一个事件循环周期中继续运行。 nextTick()工作在同一个周期,与名称相反。 Argh!

这是Bert Belder提供的图示,他从事事件循环方面的工作,清楚知道事件循环如何工作!

使用Functional Inheritance

(译注:functional继承,'functional'一词就不强行翻译了,个人理解为——函数式)

JavaScript 支持原型链继承,即对象从其他对象继承而来。 class运算符也已经被添加到ES6的语言中。然而,它相比functional inheritance明显更复杂。大多数Node大师更喜欢后者(functional inheritance)的简单性。它由一个简单的函数工厂模式实现,不需要使用 prototypenewthis。 当你更新原型(这会导致所有实例也跟着改变)时,并没有隐式的影响,因为在functional inheritance中,每个(实例化后的)对象使用它自己的方法副本。

请观察思考Express,Mocha,Connect,Superagent和几十个其他Node模块背后的多产天才TJ Holowaychuk的代码。在Express环境使用functional inheritance:(完整源代码):

exports = module.exports = createApplication;
// ...
function createApplication() {
  var app = function(req, res, next) {
    app.handle(req, res, next);
  };

  mixin(app, EventEmitter.prototype, false);
  mixin(app, proto, false);

  app.request = { __proto__: req, app: app };
  app.response = { __proto__: res, app: app };
  app.init();
  return app;
}

客观来说,核心的Node模块频是繁使用原型继承的。如果你也要跟着使用这个模式,请确保你了解它的运作方式。更多内容可以参考JavaScript继承模式。

适当地取名

这一点很明显,就是用好的名字作为文档。下面你喜欢哪一个?

const dexter = require('morgan')
// ...
app.use(dexter('dev')) // When is the next season?

当我只看 app.use()我是不知道 dexter正在做什么的。 如果是一个不同的更有意义的名称——

const logger = require('morgan')
// ...
app.use(logger('dev')) // Aha!

同样,文件名必须正确反映代码内部的目的是什么。 如果你看看Node的 lib文件夹 (GitHub 链接)其具有平台捆绑的所有核心模块,那么你将看到文件/模块的清晰命名(即使你不是很熟悉所有核心模块):

events.js
fs.js
http.js
https.js
module.js
net.js
os.js
path.js
process.js
punycode.js
querystring.js

内部模块用下划线( _debugger.js_http_agent.js_http_client.js)标记,就像代码中的方法和变量一样。 这有助于警告开发人员这是一个内部接口,如果你使用了这个变量,导致它被重构或甚至删除,那么不要抱怨,这是你自找的。

Consider NOT Using JavaScript

啊哈?你确定看准确吗?这是什么鬼?没错。 就是这样的。 即使使用ES6和ES2016/ES7增加的两个功能,JavaScript仍然有它的诡异之处。 除了JavaScript,还有其他可以用的选择,你或你的团队可以从中受益,仅需稍微设置一下。根据专业水平和应用程序的性质,你可能会从像 TypeScript 或 Flow 这样的强语言。 另一方面,还有完全functional形式的脚本语言,像 Elm 或 ClojureScript。 CoffeeScript 是另一个伟大的并且经过实战测试的可选语言。 你也可以参考 Dart 2.0。

当你需要的只是一些宏操作(宏可以使你准确建立你想要语句),而不是需要一整套新语言,可以考虑 Sweet.js 它会做到这一点——允许你编写生成代码的代码。

如果进行非JavaScript的路由,请仍然包括你编译的代码,因为一些开发人员可能不太了解你的语言以正确构建它。 例如,VS Code是最大的TypeScript项目之一,也许随Angular 2之后,Code运用TypeScript使用types来对Node的核心模块打补丁。在VS code的repo vscode/src/vs/base/node/ 中(链接),你可以看到像 crypto, process等熟悉的模块名称。不过有 ts那样的后缀。还有其他 ts文件在repo中。 但是,他们还包括带有原生JavaScript代码的 vscode/build

了解Express中间件

Express是一个伟大而非常成熟的框架。它的光辉来自于允许无数其他模块对其行为进行配置。因此,你需要知道最常用的中间件,你需要知道如何使用它。所以何不利用 my Express cheat sheet。其中我有主要的中间件模块列出。 例如, npm i compression-S 将通过压缩响应来降低下载速度。 logger('tiny')logger('common')分别提供较少的(dev)或更多(prod)日志。

Scale up

Node在异步处理上是很杰出的,这归功于它的非阻塞I/O以及它一直以来简洁的异步过程的代码。这带来了提前开启放大的机会,也许甚至就是第一行代码开始。有一个核心的 cluster模块,它将允许您垂直缩放,并且没有太多的问题。然而,更好的方法是使用工具,如pm2 或者 StrongLoop’s cluster control。

例如,这是如何开始使用pm2:

`npm i -g pm2`

然后可以启动同一服务器的四个实例:

`pm2 start server.js -i 4`

对于Docker,pm2 version 2+ 有 pm2-docker。所以你的Dockerfile可以看起来像这样:

# ...

RUN npm install pm2 -g

CMD ["pm2-docker", "app.js"]

官方Alpine Linux pm2镜像在 Docker Hub中。

缓存请求

这是一个开发的最佳实践,使得你可以从你的Node实例之外得到更多的关联(通过pm2,你可以得到的不止一个,见上)。需要使用的方法是让Node服务器做类似请求,处理数据和执行业务逻辑的应用程序,并将流量卸载到另一个Web服务器(如Apache httpd或Nginx)的静态文件。 你可能又要使用Docker进行设置:

FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf

我喜欢使用Docker组合来制作多容器(nginx,Node,Redis,MongoDB)。 例如:

web:
  build: ./app
  volumes:
    - "./app:/src/app"
  ports:
    - "3030:3000"
  links:
    - "db:redis"
  command: pm2-docker app/server.js

nginx:
  restart: always
  build: ./nginx/
  ports:
    - "80:80"
  volumes:
    - /www/public
  volumes_from:
    - web
  links:
    - web:web

db:
  image: redis

总结

在这个软件开源的时代,没有借口不从开放的可信的和被测试过的代码中学习。你无需在核心圈便可以触及。学习永远不会停止,通过实践带来的失败和成功,我相信很快我们将有不同的最佳实用技巧。 这是肯定的。

最后,我想谈一谈软件是如何吞噬着这个世界,而世界是如何正在被JavaScript吞噬的。。。有很多伟大的东西,比如每年发布的标准,大量的npm模块,工具和参考等等。。。然而对此最终我表示谨慎。

我看到越来越多的人在追逐下一个新的框架或语言。 它是闪光物体综合征。 他们每个星期都学习一个新的库,每个月学习一个新的框架。 他们强制自己每周刷Twitter,Reddit,Hacker News和JS。 强制性的行为导致在JavaScript领域中的拖延。却没有一条GitHub记录。

学习新东西是好的,但不要误以为它就是实际建立出东西。 实际上是你建立的东西至关重要并劳有所得。 停止过多的工程理论。 你不是建立下一个Facebook。 Promises vs. generator vs. async await对我来说算不上是个问题,因为此时在讨论中已有人对于单个线程做出回复,我已经写了我的回调函数(并且使用CoffeeScript做到比普通ES5 / 6/7快2倍的速度! )。

最后,最佳的实践是使用最佳实践,掌握基础知识是最重要的。 阅读源代码,在代码中尝试新东西,最重要的还是自己输出成吨的代码。 现在,就在此时,有意义的十停止阅读和去发布代码!

以防本篇文章不够,这里是一些更好的节点Node阅读材料:

https://blog.risingstack.com/nodejs-at-scale-npm-best-practices

https://devcenter.heroku.com/articles/node-best-practices

https://blog.risingstack.com/node-js-best-practices

https://expressjs.com/en/advanced/best-practice-performance.html

https://www.codementor.io/nodejs/tutorial/nodejs-best-practices


往期精选文章

使用虚拟dom和JavaScript构建完全响应式的UI框架

扩展 Vue 组件

使用Three.js制作酷炫无比的无穷隧道特效

一个治愈JavaScript疲劳的学习计划

全栈工程师技能大全

WEB前端性能优化常见方法

一小时内搭建一个全栈Web应用框架

干货:CSS 专业技巧

四步实现React页面过渡动画效果

让你分分钟理解 JavaScript 闭包



小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京程一灯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于作者的其它文章:
  • 使用 npm Scripts
  • 使用 Env Vars (环境变量)
  • 理解事件循环
  • 使用Functional Inheritance
  • 适当地取名
  • Consider NOT Using JavaScript
  • 了解Express中间件
  • Scale up
  • 缓存请求
  • 总结
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档