1.2 NPM
当开发者想把自己编写的可复用模块分享给别人的时候,只需要复制给他就可以了;在同事之间进行分享的时候,也只需要通过邮件或通信工具进行发送即可。但是当开发者决定向技术社区贡献代码的时候,由于应用模块的人遍布世界各地,如何保证所有需要该模块的开发者都能够随时得到适用于各自系统的版本,并且在模块之间存在依赖关系的时候,也能够顺利找到所有的依赖项?答案就是使用模块管理工具。
NPM是一个JavaScript的模块管理工具,遵循CommonJS标准,由Isaac Z.Schlueter开发(Isaac Z.Schlueter同时也是Node.js的第二任“Gatekeeper”)。NPM完全用JavaScript写成,也是Node.js默认的模块管理工具,用于管理模块的安装、卸载和依赖项。Node.js与NPM的Logo如图1.11所示。
图1.11 Node.js与NPM的Logo
1.2.1 NPM介绍
NPM(Node Package Manager)官网地址为https://www.npmjs.com。Node.js社区的工具包非常丰富,前端开发者可以在NPM的官网上获取和上传模块、搜索社区资源。NPM中的单个模块通常只用来解决一个问题,例如模块Axios用来解决HTTP通信的问题,模块http-errors则用来创建HTTP错误信息。
NPM的常用命令见表1.1。
表1.1 NPM的常用命令
其他细节请参考官方文档https://docs.npmjs.com/,也可以在命令行中输入“npm -h”及“npm -l”来便捷地获取NPM命令行的使用方法。
提示:Facebook、Google、Exponent和Tilda于2016年开发了一款新的模块管理工具Yarn,在速度和可靠性上较NPM更加优秀。Yarn并没有完全取代NPM,然而已经有许多开发者对它表示青睐,使之成为与NPM齐名的Node.js模块管理工具。Yarn官网地址为https://yarnpkg.com/zh-Hans/。
1.2.2 NPM模块结构
完全符合CommonJS规范的模块应包含以下几个文件。
· package.json:模块的描述性文件。
· bin:存放可执行的二进制文件。
· lib:存放JavaScript代码。
· doc:存放文档。
· test:存放单元测试用例。
最低限度,模块应包含一个描述性文件package.json及一个存放模块代码的index.js文件。
package.json文件可通过npm init命令创建,NPM会在创建过程中对开发者进行引导,根据提示输入内容然后一步步按回车键进行确认即可。package.json文件包含了模块所有的依赖关系,也可以定义依赖项的元数据(如名称、版本、许可证等),package.json文件内容如图1.12所示。
图1.12 package.json文件内容
安装Koa的命令如下:
Koa安装成功会得到提示,如图1.13所示。
图1.13 Koa安装成功的提示
打开文件夹查看,发现除原本的package.json和index.js外增加了package-lock.json文件及node_modules文件夹。打开package.json,查看文件中增加的内容,如图1.14所示。
图1.14 变化后的package.json文件
每安装一个新的模块,NPM会自动在package.json文件中写入模块的相关依赖信息。
package.json文件常用的字段见表1.2。
表1.2 package.json文件常用的字段
续表
提示:在官网文档中有关于各字段更详细的介绍,地址为https://docs.npmjs.com/files/package.json。
test文件夹内新增加的node_modules文件夹是在执行npm install命令时NPM自动创建的,打开它能够看到所有已经安装的模块,包括刚刚安装的Koa和所有依赖项。执行npm install命令的输入和输出示意图如图1.15所示。
图1.15 执行npm install命令的输入和输出示意图
理论上,对于相同的package.json文件,输入安装命令,输出的模块包应该是一致的。然而事实并非如此,得到和预想一致的模块包在NPM 5.0版本之前是个让用户头疼的问题。原因可能如下:
· NPM采用的安装算法稍有不同。
· 在最近一次安装之后,模块进行了版本更新,于是会自动采用最新版本(而非预先设定的版本)。
· 即使锁定了版本信息,如果模块的依赖包进行了更新,模块也会自动更新。
· 更换了新的下载源。
这些都是因为NPM的版本兼容机制非常宽松造成的。NPM定义的版本是向后兼容的,以安装Koa为例,配置如下:
定义的是只要在大版本号“2”上相同,就允许下载最新版本的Koa。也就是说,实际上得到的版本也许是2.5.2。符号^表示的是大于某个版本号。
虽然NPM的模块开发原则是大版本相同的接口必须保持兼容,然而这个原则并非强制执行,因此用户下载的最新版本也许会导致依赖包的行为完全不兼容,从而导致模块不可用。package-lock.json锁定了依赖版本号,只要保存了源文件,就能够确保得到完全一致的依赖包,从而提高了模块的稳定性和可用性。
因此,package-lock.json就是NPM为了防止模块包的不一致而进行的功能加强,这也是在Yarn冲击下的必然结果。这个文件在运行命令npm install的时候为了锁定依赖版本和来源而由NPM自动创建,实际上记录了当前状态下安装的所有模块信息,确保了在下载时间、开发者、机器和下载源都不相同的情况下也能够得到完全一样的模块包。
1.2.3 使用NVM控制Node.js版本
在日常开发过程中经常会因为不同的项目所依赖的Node.js版本不同,而需要在不同的Node.js版本之间进行切换。如果缺乏可靠的工具,这将是一件非常麻烦的事情。
NVM(Node Version Manager,Node版本管理器)是在Mac环境下管理Node.js版本的工具,类似于管理Ruby的RVM(Ruby Version Manager,Ruby版本管理器)。在Windows环境下推荐使用nvmw或nvm-windows。本节将介绍NVM的安装过程及切换Node.js版本的方式。
1.卸载已经全局安装的Node.js和NPM(推荐,非必须)
从官网下载的Node.js会默认安装在全局环境中,需要执行以下步骤来完全删除与Node.js和node_modules相关的内容。
· 删除/usr/local/lib和/usr/local/include两个文件夹中所有和Node.js及node_modules相关的文件;
· 检查个人主文件夹下所有的local、lib、include文件夹并删除所有与Node.js和node_modules有关的内容;
· 从/usr/local/bin中删除Node.js的可执行文件。
提示:使用brew安装的Node.js还需要额外运行brew uninstall node命令来进行卸载。
除此以外,还有可能需要用到的命令如下:
2.安装NVM
在安装NVM之前还需要一个C++编译器,在Mac上可以安装Xcode命令行工具(如已安装请忽略)。
然后可以使用cURL或Wget安装NVM,命令如下:
或者
注意:请访问https://github.com/creationix/nvm查看当前最新版本。
输入以下命令:
如果安装成功会输出“nvm”,如果出现“nvm: command not found”,则可能有以下原因:
· 安装时系统缺少.bash_profile文件,使用touch ~/.bash_profile命令创建所需文件并重新安装NVM;
· 重启命令行工具,再次尝试输入该命令。
如果仍然提示安装失败,请打开.bash_profile文件并添加以下代码:
3.安装并切换不同Node.js版本
可能用到的命令如下:
提示:更多NVM命令的详细介绍可参考https://github.com/creationix/nvm#usage。
使用命令nvm ls列出本机所有已安装的版本,如图1.16所示。
图1.16 本机所有已安装的版本
4.配置项目所使用的Node.js版本
如果项目所需Node.js版本不是默认版本,可以在项目根目录下创建.nvmrc文件并在其中预先指定版本号,可能用到的命令如下:
配置好的Node.js版本如图1.17所示。
图1.17 配置好的Node.js版本
1.2.4 Web代理工具NProxy
前端开发者对Fiddler和Charles之类的Web代理工具应该都不陌生。这些工具使我们可以直接使用本机文件替换线上相应静态文件(JavaScript、CSS、图片等),从而调试线上问题。然而,不管是选择Fiddler、Charles、Rythem,还是Tinyproxy,总有一些需求无法完全满足:
· 同时支持Mac、Linux和Windows系统。
· 使用多个本地源文件替换线上的combo文件。
· 进行目录替换。
· 支持HTTP和HTTPS。
而这些就是NProxy存在的理由。NProxy是一个跨平台,支持单文件、多文件及目录替换,支持HTTP和HTTPS协议的Web代理工具,在文件替换功能上尤其出色。官网地址为https://www.npmjs.com/package/nproxy。
使用NPM进行安装(Node.js版本必须大于0.8.x),命令如下:
启动NProxy也非常简单,命令如下:
replace_rule.js文件为项目中由开发者创建的替换规则文件。NProxy提供的模板代码如下:
可按照项目的实际需求更改其中的配置项,其他常用指令还包括:
1.2.5 实战演练:在npm.org上发布一个模块
当我们开发出一个不错的Node.js模块时,也可以发布到NPM上供其他开发者使用。首先要做的是在https://www.npmjs.com/signup上注册账号,NPM账号注册页面如图1.18所示。
图1.18 NPM账号注册页面
然后进入项目目录运行命令npm adduser,并依次输入刚刚注册好的用户名、密码和邮箱(邮箱需要验证),再运行发布命令:
发布成功后输出的信息如图1.19所示。
图1.19 发布成功后输出的信息
最后,在NPM官网上搜索该模块,验证发布是否成功,已发布模块的搜索界面如图1.20所示。
图1.20 已发布模块的搜索界面