npm入门(二)—package(包)的管理

5,561 阅读14分钟

前言

上一篇 npm入门(一)—了解基本组成与概念 简单介绍了一下npm的相关知识,这篇可以说是npm的核心知识。

分类

关于pacakge,是有分为public pacakge(公共包)、private pacakge(私有包)。前面我们也知道npm账号也有两种,一直的免费用户,一个是付费用户。私有包是付费用户才能发布的。

直观地,在npn website上看,package前面会有个标签标注该包是公有的还是私有的

scopes

在此之前,我们先了解这么一个概念——scopes(中文意思是作用域)。我们在注册npm账号和创建组织时,你将被授予一个与你的用户或组织名称匹配的范围,即你获得了一个适用范围(scope),这个范围是你的用户名或者创建的组织名。你可以将此范围用作相关包的命名空间。如你有一个package名叫mypackage,你的用户名为myusername,则你可以把这个package放到你的域里

@myusername/mypackage

这样有什么作用呢?

  1. 避免与别人的包重名,发生冲突。
  2. 限制该包的访问权限。假设你是付费用户,想要创建一个私有包,那么可以在你的域里授权哪些用户才能访问

public package

默认地,如果我们不对registry进行了任何设置,那么发布的包就是基于默认的registry(http://registry.npmjs.org)的,发布出来的包是公共的,任何人都可以访问使用。

public package也有两种:

  • unscoped package:这个就是普通的共用包了,没有指定范围
  • scoped package:这个是在划分了范围的包,默认是私有的,但是手动转化为共有的。

private package

私有包,只有付费用户才能创建。私有包,是指只有授权用户才能进行下载发布等管理,而且还能指定各种权限,例如只读只写之类的。

私有包肯定是指定了范围的(scoped),默认地,指定了范围的包都是私有包(当然后面可以手动更改)

私有包可以划分两种

  • 用户范围的私有包:只能由你和你授予读或读/写访问权限的协作者访问。
  • org(组织)范围的私有包:只能被授予读或读/写访问权限的团队访问。

包类型的转换

上面我们知道包的一些分类,那么,如何在需要时改变它们的类型呢?

公有转私有

在npm website上操作的方法就不说了,直接说敲命令的方式:

npm access restricted <pacakge-name>

<pacakge-name>替换为真实包名

私有转公有

在npm website上操作的方法就不说了,直接说敲命令的方式:

npm access public <pacakge-name>

<pacakge-name>替换为真实包名

需要注意的是,只有是付费用户才能转为私有。

私有包授权用户

私有包有时候为了协作,需要添加其他开发者进行一起管理,所以需要把私有包授权给某些用户。根据私有包类型

用户私有包

在npm website上操作的方法就不说了,直接说敲命令的方式:

npm owner add <user> <your-package-name>

组织私有包

要授予npm用户对私有组织包的访问权,您必须有一个组织所有者将它们添加到您的组织中,然后将它们添加到有权访问私有包的团队中。具体步骤参考 这里


创建package

说了那么多,是时候应该知道,如何创建一个package了。

进入你想要创建package的文件夹根目录中,运行以下命令

npm init

进行npm项目(package)的初始化,当运行这个命令后,会出现一个问卷,例如问你项目的名称,作者,描述等信息,你按照实际情况输入回应即可。填完问卷后,会在该目录下生成一个package.json文件,该文件里包含刚回应问卷的一些信息。

如果你懒得一个个回应,可以使用默认的情况,运行

npm init --y 或者 npm init --yes

这样会自动根据你当前目录的情况,生成一系列默认信息在package.json文件。

当然我们也可以设置一些init时的固定指定信息,如

npm set init.author.name xxxx
npm set init.author.email xxxx

这里就设定了init时固定作者信息是啥

如果你想创建的是指定域的包,那么运行

npm init --scope=@yourscopename

yourscopename替换成你想要起的域的名称

package.json

上一篇我们说过,package是由一个package.json文件描述组织起来的,所以这个文件至关重要。先大概看一下这个文件长哪样

{
  "name": "xxxx",
  "version": "1.0.0",
  "description": "xxx",
  "author": "myname <myname@xxx.com>",
  "private": true,
  "scripts": {
    "dev": "concurrently \"webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --env.sysName=eod\" \"node mock-server.js\""
  },
  "dependencies": {
    "vue-router": "3.0.1"
  },
  "devDependencies": {
    "autoprefixer": "7.1.2"
  },
  ...
}

挑了些常用常见的内容展示出来。

属性 描述
name 必需。package的名称
version 必需。package的版本,遵循semantic versioning spec(语义版本控制规范)
description 推荐。用来描述你的package的一些信息,方便别人在npm website上查找你的pacakge
author 作者的相关信息。格式Your Name <email@example.com> (http://example.com)。包含了你的名称、邮箱和博客之类的网址,不一定要全写
private 你的package是私有的还是公有的
scripts 一些npm脚本,形成npm指令,方便你进行某些工作,如构建
dependencies 这是你的package发布后,罗列的所需要依赖的一些别人的package,缺乏了这些package,你的package也会不能如期正常工作
devDependencies 这里是罗列你在开发过程中所依赖的一些package,为了方便你的开发所用的包,缺少他们也不会影响到你的包发布后的正常使用,就放在这里了。

作用

  1. 从文件里能看出,该包的一些基础信息,以及所依赖的一些包
  2. 能看出所依赖的包的一些版本信息
  3. 使你的构建具有可重复性,因此更容易与其他开发人员共享

README.md

顾名思义,这个相当于用该package之前先看它的意思,即使用手册之类的意思。一般地,推荐package包含这个文件比较好,方便用户使用你的包。这个文件是使用markdown语法

此文件只有在发布包的新版本时才会在包页面上更新。

发布package

发布package之前,要好好检查你的文件里是否包含某些私人信息,敏感信息。请注意删除或者发布时忽略掉。使用.npmignore.gitignore文件来忽略掉,详情见

发布包命令:

npm publish
  1. 如果要发布一个未指定域的公用包,直接运行上述命令即可。
  2. 如果要发布一个指定域的私有包,直接运行上述命令即可(默认指定域是私有包)。需要注意的是,publish之前要注意npm所在registry,如你要发布到公司的registry里,则发布前需要切换到公司registry下,才运行该命令,例如使用上一篇提到的npmrc工具
  3. 如果要发布一个指定域的私有包进行公有化,运行
npm publish --access public

pacakge的版本控制规范

一个package一定要指定某个版本,而为了规范网络上大家各种各样的package,方便大家交流共享等,就制定了一个版本控制规范,大家在给自己package指定版本/更新版本的时候就好好考虑版本号了。

以当前版本为1.0.0为例子,遵循以下规范:

更新情况 位置 version
修复当前版本的一些bug 第三位 1.0.1
新增向后兼容的新特性 第二位 1.1.0
进行了破坏性地无法向后兼容的更改 第一位 2.0.0

在package.json里,我们看到依赖项里,包的版本信息里会出现^~符号。这里要知道这些符号代表什么意思。例如

"eslint": "^3.19.0",
"css-loader": "~3.19.0",

代表安装这个包的版本信息是浮动的,而不是指定死版本。

  • ^代表固定主版本号的,其余号浮动,如^1.3.0,高于等于1.3.0,1.x.x都符合,但是要低于2.0.0

  • ~代表固定次版本号的,修订号浮动,如~1.3.0,高于等于1.3.0,1.3.x都符合,但是要低于1.4.0

为package打tag

虽然package已经有版本号作为一些信息反馈给用户,但是语义化不够,不够直观明了,因此可以为package加上tag,即标签,为其备注一些信息,让用户更浅显易懂点。如运行

npm publish --tag beta

在发布时,就为package打上了beta标签了。

默认地,发布时会自动继承这个包上次发布的标签的信息,如上次打了个beta标签,后面直接运行npm publish时,也会自动应用上beta标签。

需要注意的是,tag名尽量不要使用数字或者v(不论大小写)开头的名字,因为tag的命名空间和版本号是一起的,会发生冲突。

如果想要指定版本进行打标签,运行

npm dist-tag add <packagename>@<version> tagname

npm dist-tag add vue@1.2.0 beta

发布后对于package的管理

更新版本

当你在维护一个包时,免不得了在调整之后需要对版本进行改变,以告知使用你的包的人,运行以下命令进行更新版本并进行发布

npm version <new-version>
npm publish

弃用与取消弃用package

弃用

当你不再想维护一个package,你需要告知那些依赖了你的包的人,让他们知道你的这个包你不再进行维护了,这是出于你的责任心啦。运行

npm deprecate <package-name> 'message'

这里的message就是你需要告知别人你的一些关于弃用的消息,这里一定要带上这个消息哦,不然就是另一个含义了。

如果你只想弃用某个版本,而不是整个package,运行

npm deprecate <package-name>@<version> 'message'

注意:弃用之后别人在npm的网站上会搜不出你的包来哦。访问你的包的网页也会有标识表名你的包给弃用了。别人在安装你的包时也会出现弃用的消息

取消弃用

如果日后你又回心转意了,想继续维护这个包,那么你就可以取消弃用了。运行

npm deprecate <package-name> ''

大家留意到吗,这里跟弃用的命令很像,唯一的区别在于,之前的message替换成'',这样就可以取消弃用了

转移package

如果你不想维护你的包了,你可以选择弃用,也可以选择转移你的包,希望它再找个主人吧。你可以把你的包转移给@npm,运行

npm owner add npm <package-name>
npm owner rm <user> <package-name>

上面的两句命令就是,为你的package添加授权给npm,然后删除你对该包的拥有权。<user>为你的账号名

所以,当转移了包之后,你就没了对它的使用权了,也不能更新它。

取消发布

发布了一个包之后,如果日后你不想让它再出现了,又不想仅是标志弃用,那么可以选择取消这个包的发布。当然这个行为可能会对别人产生不好的影响,例如别人依赖你的包,你无声无息地把这个包给取消掉了,叫别人情何以堪。

当你发布了一个公共package之后,72小时内后悔了,可以运行

npm unpublish <package-name> -f

如果你仅想取消某个版本,运行

npm publish <package-name>@<version>

如果是72小时后,那么需要联系 npm support了。如果你想取消的是一个组织包,非个人包,那么需要联系 enterprise@npmjs.com

安装package

我们已经了解过了pacakge的基本情况,知道从他的创建到发布,到发布后的管理。都是从自身作为包的拥有者角度去处理包,那么现在是时候作为一名使用者角度,知道如何使用别人的包了。

使用别人的包,首先就得安装下载他们的包,安装分为两类:

  • local install (本地安装)
  • global install (全局安装)

本地安装

例如在你的某个项目中,需要使用到别人的一些包,那么需要在你这个项目下下载安装所需的包,下载下来的包只会在该项目中被引用。

换个思路去理解,就是像很久以前开发一个项目,需要引入某个类库,如jquery,那么就下载jquery.min.js,放在项目里某个文件夹里,然后在适当的位置引入它来进行使用,如在index.html里通过script标签进行引用。这样的话,其实这个jquery.min.js只会在这个项目里被引入使用,而不能在第二个项目B中被引用,因为它是被放在项目A里面了,这种就是本地安装

运行以下命令进行本地安装:

npm install 

会依据项目中的package.json文件的依赖项以及声明的semver规则的最新版本来进行安装对应的包。如果该项目里没有node_modules文件夹,那么会新建一个,里面内容就是安装的package代码,如果有,那么直接在这个文件夹下新增pacakge

如果想要安装指定某个包(私有包请带上@域名/),运行

npm install <package-name>

如果项目里没有package.json文件,那么会下载指定包的最新版本,如果存在,会下载package.json中声明的semver规则的最新版本。

如果想要指定依赖的类型(dependencies, devDependencies等)

npm install <package-name> --save

加上--save是指该package是生产依赖项,存放在package.jsondependencies里,其实这是个默认的行为,即就算不加上--save,默认也是放在dependencies里。

如果想放在开发依赖里,运行

npm install <package-name> --save-dev

如果想要安装指定版本或者tag的包,运行

npm install <package-name>@<version>
npm install <package-name> <tag>

需要注意的是,如果是指定了某个tag的package进行安装,那么下载安装如果不带上tag,会自动默认依据上次的tag信息进行安装,例如,

npm install loadash beta

下次安装loadash的时候,默认是下载beta标签的loadash

全局安装

全局安装,就是指安装一些共用的包,在你的本地计算机下的项目,都能共用这些包。例如npm了,每个项目都需要使用npm,那么全局安装就好了,不必要每个项目都独立安装一遍。指令也很简单

npm install -g
npm install -g <package-name>

其实跟本地安装介绍的意思是一样的,只不过区别就在于,多了个-g来标记是全局安装

更新package

随着时间的变化,可能你本地下载的包已经是比较老的了,需要更新一下别人的包,那么在项目根目录下运行

npm update

即可更新package.json里罗列的包。

如果想单独更新某个包(私有包请带上@域名/),运行

npm update <package-name>

同样地,如果想更新全局的包,也是加个-g即可,如

npm update -g

如果想看看当前项目里有哪些过时的包,可以运行

npm outdated

会显示当前有哪些包过时了。当然这也可以用来检验是否更新成功了

如果想看看有哪些过时的全局包,运行

npm outdated -g --depth=0

取消安装/删除package

如果某个包你不想要了,为了节省空间以及协作时避免别人下载一些不必要的资源,可以删除某些不需要的包。运行(私有包请带上@域名/

npm uninstall <package-name>

指定删除某个包

npm uninstall -g <package-name>

指定删除某个全局包

未经允许,请勿私自转载