npm 重点小结

时间:2022-02-01 06:09:46

npm作为javascript一个用得比较广的包管理工具,已经集成在了node里面,基本一安装node就可以用npm了,十分方便。这里的小结主要沿着官方文档的思路,挑出一些比较重点的,平时常用的部分进行说明,力求清晰与主次分明。

  1. 全局与本地安装

    本地安装指的是只将包下载到当前项目的node_module文件夹,当安装的包只需要在项目中被require使用时,用本地安装;全局安装指将包下载到本机安装的npm创建的/lib/node_module文件夹,当安装的包需要在控制台打命令行运行时,就需要全局安装,比如gulp,express cli等等。

  2. package.json

    package.json文件是用来管理项目本地npm的下载包,用npm init命令创建,有一些需要留意的地方:

    • 项目的命名是有一定要求的,小写,不能有空格,可以用下划线或者连字符。

    • scripts 字段可以配置自定义的一些命令行语句,作用是简化命令行,而且统一命令行为npm run ...的格式,自己自己配置一些语义化的命令,举个例子:


    "scripts": { "build": "webpack", "dev": "webpack-dev-server --inline --hot --quiet" },

    这样配置后在命令行打npm run build和打webpack的效果是一样的,这个例子看起来打的命令变长了,但是语义化更强了一些,一看就知道是项目构建;第二条命令npm run dev简化命令行的效果就很明显了。

    • package.json里面还有两个比较重要的字段,即dependenciesdevDependenciesnpm install <package> --save会把安装的包写到dependencies,表示的是正式环境的包;npm install <package_name> --save-dev会把安装的包写到devDependencies,表示的是测试环境的包。很多人知道的就仅限于此了,测试和正式安装的版本不同会怎么样?install的时候是装哪一个?包的版本号是怎么控制的?这些深入了解的人就不多了,下面来仔细说明一下:
  3. npm install的时候会将dependenciesdevDependencies里面的包全部安装,当两个里面的包版本不同时,安装dependencies内的版本,同时会有invalid的提示:npm 重点小结

    其实dependenciesdevDependencies里面如果有相同的包这种情况是不应该出现的,原因在于有些人对dependenciesdevDependencies有一些误解,觉得devDependencies应该包含dependencies里面的内容,然后再在devDependencies中加入一些开发环境需要的包,其实devDependencies的意义在于增加一些开发环境需要的包以及一些未确定是否要用的包,如果某个包是确定要在线上用的,那么就直接写到dependencies就可以了,不需要在devDependencies中出现,简单来讲就是devDependencies其实已经包括dependencies了。所以当你测试完一个包觉得可以在线上使用时,你就可以把包写到dependencies里,然后删掉devDependencies中对应的包,保持包名不要重复出现,也有利于package.json文件的简洁。

    线上环境可以用npm install --production命令(或者配置了NODE_ENV环境变量为production),就只安装dependencies里面的包。安装完后可以用npm ls查看安装的包的情况。

  4. 所有的包安装后都会带版本号,版本号的规则要符合包node-semver的解析规则,下面直接举例说明:

    npm install sax@0.1.1
    
    npm install sax@">=0.1.0 <0.2.0"
    
    npm install vue@^1.0.0

    第一种是直接指定版本号

    第二种也是也很容易理解,类似的有< <= > >= =,不过写=1.0.0或者v1.0.01.0.0其实是一样的,字符串中甚至还可以加上||,比如:1.2.7 || >=1.2.9 <2.0.0,来排除中间1.2.8这个版本,其他一些写法可以参考github上面[node-semver] (https://github.com/npm/node-semver)的用法说明,这里主要说明几个常用的

    • 缺省:版本号一般分三段,[major, minor, patch](主版本.此版本.补丁),版本可以缺省,表示没有限制这一段的版本,比如1.2表示1.2.0 - 1.2.9

    • -:连字符,可以简单规定版本范围,比如1.2.3 - 2.3.4相当于>=1.2.3 <=2.3.4,需要留意的是连字符左右要有空格空开;

    • * x X:星号表示任意数字,和缺省类似,1.2 1.2.* 1.2.x 1.2.X是一样的

    • ~:波浪号允许小版本迭代,规则分情况理解比较容易:如果有缺省值,则表示缺省部分任意迭代;如果没有缺省值,则表示只允许第三段即补丁的迭代,具体来看node-semver上举的例子(测试版本号有点不一样,不过平时用得少就不列举了):

        1. ~1.2.3 :>=1.2.3 <1.3.0
    
        2. ~1.2 :  >=1.2.0 <1.3.0 (相当于1.2.x)
    
        3. ~1 :   >=1.0.0 <2.0.0 (相当于1.x)
    
        4. ~0.2.3 :   >=0.2.3 <0.3.0
    
        5. ~0.2 :  >=0.2.0 <0.3.0 (相当于0.2.x)
    
        6. ~0 :  >=0.0.0 <1.0.0 (相当于0.x)
    • ^:上尖号和~含义相对,允许大版本迭代,规则同样分情况:如果有缺省值,则允许缺省值的前一位版本+1迭代;如果没有缺省值,则版本号允许从大到小第一个不为0那一位允许+1迭代,还是直接看例子:
        ^1.2.3: >=1.2.3 <2.0.0
    
        ^0.2.3: >=0.2.3 <0.3.0
    
        ^0.0.3: >=0.0.3 <0.0.4
    
        ^1.2.x:>=1.2.0 <2.0.0
    
        ^0.0.x:>=0.0.0 <0.1.0
    
        ^0.0:>=0.0.0 <0.1.0
    
        ^1.x:>=1.0.0 <2.0.0
    
        ^0.x:>=0.0.0 <1.0.0

    以上就是常见的版本号控制语法了,当然还有一些更加高级的混用,不过个人感觉容易引起出错混乱,还是不要折腾了。版本在这里说了那么多,是因为版本是很重要的部分,现在很多包都是开源的,更新迭代很快,npm install <package> --save安装时写入package.json一般是^版本号的格式,在不同时间用npm install安装package.json中的文件时,可能就会出现版本不一致引起的代码运行结果不同。

    npm install还有一个参数是--save-optional这个会将包加入optionalDependencies中,这个平时用得比较少,从字面上理解是可选包,等有这样的需求再研究吧。

  5. npm outdated命令可以查看有新版本的包的版本情况,如下图所示,current是当前安装的包的版本,wanted是package.json里面写的版本,latest是最新版本:npm 重点小结npm update命令可以更新本地package.json里面列举的包,当然,更新也会遵循package.json里面包的版本规则;不过更新全局的包不是用的update,而是直接重新npm install -g ,如果是更新所有全局的包,直接用npm update -g,话说这样变来变去不知道是出于什么考虑...

  6. npm uninstall是卸载包的命令,不过很多人安装包的时候知道加--save或者--save-dev命令,而卸载的时候就会忘了加,如果这个包是确定不需要使用的,就可以直接加--save或者--save-dev从package.json中删掉它。卸载全局的包只需要加个-g参数。

  7. npm config是npm中查看配置信息的命令,主要涉及npmrc files 文件

        npm config set <key> <value> [-g|--global]
    npm config get <key>
    npm config delete <key>
    npm config list
    npm config edit
    npm get <key>
    npm set <key> <value> [-g|--global]
  8. npm docs <pkg> 这个命令可以直接打开包的官方文档网站,一般就是github了,不过打开速度不是很快。

  9. npm explore <pkg> [ -- <cmd>] explore 可以暂时定位到包的目录,可以查看修改包内的内容,当然修改完要用npm rebuilt <pkg>来重新编译包;cmd 可以添加一些命令行指令,官网给出的例子是-- git pull origin master,即更新本地git仓库,一般用在包的子模块的更新。exit或者ctrl C 可以退出包目录返回原来的目录地址。

  10. npm help 辅助命令,比如打npm help explore就会打开npm explore的html文档,有个类似的指令是npm help-search,当npm help命令无法定位到确定文档时,就会自动调用npm help-search命令,比如打npm help b会在所有的npm help *命令的文档里面查找。

  11. npm install <pkg> npm install 后面可以带带版本号标签号的包名,或者压缩包、压缩包地址等等,下面是文档列举的方式,常用的就是直接指定包名了


    npm install [<@scope>/]<name>
    npm install [<@scope>/]<name>@<tag>
    npm install [<@scope>/]<name>@<version>
    npm install [<@scope>/]<name>@<version range>
    npm install <tarball file>
    npm install <tarball url>
    npm install <folder>
  12. npm link是用来链接全局包的命令,npm link主要是为模块开发者使用的一个命令,设想这样的一个情景:你开发了一个模块a并发布了(npm public),并在项目中引入这个模块,在使用过程中发现了a有bug,你改动了a,于是需要重新npm public,发布完你又要回到自己的项目中用npm update命令来更新模块,如果只是小改动还好,如果是开发初期的频繁更新,那么就很浪费时间,毕竟自己开发的模块在本机还要更新,这个步骤明显很多余。npm link命令就是用来同步模块更新的,一般应用场景如下:

    自己开发的包名为appy,放在src/appy文件夹——cd to src/appy——npm link,将会把src/appy这个包复制到npm的全局模块安装文件夹node_modules内,并创建符号链接(symbolic link,应该是一个软链接)——自己的项目放在src/mysite文件夹——cd to src/mysite——npm link appy,那么项目中的appy包就会和src/appy相关联,每次npm publish后,项目文件夹里面的appy包都会随之更新。

    有时候这个包并不是你开发的,但是你想contribute这个包时,也可以在自己的项目文件夹中直接用npm link <package>,这个包同样会被安装到全局,并和此项目中的包相关联。

  13. npm ls[ll | la]是和shell命令类似的语法,就是列举信息,默认以树形的方式列举包名,包括其依赖,llla列举的信息较为多一点。如果你想用json格式来列举,可以通过设置config文件的json字段来设置,用npm config set json true,则将以json格式来显示包及其依赖,不过这个字段是npm全局的,很多命令的显示都会变成json格式。其余还有一些蛮有用的配置项,比如如果列举的依赖过多,可以设置depth(int)参数来限制显示的层级,prod / production(Boolean)来只显示dependencies的依赖,dev(Boolean)来只显示devDependencies的依赖等等。

  14. npm prune,这个命令要和package.json文件路径下运行,将会移除package.json中没有列举的node_modules的包,如果是生产环境中或者加--production,将会移除devDependencies里面的包,用于清理多余的包资源。

  15. npm repo <package>,这个和上面的npm docs类似,一般也是打开的github网址。

  16. npm root [-g],打印出node_modules文件夹路径,加个-g可以查看全局包的安装路径,有时候忘了全局包安装路径这个小命令还是蛮有用的。

  17. npm run <command>用npm run来跑package.json里面script字段内的命令,可以直接打npm run查看有哪些命令

  18. npm shrinkwrap,这个命令用来指定安装的包版本,主要是为了项目环境的稳定。因为传统的npm install安装的包写入package.json时往往带的是一个版本号范围,有时候为了在其他地方安装能够保持版本号一致或者在线上部署希望项目稳定,所以希望用npm install安装依赖时安装的包和测试通过时是一样的,或者说保持版本号一致,npm shrinkwrap就是这样的一个功能。npm shrinkwrap会在目录下面创建npm-shrinkwrap.json文件,里面是项目中已经安装的包(包括所有包内嵌套的包)的确定版本号以及包的下载位置,当用npm install是,会直接安装npm-shrinkwrap.json文件内列举的包名。如果想要更新npm-shrinkwrap.json文件内的包,可以先用npm update <package>更新包,再用npm shrinkwrap命令来重新创建npm-shrinkwrap.json文件,npm shrinkwrap默认只确定package.jsonde­pen­den­cies内的包,测试环境的包需要加--dev参数。

  19. npm update [-g] [<pkg>...]用来更新包,需要注意的是包更新依然需要符合package.json中的版本号范围,只会在版本号范围内更新最新版本的包。有-g--dev--save参数,没有加具体包名时默认更新所有的包。

  20. npm view可以查看很多信息,下面列举几个常用的:

    • npm view connect直接接包名查看包信息

    • npm view npm view ronn@0.3.5 dependencies查看包依赖

    • npm view connect versions查看包历史版本列表,如果version不加s则表示查看包最新版本。

以上列出的命令涉及到的是日常的使用范围,还有一些复杂的参数和设置就不列举了,实际上个人用到的命令不多,很多都是看文档的时候才知道的,如果有哪些错漏欢迎指出。除此之外,npm还有其他一些命令是关于发布包的流程与管理的,这部分就蛮复杂(主要是我没有发布包的经验),希望以后有机会发布自己的包的时候再来写了。最后吐槽一下博客园的Markdown编辑器,总觉得显示出来的效果实在是差点意思......

https://github.com/npm/node-semver

npm documentation

RYAN . What is npm shrinkwrap and when is it needed

npm link: [developing your own npm modules without tears](http://justjs.com/posts/npm-link-developing-your-own-npm-modules-without-tears

Oleksii Rudenko . Simple Way to Manage Local Node Modules Using NPM Link.

JeremyWei . 如何发布Node模块到NPM社区