低代码到底是不是行业毒瘤?一线大厂怎么做的?戳此了解>>> 了解详情
写点什么

快乐 Node 码农的十个习惯

2014 年 4 月 23 日

从问世到现在将近 20 年,JavaScript 一直缺乏其它有吸引力的编程语言,比如 Python 和 Ruby,的很多优点:命令行界面,REPL,包管理器,以及组织良好的开源社区。感谢 Node.js 和 npm,现如今的 JavaScript 鸟枪换炮了。Web 开发者有了强大的新工具,接下来就看他们的想象力了。

下面这个提示和技巧清单,能让你和你的 node 程序保持快乐。

1. 用 npm init 开始新项目

npm 有个 init 命令,可以引导你完成创建 package.json 文件的过程。即便你非常熟悉 package.json 和它的属性,也可以把 npm init 当作将你的新程序或模块导入正轨的简便办法。 它可以聪明地为你设置默认值,比如通过上层目录的名称推断模块名,从~/.npmrc 中读取创作者的信息,以及用你的 git 设置确定代码库。

复制代码
mkdir my-node-app
cd my-node-app
npm init

2. 声明所有依赖项

在将模块安装到项目本地时坚持使用–save (或 --save-dev) 是个好习惯。这些选项会将指定的模块添加到 package.json 的 dependencies(或 devDependencies)清单中,并使用合理的默认 semver 范围

复制代码
npm install domready --save

注意,现在 npm 使用插入符风格的 semver 范围

复制代码
"dependencies": {
"domready": "^1.0.4"
}

3. 指定启动脚本

在 package.json 中设定 scripts.start,你就可以在命令行中用 npm start 启动程序了。这个非常方便,因为克隆了你的程序的其他 node 开发人员不用猜就能轻松运行它。

额外奖励:如果在 package.json 中定义了 scripts.start,你就不需要 Procfile 了(Heroku 平台用 Procfile 来声明在你程序的 dynos 上运行什么命令)。使用 npm start 会自动创建一个作为 web 进程的 Procfile。

这里有个启动脚本示例:

复制代码
"scripts": {
"start": "node index.js"
}

4. 指定测试脚本

就像团队中的所有人都应该可以运行程序一样,他们也应该可以测试它。package.json 中的 scripts.test 就是用来指定运行测试套件的脚本的。如果你用 mocha 之类的东西运行测试,一定要确保把它包含在 package.json 里的 devDependencies 中,并且指向安装在你项目本地的文件,而不是全局安装的 mocha:

复制代码
"scripts": {
"test": "mocha"
}

5. 不要把依赖项放在源码的版本控制中

很多 node 程序使用的 npm 模块带有 C 语言写的依赖项,比如 bson、ws 和 hiredis,这些依赖项必须在 Heroku 的 64 位 Linux 架构下进行编译。编译过程可能非常耗时。为了让构建过程尽可能的快,Heroku 的 node buildpack 在下载和编译完依赖项后会缓存它们,以便在后续部署中重用。这个缓存是为了降低网络流量并减少编译次数。

忽略 node_modules 目录也是模块创作者推荐的 npm 实践。应用程序和模块之间少了一个区别!

复制代码
echo node_modules >> .gitignore

6. 用环境变量配置 npm

以下内容摘自 npm 配置

所有以 npm_config_ 开头的环境变量都会被解释为配置参数。比如说环境中有 npm_config_foo=bar 时,会将配置参数 foo 设置为 bar。任何没有给出值的环境配置的值都会设置为 true。配置值对大小写不敏感,所以 NPM_CONFIG_FOO=bar 也一样。

最近在所有的 Heroku 构建中都有程序的环境。这一变化让 Heroku 上的 node 用户无需修改程序代码就可以控制他们的 npm 配置。习惯#7 是这一方式的完美例证。

7. 带着你自己的 npm 注册中心

最近几年公共 npm 注册中心出现了突飞猛进式的增长,因此会偶尔不稳定。所以很多node 用户开始寻求公共注册中心之外的方案,他们或者是出于开发和构建过程中速度及稳定性方面的考虑,或者是因为要放置私有的node 模块。

