npm--你真的掌握了吗?

1,611 阅读8分钟

title-img

npm--你真的掌握了吗?

npm 是 JavaScript 世界的包管理工具,并且是 Node.js 平台的默认包管理工具。通过 npm 可以安装、共享、分发代码,管理项目依赖关系。

问题

  • 你还在用 npm install nmp init ... 吗?
  • 你还在纠结install --save-dev --save -S -D 吗?
  • 你还在用 cnpm 或者 npm config set registry --修改源吗?
  • 你是如何在本地调试 npm包的?
  • 为啥现在npm install 会生成package_lock.json?
  • 你知道生成的package.json是什么东西吗?
  • ...

开始

在开始之前我有话说, 如果上面的问题你都能清楚掌握,那么这篇文章对你来说就没有太大的意义来了。如果在有些地方还是模棱两可,那不妨和我一起来看看这个npm的葫芦里卖的是什么药。

如何开发一个npm包 ?

如果我们有一个功能会高频次用到我们一般都会把它抽出来方便调用;如果该功能在整个团队开发都会多次调用(如 工具类方法,Modal层组件)我们会抽到公共组件中以方便团队成员使用;为了让更多人使用,我们可以将其做成npm包发布到远程仓库。

初始化一个包

npm init

在开发目录生成一个 package.json文件,里面存放着安装包的信息,以方便其他开发着使用。
但是直接 npm init我们需要根据命令行提示一步一步完成基本的信息;如何跳过呢?

** 安装我们需要的工具包**

** npm init -f(force) / npm init -y(yes)**

这时直接跳过信息填写,本地生成package.json;后面会详细讲解package.json里面的内容。

npm install < packageName >

安装模块;
npm install 会直接去安装package.json文件的dependencies/devDependencies节点下的依赖。

npm install express  简写 npm i express
每次install时后面带了很多 参数 -g -golbal --save -D ...
下面会一一详解
  • --save-dev / -D
安装开发环境依赖,依赖的版本信息在package.json文件的devDependencies节点下。
ex:  npm install --save-dev glup  简写 npm i -D glup 
  • --save / -S
安装生产环境依赖,依赖的版本信息在package.json文件的dependencies节点下。
ex: npm install --save  axios  简写 npm i -S axios
  • ** --save-exact**
安装生产环境精确版本的依赖,依赖的版本信息在package.json文件的dependencies节点下。
dependencies节点下的包版本号 前面没有~符号(介绍package.json会讲到)。
ex:npm install --save-exact jquery 简写 npm i -E jquery
  • -g / -golbal
表示全局安装依赖。
如果安装依赖时没有带 -g/-golbal的话。会将该依赖直接安装到工作目录的node_module中。
否则,将依赖安装到全局的node_module中。
全局的安装路径根据本机系统而定,当然你也可以通过npm config set prefix <path>来设定。

解决安装依赖过慢的问题

开始使用npm i去安装包的时候由于种种原因导致我们安装时间过长,甚至安装失败。这个是我们不能容忍的事情。网上的解决意见都是安装cnpm修改源来解决这个问题。还有更好的办法么?

  • 网上解决方案
npm install cnpm -g --registry=https://registry.npm.taobao.org
ok!我们可以愉快的用cnpm来安装了。  
npm set registry https://registry.npm.taobao.org/
ok!直接修改npm源,这样我们可以使用npm。

因为有的公司基于安全稳定考虑会在内部部署npm仓库,我们在家里开发要切换到taobao源,到了公司我们又要切换到公司的源;这样三五次就会很苦恼。

  • 更好的方法

安装nrm (nrm是专门用来管理和快速切换私人配置的registry)

npm install nrm -g -S  全局安装nrm
nrm ls 查看查看默认配置  带*是我们当前使用的源
nrm current  可以直接输入以下命令查看当前使用的是哪个源
nrm use cnpm  切换不同的源
假如你公司的源是 http://registry.xxx.org
nrm add company http://registry.xxx.org  添加公司源
nrm ls 可以查看是否添加成功,成功会多一个company的源
nrm use company 切换到公司的源
nrm del company 离职后直接移除

这里有很好的nrm使用介绍

依赖包的操作技巧集合

npm uninstall < packageName >

卸载模块。(卸载工作目录的依赖包;不删除package.json里面的模块信息)
ex: npm uninstall jquery  (-g / --save-dev / --save)
-g : 卸载全局安装的依赖包
--save-dev:卸载工作目录的依赖包;同时删除模块留在package.json中dependencies下的对应信息
--save:卸载工作目录的依赖包;同时删除模块留在package.json中devDependencies下的对应信息

npm update < packageName >

更新依赖包。(更新工作目录)
ex:npm update express (-g)
-g:更新全局环境

npm root < packageName >

查看依赖包的安装路径。
ex:npm root express (-g)
-g:全局环境下依赖包安装地址

npm list < packageName >

查看所有安装的依赖包。
ex:npm list  简写 npm ls (-g)
-g:查询全局环境的依赖包。

npm outdated < packageName >

查看过期的依赖包。
ex:npm outdated (-g / pkg)
-g:查看全局的依赖包。
pkg:查看对应的pkg。
注:推荐使用检查依赖包更强大的一个工具 npm-check,
更强大分析包的能力以及可以通过加上参数提供交互式更新方式,详情请参考其文档说明

npm prune < packageName >

删除没有使用到的依赖包。
ex:npm prune (pkg)
pkg:删除pkg。

锁定安装依赖

npm config set save-prefix="flag" 
flag:可选 (~,^)
或者:npm config set save-exact true 安装精确版本好安装类似:npm install -E

