第5章 包与npm

学习目标

  • 掌握 npm 的常用命令
  • 理解安装本地包和全局包的区别
  • 理解 package.json 文件作用

npm

npm 全称 Node Package Manager,它的诞生是为了解决 Node 中第三方包共享的问题。
和浏览器一样,由于都是 JavaScript,所以前端开发也使用 npm 作为第三方包管理工具。
例如大名鼎鼎的 jQuery、Bootstrap 等都可以通过 npm 来安装。
所以官方把 npm 定义为 JavaScript Package Manager

npm 有两层含义。一层含义是Node的开放式模块登记和管理系统,网址为npmjs.org。另一层含义是Node默认的模块管理器,是一个命令行下的软件,用来安装和管理Node模块。

npm不需要单独安装。在安装Node的时候,会连带一起安装npm

执行下面的命令可以用来查看本地安装的 npm 的版本号。

  1. npm --version

如果想升级 npm ,可以这样

  1. npm install npm --global

常用命令

表格

  1. # 在项目中初始化一个 package.json 文件
  2. # 凡是使用 npm 来管理的项目都会有这么一个文件
  3. npm init
  4. # 跳过向导,快速生成 package.json 文件
  5. # 简写是 -y
  6. npm init --yes
  7. # 一次性安装 dependencies 中所有的依赖项
  8. # 简写是 npm i
  9. npm install
  10. # 安装指定的包,可以简写为 npm i 包名
  11. # npm 5 以前只下载,不会保存依赖信息,如果需要保存,则需要加上 `--save` 选项
  12. # npm 5 以后就可以省略 --save 选项了
  13. npm install 包名
  14. # 一次性安装多个指定包
  15. npm install 包名 包名 包名 ...
  16. # 安装指定版本的包
  17. npm install 包名@版本号
  18. # npm list命令以树型结构列出当前项目安装的所有模块,以及它们依赖的模块。
  19. npm list
  20. # 加上global参数,会列出全局安装的模块
  21. npm list -global
  22. # npm list命令也可以列出单个模块
  23. npm list 包名
  24. # 安装全局包
  25. npm install --global 包名
  26. # 更新本地安装的模块
  27. # 它会先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在,或者远程版本较新,就会安装
  28. npm update [package name]
  29. # 升级全局安装的模块
  30. npm update -global [package name]
  31. # 卸载指定的包
  32. npm uninstall 包名
  33. # 查看包信息
  34. # view 别名:v、info、show
  35. npm view 包名
  36. # 查看使用帮助
  37. npm help
  38. # 查看某个命令的使用帮助
  39. # 例如我忘记了 uninstall 命令的简写了,这个时候,可以输入 `npm uninstall --help` 来查看使用帮助
  40. npm 命令 --help

全局命令行工具

每个模块可以“全局安装”,也可以“本地安装”。“全局安装”指的是将一个模块安装到系统目录中,各个项目都可以调用。一般来说,全局安装只适用于工具模块,比如eslintgulp。“本地安装”指的是将一个模块下载到当前项目的node_modules子目录,然后只有在项目目录之中,才能调用这个模块。

提示:安装全局包必须加 --global 参数

http-server

https://github.com/indexzero/http-server#readme

nodemon

http://nodemon.io/

less

http://lesscss.org/

browser-sync

https://browsersync.io/

切换 npm 镜像源

  • npm install jquery --registry=https://registry.npm.taobao.org
  • npm config set registry https://registry.npm.taobao.org
  • nrm

npm 存储包文件的服务器在国外,有时候会被墙,速度很慢,所以我们需要解决这个问题。

国内淘宝的开发团队把 npm 在国内做了一个备份,网址是:http://npm.taobao.org/。

最简单的方式就是我们在安装包的时候告诉 npm 你去哪个服务器下载。

例如使用淘宝的 npm 镜像源下载 jquery:

  1. npm install jquery --registry=https://registry.npm.taobao.org

但是每次手动往后面加 --registry=https://registry.npm.taobao.org 很麻烦,
所以我们可以通过修改配置文件的方式来处理解决。

  1. # 配置到淘宝服务器
  2. npm config set registry https://registry.npm.taobao.org
  3. # 查看 registry 是否配置正确
  4. npm config get registry

只要经过了上面命令的配置,则你以后所有的 npm install 都会使用你配置的 registry 下载。

package.json

每个项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。

package.json文件可以手工编写,也可以使用npm init命令自动生成。

  1. npm init

这个命令采用互动方式,要求用户回答一些问题,然后在当前目录生成一个基本的package.json文件。所有问题之中,只有项目名称(name)和项目版本(version)是必填的,其他都是选填的。

这个文件可以通过 npm init 的方式来自动初始化出来。