最近几个月冒出了一些可供选择的npm 注册中心。 Nodejitsu Gemfury 提供收费的私有注册中心,此外也有一些免费的,比如 Mozilla 的只读 S3/CloudFront 镜像 Maciej Małecki 的欧洲镜像

在 Heroku 上配置 node 程序使用定制注册中心很容易:

复制代码
heroku config:set npm_config_registry=http://registry.npmjs.eu

8. 追踪过期的依赖项

如果你编程的时间足够长,可能已经领教过相依性地狱的厉害了。好在Node.js 和npm 接纳了semver,即 语义化版本管理规范 ,设置了一个健全的依赖项管理先例。在这个方案下,版本号和它们的变化方式传达的含义涉及到了底层代码,以及从一个版本到下一版本修改了什么。

npm 有一个很少有人知道的命令,outdated。它可以跟 npm update 结合使用,能够找出程序的那些依赖项已经过期了,需要更新:

复制代码
cd my-node-app
npm outdated
Package Current Wanted Latest Location
------- ------- ------ ------ --------
express 3.4.8 3.4.8 4.0.0-rc2 express
jade 1.1.5 1.1.5 1.3.0 jade
cors 2.1.1 2.1.1 2.2.0 cors
jade 0.26.3 0.26.3 1.3.0 mocha > jade
diff 1.0.7 1.0.7 1.0.8 mocha > diff
glob 3.2.3 3.2.3 3.2.9 mocha > glob
commander 2.0.0 2.0.0 2.1.0 mocha > commander

如果你做的是开源的 node 程序或模块,可以看看 david-dm NodeICO shields.io ,你可以用这三个优秀服务所提供的图片徽章在项目的 README 或网站上显示生动的依赖信息。

9. 用 npm 脚本运行定制的构建步骤

随着 npm 生态系统的持续增长,开发和构建过程的自动化选择也会随之增长。 Grunt 是迄今为止 node 世界中最流行的构建工具,但像 gulp.js 这种新工具,以及普通的老式 npm 脚本也因为较轻的负载受到欢迎。

在你把 node 程序部署到 Heroku 上时,要运行 npm install --production 命令以确保程序的 npm 依赖项会被下载下来装上。但那个命令也会做其它事情:它会运行你在 package.json 文件中定义的所有 npm 脚本钩子,比如 preinstall 和 postinstall。这里有个样本:

复制代码
{
"name": "my-node-app",
"version": "1.2.3",
"scripts": {
"preinstall": "echo here it comes!",
"postinstall": "echo there it goes!",
"start": "node index.js",
"test": "tap test/*.js"
}
}

这些脚本可以是行内 bash 命令,或者也可以指向可执行的命令行文件。你还可以在脚本内引用其他 npm 脚本:

复制代码
{
"scripts": {
"postinstall": "npm run build && npm run rejoice",
"build": "grunt",
"rejoice": "echo yay!",
"start": "node index.js"
}
}

10. 尝试新东西

ES6,也就是被大众称为 JavaScript 的 ECMAScript 语言规范的下一版,其工作名称为 Harmony。 Harmony 给 JavaScript 带来了很多振奋人心的新特性,其中很多已经出现在较新版本的 node 中了。

Harmony 实现了很多新特性,比如块作用域生成器代理弱映射等等。

要在你的 node 程序中启用 harmony 的特性,需要指定一个比较新的 node 引擎,比如 0.11.x,并在启动脚本中设置–harmony 选项:

复制代码
{
"scripts": {
"start": "node --harmony index.js"
},
"engines": {
"node": "0.11.x"
}
}

11. Browserify

客户端 JavaScript 有乱如麻团般的遗留代码,但那并不是语言本身的错。由于缺乏合理的依赖项管理工具,让 jQuery- 插件拷贝 - 粘帖的黑暗时代延续了好多年。感谢 npm,带着我们步入了前端振兴的年代:npm 注册中心像野草一样疯长,为浏览器设计的模块也呈现出了惊人的增长势头。

Browserify 是一个让 node 模块可以用在浏览器中的神奇工具。如果你是前端开发人员,browserify 将会改变你的人生。可能不是今天,也不是明天,但不会太久。如果你想开始使用 browserify,请参阅这些文章