npm home < packageName >

运行home命令可以打开此package的主页。
不管你机器中是否全局安装了此package,甚至是不存在于你当前项目中都可以打开。
ex: npm home express

**npm repo < packageName > **

如何打开package的Github仓库地址。
不管你机器中是否全局安装了此package,甚至是不存在于你当前项目中都可以打开。

**npm shrinkwrap **

使用shrinkwrap命令会在你当前项目中生成一个npm-shrinkwrap.json文件。
它会将当前package.json中引用的依赖版本锁定,当下次执行npm install时,
它默认安装的其实是shrinkwrap.json中锁定的依赖版本号。

注意:npm在 5.0.0+ 版本默认生成 package-lock.json,就是说你现在不需要 npm shrinkwrap了

package-lock.json为的是让开发者知道只要你保存了源文件,到一个新的机器上、或者新的下载源,只要按照这个package-lock.json所标示的具体版本下载依赖库包,就能确保所有库包与你上次安装的完全一样。

这里有很好的package_lock.json的问答----知乎

依赖包调试技巧

npm link

假如 unit(开发的依赖包);在发布之前我们怎么调试unit是否能正常工作?
先将unit依赖包link到全局,然后在需要调试的项目里,将该命令链接到本地node_modules下面。
ex:
$ # 先去到模块目录,把它 link 到全局
$ cd path/to/my-utils
$ npm link
$
$ # 再去项目目录通过包名来 link
$ cd path/to/my-project
$ npm link my-utils

这里有很好的link使用介绍

package.json

{
  "name": "normalize.css",
  "version": "3.0.3",
  "description": "Normalize.css as a node packaged module",
  "style": "normalize.css",
  "files": [
    "LICENSE.md",
    "normalize.css"
  ],
  "homepage": "http://necolas.github.io/normalize.css",
  "repository": {
    "type": "git",
    "url": "git://github.com/necolas/normalize.css.git"
  },
  "main": "normalize.css",
  "author": {
    "name": "Nicolas Gallagher"
  },
  "license": "MIT",
  "gitHead": "2bdda84272650aedfb45d8abe11a6d177933a803",
  "bugs": {
    "url": "https://github.com/necolas/normalize.css/issues"
  },
  "_id": "normalize.css@3.0.3",
  "scripts": {
      "start": "node index.js"
  },
   "dependencies": {
    "express": "latest",
    "mongoose": "~3.8.3",
    "handlebars-runtime": "~1.0.12",
    "express3-handlebars": "~0.5.0",
    "MD5": "~1.2.0"
  },
  "devDependencies": {
    "bower": "~1.2.8",
    "grunt": "~0.4.1",
    "grunt-contrib-concat": "~0.3.0",
    "grunt-contrib-jshint": "~0.7.2",
    "grunt-contrib-uglify": "~0.2.7",
    "grunt-contrib-clean": "~0.5.0",
    "browserify": "2.36.1",
    "grunt-browserify": "~1.3.0",
  }
  "_shasum": "acc00262e235a2caa91363a2e5e3bfa4f8ad05c6",
  "_from": "normalize.css@3.0.3",
  "_npmVersion": "2.7.0",
  "_nodeVersion": "0.10.35",
  "_npmUser": {
    "name": "necolas",
    "email": "nicolasgallagher@gmail.com"
  },
  "maintainers": [
    {
      "name": "tjholowaychuk",
      "email": "tj@vision-media.ca"
    },
    {
      "name": "necolas",
      "email": "nicolasgallagher@gmail.com"
    }
  ],
  "bin" : { "myapp" : "./cli.js" }
  "dist": {
  "shasum": "acc00262e235a2caa91363a2e5e3bfa4f8ad05c6",
    "tarball": "https://registry.npmjs.org/normalize.css/-/normalize.css-3.0.3.tgz"
  },
  "directories": {},
  "_resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-3.0.3.tgz",
  "readme": "ERROR: No README data found!"
}

name - 包名.
version - 包的版本号。
description - 包的描述。
homepage - 包的官网URL。
author - 包的作者,它的值是你在https://npmjs.org网站的有效账户名,遵循“账户名<邮件>”的规则,
contributors - 包的其他贡献者。
dependencies / devDependencies - 生产/开发环境依赖包列表(-S -D 就会分别安装到这个目录中)。它们将会被安装在 node_module 目录下。
repository - 包代码的Repo信息,包括type和URL,type可以是git或svn,URL则是包的Repo地址。
main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
keywords - 关键字

  • bin

许多包有一个或多个可执行文件希望被安装到系统路径。在npm下要这么做非常容易(事实上,npm就是这么运行的)。
这需要在你的package.json中提供一个bin字段,它是一个命令名和本地文件名的映射。在安装时,如果是全局安装,npm将会使用符号链接把这些文件链接到prefix/bin,如果是本地安装,会链接到./node_modules/.bin/。

如:bin" : { "myapp" : "./cli.js" }     

这么一来,当你安装myapp,npm会从cli.js文件创建一个到/usr/local/bin/myapp的符号链接(这使你可以直接在命令行执行myapp)

  • mongoose": "~3.8.3

npm模块的完整的版本号一般是【主版本 . 次要版本 . 补丁版本】,一般情况下,次要版本号发生改变的话,表示程序有重大更新。

3.8.3:当前版本号
>3.8.3:必须大于3.8.3
<3.8.3:必须小于3.8
~3.8.3:会匹配3.8.x的最新版本;不会自动升级3.9.0
^3.8.3:会匹配3.x.x的最新版本;不会自动升级4.0.0

这里有很好的package.json介绍