下面是一个最简单的package.json文件,只定义两项元数据:项目名称和项目版本。

  1. {
  2. "name" : "xxx",
  3. "version" : "0.0.0",
  4. }

package.json文件就是一个JSON对象,该对象的每一个成员就是当前项目的一项设置。比如name就是项目名称,version是版本(遵守“大版本.次要版本.小版本”的格式)。

下面是一个更完整的package.json文件。

  1. {
  2. "name": "Hello World",
  3. "version": "0.0.1",
  4. "author": "张三",
  5. "description": "第一个node.js程序",
  6. "keywords":["node.js","javascript"],
  7. "repository": {
  8. "type": "git",
  9. "url": "https://path/to/url"
  10. },
  11. "license":"MIT",
  12. "engines": {"node": "0.10.x"},
  13. "bugs":{"url":"http://path/to/bug","email":"bug@example.com"},
  14. "contributors":[{"name":"李四","email":"lisi@example.com"}],
  15. "scripts": {
  16. "start": "node index.js"
  17. },
  18. "dependencies": {
  19. "express": "latest",
  20. "mongoose": "~3.8.3",
  21. "handlebars-runtime": "~1.0.12",
  22. "express3-handlebars": "~0.5.0",
  23. "MD5": "~1.2.0"
  24. },
  25. "devDependencies": {
  26. "bower": "~1.2.8",
  27. "grunt": "~0.4.1",
  28. "grunt-contrib-concat": "~0.3.0",
  29. "grunt-contrib-jshint": "~0.7.2",
  30. "grunt-contrib-uglify": "~0.2.7",
  31. "grunt-contrib-clean": "~0.5.0",
  32. "browserify": "2.36.1",
  33. "grunt-browserify": "~1.3.0",
  34. }
  35. }

下面详细解释package.json文件的各个字段。

dependencies

dependencies字段指定了项目运行所依赖的模块,devDependencies指定项目开发所需要的模块。

它们都指向一个对象。该对象的各个成员,分别由模块名和对应的版本要求组成,表示依赖的模块及其版本范围。

  1. {
  2. "devDependencies": {
  3. "browserify": "~13.0.0",
  4. "karma-browserify": "~5.0.1"
  5. }
  6. }

对应的版本可以加上各种限定,主要有以下几种:

  • 指定版本:比如1.2.2,遵循“大版本.次要版本.小版本”的格式规定,安装时只安装指定版本。
  • 波浪号(tilde)+指定版本:比如~1.2.2,表示安装1.2.x的最新版本(不低于1.2.2),但是不安装1.3.x,也就是说安装时不改变大版本号和次要版本号。
  • 插入号(caret)+指定版本:比如ˆ1.2.2,表示安装1.x.x的最新版本(不低于1.2.2),但是不安装2.x.x,也就是说安装时不改变大版本号。需要注意的是,如果大版本号为0,则插入号的行为与波浪号相同,这是因为此时处于开发阶段,即使是次要版本号变动,也可能带来程序的不兼容。
  • latest:安装最新版本。

main

main字段指定了加载的入口文件,require('moduleName')就会加载这个文件。这个字段的默认值是模块根目录下面的index.js

scripts

scripts指定了运行脚本命令的npm命令行缩写,比如start指定了运行npm run start时,所要执行的命令。

下面的设置指定了npm run preinstallnpm run postinstallnpm run startnpm run test时,所要执行的命令。

  1. "scripts": {
  2. "preinstall": "echo here it comes!",
  3. "postinstall": "echo there it goes!",
  4. "start": "node index.js",
  5. "test": "tap test/*.js"
  6. }

扩展阅读:npm scripts 使用指南

package-lock.json

npm 5 以前是不会有 package-lock.json 这个文件的。(被开发者诟病,吐槽的问题)。

以前会自作多情的自动给你升级。

npm 5 以后才加入了这个文件。

当你安装包的时候,npm 都会生成或者更新 package-lock.json 这个文件。

  • npm 5 以后的版本安装包不需要加 --save 参数,它会自动保存依赖信息
  • 当你安装包的时候,会自动创建或者是更新 package-lock.json 这个文件
  • package-lock.json 这个文件会保存 node_modules 中所有包的信息(版本、下载地址)
    • 这样的话重新 npm install 的时候速度就可以提升
  • 从文件来看,有一个 lock 称之为锁
    • 这个 lock 是用来锁定版本的
    • 如果项目依赖了 1.1.1 版本
    • 如果你重新 isntall 其实会下载最新版本,而不是 1.1.1
    • 我们的目的就是希望可以锁住 1.1.1 这个版本
    • 所以这个 package-lock.json 这个文件的另一个作用就是锁定版本号,防止自动升级新版

扩展阅读

小结