npm进阶学习

Posted by Yeoman on 2017-01-16

npm的由来

前端开发的依赖越来越重,去下载源码进行引用的方式已经过于繁琐,于是Isaac Z. Schlueter 大神就用JavaScript(node.js)写了一个npm(Node Package Manager)。

npm的发展和Node.js发展相辅相成,Node.js也缺少一个包管理工具,于是Node.js作者和npm作者达成合作,Node.js内置了npm。之后npm的作者成立了一家公司专门维护npm上的registry。

npm本质就是一个代码仓库(registry)。开发者可以发布自己的代码到这个服务器,其他开发者都可以在这个服务器上统一下载需要的依赖。


npm的常见使用

刚才讲到,npm的(registry)本身就是一台托管代码的服务器,那么如何确定我们下载的代码就是来自于这里呢?npm提供了一个查询的指令:

npm view vue

这个命令可以查看这个仓库的包管理信息,其中有一个json字段:

 dist:
 { shasum: 'ae30aa86024fccf5535292ce414e7b4c221a1756',
tarball: 'https://registry.npmjs.org/vue/-/vue-2.1.8.tgz' }

这个看到这是仓库的最新版本的压缩包的网址就是在npm的registry下。



npm install

现在我们回到最常用的命令npm install <packageName>npm update <packageName>。第一个命令大致做了哪些事呢?

  1. 从当前目录向上检查node_modules目录,如果发现了相同的包,则停止安装。
  2. 从registry上下载压缩包到~/.npm目录下(缓存目录)。
  3. 解压缩到当前node_modules目录。



然后介绍几种常用的npm install的参数。

  • npm install <packageName> --save 安装完依赖之后会在 package.json 中的 dependencies 字段中。
    npm install <packageName> --save-dev则在 devDependencies 字段中添加。
    这样只要保证你和别人用相同的一份配置文件就可以安装相同的依赖环境。

  • npm install --only=prodnpm install --only=dev 分别只下载 dependenciesdevDependencies 中的依赖。

  • npm install <packageName> --force 不管本地只否已经安装依赖,npm都会强制重新安装。
  • npm install <packageName> --global 把依赖安装到全局,通常适用于安装一些需要在全局使用的CLI工具。可以通过npm root -g查看npm全局路径,macOS下默认在/usr/local/lib/node_modules^ 符号,允许第一位版本号不为零情况下更新到最新版本,当第一位版本号为零则保持第一位版本号不变,更新后面的版本号。 符号,只能更新最右版本号。
  • npm install <packageName>@<version> 可以安装指定版本的依赖。

以上大致上已经讲明白npm是如何干活的,再简单讲几个常用的指令。



npm update

这个指令做的事情类似于安装的指令。

  1. 检查registry和本地的仓库版本
  2. 如果发现有新版本,则下载压缩包到~/.npm下,注意,这个操作并不会删除~/.npm下老的版本,而是保留多个版本
  3. 解压缩并替换掉当前目录下的老版本依赖。

同时在用这个更新命令的时候,应该注意几点:

  • 在update的时候尽量带上–save参数,保持package.json信息同步。
  • package.json中指定版本的时候有Caret DependenciesTilde Dependencies区别

npm uninstall <packageName>

卸载依赖包,这个命令同样不会删除~/.npm/中的cache包。

npm outdated

可以查看所有依赖的当前/需要/最新版本情况。

npm cache clean

清除npm缓存文件。

npm run-scripts

可以在package.json中的scripts配置shell脚本。

"scripts": {
"test": "node ***/app.js"
}

然后在shell中可以直接运行npm run test,就相当于node ***/app.js,可以把和这个项目的shell命令统一交给npm来管理。

创建和发布

npm init -y

初始化一个仓库,-y或者-f参数会根据npm的默认配置来生成仓库。

npm adduser

使用在npm上注册的账号密码来登陆命令行,获取后续的发布操作的授权。

npm publish

发布到npm仓库,在发布仓库的时候一个常见的需求是过滤想发布的目录和文件。我们可以通过.npmignore.gitignore来过滤不想上传的目录。但是有些文件是不受配置文件影响的:

但是很多时候我们其实只要上传指定的目录和文件,最方便的做法是在package.json中配置files: []属性,数组内是需要发布的目录,当配置了这个属性之后,是不会被.npmignore.gitignore过滤的,也就是优先级高于.npmignore.gitignore




npm的配置

首先,npm默认是没有生成一个配置文件的,但是已经存在很多默认配置。运行

npm config list

可以查看当前配置情况

npm config list -l

可以查看所有默认配置,如果没有添加配置文件,这些默认配置就会生效,但是这些默认配置的优先级是最低的。




那么除了这些默认配置,npm可以有不同的优先级来修改配置信息。

  • per-project config file (/path/to/my/project/.npmrc)

    // 项目目录,优先级最高

  • per-user config file (~/.npmrc)

    // 当前用户目录,优先级次之

  • global config file ($PREFIX/etc/npmrc)

    // npm全局目录,优先级再次之

  • npm builtin config file (/path/to/npm/npmrc)

    // npm安装目录,默认在/usr/local/lib/node_modules/npm,优先级仅高于默认配置

我们可以通过命令行来设置一个参数,例如:

npm config set cache {$HOME}/.npm/.cache/cnpm

这个指令是修改npm的cache路径,这时候运行

cat ~/.npmrc

发现在用户目录下生成了一个.npmrc文件,并且打印cache=/Users/yeoman/.npm/.cache/cnpm,由此可见,这个config指令默认会配置在用户目录下,而带上–global参数之后就会在全局目录下生效。
这时候再通过npm config list -l查看,发现其一项配置变成:

; cache = "/Users/yeoman/.npm" (overridden)

由此默认配置被覆盖,修改成功。
其他的配置都可以通过

npm config set key value

已及

npm config get key

进行设置和获取。


Tips:

  • 之前提到的npm的仓库地址是https://registry.npmjs.org/,这个服务器是在美国,所以在国内访问速度非常慢。现在比较通用的做法是用淘宝的npm镜像源,目前是十分钟就会同步一次npm的源。这个源是在阿里云服务器,速度杠杠的。
    以下是几种常见解决方式:

第一种方式就是把npm指向的源改成淘宝的源

$ npm config set registry https://registry.npm.taobao.org



第二种方式是直接安装cnpm,然后cnpm基本上支持npm所有的功能。

$ npm install -g cnpm --registry=https://registry.npm.taobao.org



但是最推荐的方式还是用alias给npm参数定一个别名

$ alias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"

这么做的好处是既可以用npm原有的所有命令,也可以用cnpm的源,并且不影响原来的npm设置。



  • 离线下载(也就是从~/.npm/的cache中下载)
    这个功能个人感觉应该绝大部分情况用不到。如果是为了提升速度,还是直接换源的方式比较直接。

方式如下:

$ npm --cache-min 9999999 install <package-name>

这种方式也存在一些问题,解决方式看这篇文章

参考:
npm官方文档
阮叔叔的文章