前段时间,我们邀请了我们“城内”(葡萄城)资深开发工程师刘涛为大家分享了一次干货满满的关于Electron线上公开课,在课程过程中有不少同学对于NPM的概念和用法有一些疑问,所以这次我们希望通过这篇文章来解答各位同学的问题。另外在介绍的基础上,我们还会适当的深入介绍下,如何在npm上发布第一个属于自己的包。那么,让我们马上开始吧!
得益于Node.js的模块化生态系统,我们基本上可以把NPM认为是任何Node项目的基础组成的一部分。但实际上,我们甚至可以说NPM是Node.js开发人员在开发者社区中最重要的工具之一。毕竟,他们每天都使用它来管理他们的项目使用的包。
但是,除了用它安装软件包外,大家是否真正深入了解过NPM呢?因此,我将尝试介绍该工具的基础知识,让您更深入地了解并使用它,而不是仅仅了解npm install而已。
包管理
我们都知道你可以使用NPM安装软件包,但究竟是什么意思呢?包基本上是包含您需要的代码的文件夹,您可以在本地或全局安装它。
本地安装
本地安装意味着您实际上将文件下载到项目的文件夹中。在其中,您将找到一个您未创建的目录,称为“node_modules”。由于这种简单的机制,这个本地文件夹可能会变得非常大。
那么究竟这个文件夹有多大?一张图来为你形容:
其实这只是个玩笑,通常你可以忽略该文件夹,让Node.js为你处理它。
要执行本地安装,您只需:
$ npm install [package-name]
您可以添加—save
后缀,Node会把包名称和版本保存到您的package.json
文件中。请记住,这一点很重要(甚至至关重要),因为当你作为团队中的一份子在工作时,你不会分发,也不会将node_modules文件夹添加到版本控制系统(无论是GIT,SVN还是你正在使用的任何版本管理系统),而只需简单地分享package.json
文件,然后让你的队友执行$npm install
命令,即可完成包的安装和更新。这比共享整个文件夹更快,更容易维护,整个文件夹可以增长到包含千兆字节的数据。
以下是一个package.json
文件的结构:
{ |
|
| "name": "Project name", |
| "version": "1.0.0", |
| "description": "This is a basic description", |
| "main": "index.js", |
| "scripts": { |
| "test": "echo \"Error: no test specified\" && exit 1" |
| }, |
| "author": "Fernando Doglio", |
| "license": "ISC", |
| "dependencies": { |
| "config": "^3.1.0", |
| "express": "^4.17.1", |
| "socket.io": "^2.2.0", |
| "winston": "^3.2.1" |
| } |
} |
|
您可能会改变一些,具体取决于您安装的软件包,或者您需要的文件的哪些字段(上面的示例中没有使用的其他许多字段)。
全局安装
您还可以全局安装软件包,这意味着Node.js将能够从您可能需要的任何项目中访问它们。这样做有什么问题吗?全局安装的包不会添加到package.json
文件中,那么既然不会添加到package.json中,那么为什么要安装全局安装呢?
使用Node.js和NPM能做的一个很棒的原因之一就是构建人们通常称之为“二进制文件”的东西,它们只是可以全局安装的脚本,因此可以从盒子的任何位置访问。这意味着您可以创建命令行工具并使用NPM来安装它们!
例如:ExpressJS(Node.js最受欢迎的Web框架之一)或mocha(非常流行的测试库)等软件包也附带了可以使用的可执行二进制文件。例如,mocha要求您在全局和本地安装它,以便拥有一个名为“mocha”的CLI工具,并能够在本地项目上运行测试。
全局包在需要添加到PATH环境变量的常规路径中创建符号链接(或快捷方式)。
NPM的经典命令
install
命令只是您可以与NPM一起使用的众多命令之一。事实上,抛开近60种不同的命令(是的,就这么多!),我将简要介绍一下,NPM还允许你创建自己的自定义命令,以防止内置命令对你不够用。
以下是最常见的命令列表,取自官方文档:
access:设置已发布包的访问级别,限制或启用除作者之外的其他人的访问权限。例:$ npm access public
adduser:将用户帐户添加到注册表(默认情况下,注册表是npm的注册表,但您可以指定自定义帐户)。例:$ npm addUser
当提示时,将输入用户凭据(用户名和密码)及其电子邮件。
audit:对已安装的依赖项运行安全审核,确保没有已知的漏洞影响它们(以及扩展,您的项目)。您甚至可以使用该标志fix
自动修复在审核期间可能发现的任何问题。
bin:显示当前项目的NPM bin文件夹。
bugs:打开新浏览器窗口中的错误列表。关于这个命令的有趣的一点是,它试图猜测包的当前错误跟踪器,一旦找到它,它就会启动一个新的浏览器窗口。
cache:虽然开发人员通常不会使用此命令,但它允许它们清除,验证或向NPM的缓存添加内容。在该缓存中,存储HTTP请求信息和额外包数据。通常这是由NPM直接处理并且对开发人员透明地工作,但是如果你看到一些奇怪的行为,特别是当在不同的包和它们的不同版本之间切换时,尝试清除缓存可能是个好主意(只是为了开启)安全的一面)。
ci:几乎与npm install
用于自动化环境(例如持续集成过程)相同。此命令比此命令更严格,install
并确保安装始终是干净的(如果存在,它会自动删除node_modules文件夹)。
completion:为npm及其子命令启用Tab Completion。阅读完整文档以获取更多详细信息。
config:允许您设置,获取和编辑NPM的配置选项。
dedupe:尝试通过遍历依赖关系树并在尽可能远的层次结构中移动重复的条目来减少依赖关系的重复。当您的应用程序开始增长并包含越来越多的模块时,这尤其有用。使用此命令绝对是可选的,但如果您有很多依赖项,它将在安装期间(在CI / CD环境中最有用)提供相当大的减少。
deprecate:在库的注册表中为特定版本(或版本范围)添加弃用警告。
dist-tag:帮助管理特定包的标签。标签可以充当版本别名,以帮助识别版本而无需记住数字。例如,默认情况下,最新标记用于所有库的最后一个版本,您只需运行npm install library-name@latest
,NPM将了解要下载的库的哪个版本。
docs:就像bug一样,这个命令试图猜测软件包的官方文档在哪里,并在本地浏览器中打开该URL。
doctor:执行一组预定义的检查,以确保正在执行NPM的系统已准备好最低要求:node
和git
命令是可访问和可执行的,node_modules
文件夹(本地和全局)可由NPM,注册表写入或者它的任何自定义版本都是可访问的,最后,NPM缓存存在并且它正在工作。
help-search / help: 帮助将显示给定术语的文档页面,如果没有找到结果,help-search将对NPM的markdown帮助文件执行全文搜索并显示相关结果列表。
hook:允许您配置新的NPM挂钩,当对感兴趣的包进行更改时,它会通知自定义URL。例如,通过键入以下内容可以在发布新版ExpressJS时收到通知:反过来,您可以使用该信息执行任何您喜欢的操作(例如自动更新依赖项)。$npm hook add express
http://your-url.com/new-express-version-endpoint
init:通过询问一系列问题来帮助初始化项目,例如名称,版本,作者等。最后,package.json
使用该信息创建一个全新的文件。您还可以提供自定义初始化程序,以自定义处理到您的特定堆栈。
install:安装新包。您可以指定程序包的位置及其格式(即,您只能提供一个名称,以便在主注册表中查找它,或者在下载要安装的程序包的tarball文件的路径中)。如果您不希望每次运行此命令时都安装最新版本,则还可以指定要安装的版本(对于自动环境(如CI / CD)尤其有用)。
ls:列出当前项目的所有已安装软件包。您可以列出全局包或本地安装的包。在任何一种情况下,它不仅会列出package.json
文件中可见的名称和版本,还会列出它们的依赖关系及其版本。
outdated:检查项目中过时的包。它将为您提供已安装软件包的报告,其当前版本,package.json
文件期望的版本以及主注册表中发布的最新版本。
owner:允许您管理包所有者。如果您是图书馆所有者或维护者,这一点很重要,但如果您仅限于使用包,则不是这样。
ping: ping当前配置的主npm注册表并测试身份验证。这仅在您下载或安装任何软件包时遇到问题。它只会帮助您解决部分问题,但重要的是要记住它。
prefix:显示当前前缀,换句话说,显示最近文件夹中包含package.json
文件的路径。您可以使用该-g
标志,您将获得安装全局包的实际位置。
publish:允许开发人员通过使用组和组织公开或私下与他人共享模块。
这些是您可以使用的最常见或最有用的NPM命令,但是仍然有超过10个额外的命令供您查看,因此我建议您将其文档添加为书签,并做一个注释以便返回并仔细检查它!
如何发布我自己的包
我要分享关于NPM知识的最后一点是与其他人分享你的工作是多么容易。在上一个列表中,最后一个命令是发布命令,它基本上允许你这样做,但在这里我想给你更多的细节。
准备项目的元数据
NPM的注册表本质上是一个巨大的包搜索引擎,能够同时托管所有内容,因此您不必同时索引它可以在您的工作中获得的每一点元数据,以帮助其他人找到您的模块尽快。
换句话说,请确保您package.json
的设置正确。因为这些内容是吸引您(以及其他人)开始研究及分享您的包的主要因素。
Name:这是列表中最明显和最常见的,也是您在创建package.json
文件以跟踪依赖关系时可能已经设置的名称。请注意它的唯一性。
Description:描述你的包,以便其他人可以快速了解他们在安装时会得到什么。并确保在描述中添加尽可能多的重要关键字,以便搜索引擎知道如何快速找到您。这是尝试找到您的软件包的开发人员的需求与引擎首先尝试正确索引的需求之间的平衡。
Tags:这是一个以逗号分隔的关键字列表。话虽这么说,一旦你开始发布包,这些标签就非常重要,因为在NPM的主站点上,它们可以作为你可以轻松浏览的类别。因此,如果您没有完善你package.json
中的标签属性,其他开发人员将很难通过分类导航找到你的包。
Private:除非您只是自用,否则您需要尽快设置该属性为false
,否则没有人能够通过关键字搜索找到您的模块。
Bugs:这确保如果您在某个地方托管了您的内容,例如存在公共问题跟踪的Github,则将此属性设置为正确的URL。这将帮助NPM显示链接并在包页面上显示当前打开的问题的数量。
Repository:不是严格要求的属性,但是如果你添加它,NPM将能够显示额外的信息,例如它的链接,活动,协作者列表,仅举几例。
Homepage:与前一个一样,它将帮助NPM显示指向此URL的单独链接(如果存在)。当您将代码放在一个URL(例如Github仓库)和专用于另一个URL中的模块的特定网站时,这尤其重要。
License:用于显示您在项目中设置的实际许可证。如果您将其添加为package.json
文件的一部分,它将以不同且更突出的方式显示。您也可以在readme.md上提及它,但在此处添加它将为NPM提供有关您的项目的额外知识。
通过提供我上面提到的元数据,NPM能够展示这些数据并突出显示它供开发人员查看。以下示例为Winston的包页面:
由于其团队添加了元数据,添加了多少链接以及额外的位和详细信息。
一份优秀的文档
这步是可选的,但如果你的包是一个可供其他开发人员使用的模块的话,那么我建议你最好提供一份优秀的文档,供他人参考。
因为你真的不能指望你的工具“上手简单、易于理解”。NPM
的目的是为其他人提供一套帮助他们解决问题的预置工具。因此,请尽量丰富你的文档,吸引更多人来使用你的工具吧。
正式发布包
编码完成后,将有效的package.json
放置到你的目录中,
并编写尽可能完善的readme.md
文件,您就可以发布了。
要执行发布操作,您必须做两件事:
使用npm
CLI 登录您的NPM帐户(如果您已经有了账号)。
发布您的代码。
也就是只需两步,就能简单的完成发布。登陆:
$ npm login
将提示您输入凭据,一旦您成功登录,您可以再输入:
$ npm publish
请在项目的文件夹中执行此操作,否则第二个命令将失败。
另外,请记住,包的名称将由您的package.json文件中的name属性给出,而不是来自文件夹的名称(通常二者都是相同的,但并这不意味着他俩有什么关系)。因此,如果您遇到重复的名称错误(考虑到NPM中已经有重名的包了),那么您就必须进行更改一个再次发布了。
结论
感谢阅读,我希望到现在为止,你已经了解了NPM的复杂性和美感。它不仅仅是一个安装软件包的简单工具,但如果你花时间检查文档,你可以用它做更多的事情。