你有哪些习惯?

不管你已经做过一段时间node 程序,还是刚刚开始,我们都希望这些小技巧能对你有所帮助。如果你有一些(健康的)node 习惯想要跟大家分享,请在发tweet 时带上#node_habits 标签。编码快乐!

作者简介

本文最初由 Zeke sikelianos 发表在 Heroku 上。Zeke 在 Heroku 工作,用 ruby 和 coffeescript 编写开源软件。他从事设计师这一职业已经有 14 年了,信奉信息自由的精神,并且相信用计算机可以创造出美好的事物。

查看英文原文: What’s New in Node.js v0.12 – Running Multiple Instances in a Single Process


感谢吴海星对本文的策划。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2014 年 4 月 23 日 00:5312216
用户头像

发布了 45 篇内容, 共 22.5 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

Java 集合(6.1)-- Collection 和Collections什么关系?

秦怀杂货店

Java collection 集合 Collections

Java 集合(8)-- ArrayList 源码解析

秦怀杂货店

Java 源码 集合 ArrayList

JDBC【1】-- 初级入门之增删改查

秦怀杂货店

数据库 jbdc crud

JDBC【2】-- 工作原理以及简单封装

秦怀杂货店

Java JDBC 工作原理

常用Git命令速查手册

jiangling500

git

大量类加载器创建导致诡异FullGC

AI乔治

Java 架构 JVM GC

Java集合(1)-- 俯瞰Java集合源码以及分类

秦怀杂货店

Java 源码 Iterator和Iterable JAVA集合

Java 集合(6)-- Collection源码解析

秦怀杂货店

Java 源码 collection 集合 JAVA集合

甲方日常 51

句子

工作 随笔杂谈 日常

线程池运用不当的一次线上事故

AI乔治

Java 架构 高并发 线程池

四周 习题与总结

水浴清风

Java 集合(5)-- Collections源码解析

秦怀杂货店

Java 集合 Collections

Java 集合(7)-- List 接口源码解析

秦怀杂货店

Java List 源码 集合 java集合使用

架构师训练营第八周作业

四夕晖

Mybatis【1】-- 第一个Mybatis程序

秦怀杂货店

mybatis 入门 教程

一次“诡异”的JVM缓存加载问题排查

AI乔治

Java 缓存 架构 JVM

记一次 Java 服务性能优化

AI乔治

Java 架构 性能优化 高性能

SpringBoot系列(5)- 自定义配置

引花眠

springboot

Java 集合(9)-- Vector超级详细源码解析

秦怀杂货店

Java 源码 集合 ArrayList vector

踩了一个java命令行参数顺序的坑

AI乔治

Java 架构 stream

Mybatis【2.1】-- 从读取流到创建SqlSession发生了什么?

秦怀杂货店

数据库 mybatis SQLSession

Java 集合(4)-- iterable和iterator异同分析

秦怀杂货店

Java Iterator和Iterable 集合 iterable

ARTS打卡 第24周

引花眠

微服务 ARTS 打卡计划 springboot

Mac 安装Homebrew慢的问题解决

秦怀杂货店

Mac homebrew

Mybatis【2】-- 多个mapper文件以及namespace作用

秦怀杂货店

mybatis Mapper namespace

免费图床+CDN:GitHub+jsDeliver

jiangling500

GitHub CDN 免费图床 jsDeliver

JDBC【3】-- SPI技术以及在数据库连接中的使用

秦怀杂货店

数据库 spi

ARTS打卡 第23周

引花眠

微服务 ARTS 打卡计划 springboot

Scala语法特性(二):控制语句及函数方法

正向成长

Scala函数 Scala控制语句

Java集合(2)-- Iterator接口超级详细解读

秦怀杂货店

Java 源码 Iterator和Iterable 集合 Iterator

Java集合(3)-- iterable接口超级详细解读

秦怀杂货店

Java 源码 Iterator和Iterable 集合 iterable

2021 ThoughtWorks 技术雷达峰会

2021 ThoughtWorks 技术雷达峰会

快乐Node码农的十个习惯-InfoQ