npm 与 package.json 快速入门教程

2017-08-02 19:16:20 拭心 阅读数 78648更多

分类专栏: 学学前端
 
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。

npm 是前端开发广泛使用的包管理工具,之前使用 Weex 时看了阮一峰前辈的文章了解了一些,这次结合官方文章总结一下,加深下理解吧!

读完本文你将了解:

什么是 npm?

官方文档中对它的介绍是:

npm makes it easy for JavaScript developers to share and reuse code, and it makes it easy to update the code that you’re sharing.

即: npm 是一个包管理器,它让 JavaScript 开发者分享、复用代码更方便(有点 maven 的感觉哈)。

在程序开发中我们常常需要依赖别人提供的框架,写 JS 也不例外。这些可以重复的框架代码被称作包(package)或者模块(module),一个包可以是一个文件夹里放着几个文件,同时有一个叫做 package.json 的文件。

一个网站里通常有几十甚至上百个 package,分散在各处,通常会将这些包按照各自的功能进行划分(类似我们安卓开发中的划分子模块),但是如果重复造一些轮子,不如上传到一个公共平台,让更多的人一起使用、参与这个特定功能的模块。

而 npm 的作用就是让我们发布、下载一些 JS 轮子更加方便。

我们可以去官方网站 https://www.npmjs.com/ 浏览、搜索想要的轮子,也可以直接在命令行中 search 一下意中轮。

使用 npm 后我们可以非常方便地查看依赖的轮子是否有更新、是否需要下载新版本。

现在我们知道 npm 是干什么的了。当人们说起 “npm” 时,可能在说三个东西:

  1. 一个网站,就是前面提到用于搜索 JS 模块的网站:https://www.npmjs.com/
  2. 一个仓库,保存着人们分享的 JS 模块的大数据库
  3. 命令行里的客户端,开发者使用它来管理、安装、发布模块

只要开发者发布某个模块到仓库中,其他人就可以从 npm 网站或者命令行中下载、使用它了!

安装 npm

npm 是依附于 node.js 的,我们可以去它的官网 https://nodejs.org/en/download/ 下载安装 node.js。

下载好 node.js, npm 也就有了,使用 npm -v 查看安装的 npm 版本:

zhangshixin$ node -v
v6.10.0
  • 1
  • 2

更新 npm

npm 更新地可比 node 勤快多了,因此你下载的 node 附带的 npm 版本可能不是最新的,你可以使用如下命令下载最新 npm:

npm install npm@latest -g
  • 1

其中 install 不用介绍了,就是安装,后面的 npm@latest 就是 <packageName>@<version> 的格式,我们在下载其他模块时也是这个格式。-g 代表全局安装。

package.json 文件

package.json 文件非常重要,因此需要单独一小节介绍。

管理本地安装 npm 包的最好方式就是创建 package.json 文件。

一个 package.json 文件可以有以下几点作用:

  1. 作为一个描述文件,描述了你的项目依赖哪些包
  2. 允许我们使用 “语义化版本规则”(后面介绍)指明你项目依赖包的版本
  3. 让你的构建更好地与其他开发者分享,便于重复使用

package.json 如何创建

使用 npm init 即可在当前目录创建一个 package.json 文件:

如图所示,输入 npm init 后会弹出一堆问题,我们可以输入对应内容,也可以使用默认值。在回答一堆问题后输入 yes 就会生成图中所示内容的 package.json 文件。

如果嫌回答这一大堆问题麻烦,可以直接输入 npm init --yes 跳过回答问题步骤,直接生成默认值的 package.json 文件:

package.json 的内容

package.json 文件至少要有两部分内容:

  1. “name”

    • 全部小写,没有空格,可以使用下划线或者横线
  2. “version”
    • x.x.x 的格式
    • 符合“语义化版本规则”

比如:

{
"name": "shixinzhang-demo-package",
"version": "1.0.0"
}
  • 1
  • 2
  • 3
  • 4

其他内容:

  • description:描述信息,有助于搜索
  • main: 入口文件,一般都是 index.js
  • scripts:支持的脚本,默认是一个空的 test
  • keywords:关键字,有助于在人们使用 npm search 搜索时发现你的项目
  • author:作者信息
  • license:默认是 MIT
  • bugs:当前项目的一些错误信息,如果有的话

我们可以为 init 命令设置一些默认值,比如:

> npm set init.author.email "shixinzhang2016@gmail.com"
> npm set init.author.name "shixinzhang"
> npm set init.license "MIT"
  • 1
  • 2
  • 3

注意:
如果 package.json 中没有 description 信息,npm 使用项目中的 README.md 的第一行作为描述信息。这个描述信息有助于别人搜索你的项目,因此建议好好写 description 信息。

指定依赖的包

我们需要在 package.json 文件中指定项目依赖的包,这样别人在拿到这个项目时才可以使用 npm install 下载。

包有两种依赖方式:

  1. dependencies:在生产环境中需要用到的依赖
  2. devDependencies:在开发、测试环境中用到的依赖

举个例子:

{
"name": "my-weex-demo",
"version": "1.0.0",
"description": "a weex project",
"main": "index.js",
"scripts": {
"build": "weex-builder src dist",
"build_plugin": "webpack --config ./tools/webpack.config.plugin.js --color",
"dev": "weex-builder src dist -w",
"serve": "serve -p 8080"
},
"keywords": [
"weex"
],
"author": "fkysly@gmail.com",
"license": "MIT",
"devDependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.18.0",
"vue-loader": "^10.0.2",
"eslint": "^3.5.0",
"serve": "^1.4.0",
"webpack": "^1.13.2",
"weex-loader": "^0.3.3",
"weex-builder": "^0.2.6"
},
"dependencies": {
"weex-html5": "^0.3.2",
"weex-components": "*"
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Semantic versioning(语义化版本规则)

https://docs.npmjs.com/getting-started/semantic-versioning

dependencies 的内容,以 "weex-html5": "^0.3.2" 为例,我们知道 key 是依赖的包名称,value 是这个包的版本。那版本前面的 ^ 或者版本直接是一个 * 是什么意思呢?

这就是 npm 的 “Semantic versioning”,简称”Semver”,中文含义即“语义化版本规则”。

在安卓开发中我们有过这样的经验:有时候依赖的包升级后大改版,之前提供的接口不见了,这对使用者的项目可能造成极大的影响。

因此我们在声明对某个包的依赖时需要指明是否允许 update 到新版本,什么情况下允许更新。

这就需要先了解 npm 包提供者应该注意的版本号规范。

如果一个项目打算与别人分享,应该从 1.0.0 版本开始。以后要升级版本应该遵循以下标准:

  • 补丁版本:解决了 Bug 或者一些较小的更改,增加最后一位数字,比如 1.0.1
  • 小版本:增加了新特性,同时不会影响之前的版本,增加中间一位数字,比如 1.1.0
  • 大版本:大改版,无法兼容之前的,增加第一位数字,比如 2.0.0

了解了提供者的版本规范后, npm 包使用者就可以针对自己的需要填写依赖包的版本规则。

作为使用者,我们可以在 package.json 文件中写明我们可以接受这个包的更新程度(假设当前依赖的是 1.0.4 版本):

  • 如果只打算接受补丁版本的更新(也就是最后一位的改变),就可以这么写:

    • 1.0
    • 1.0.x
    • ~1.0.4
  • 如果接受小版本的更新(第二位的改变),就可以这么写:
    • 1
    • 1.x
    • ^1.0.4
  • 如果可以接受大版本的更新(自然接受小版本和补丁版本的改变),就可以这么写:
    • *
    • x

小结一下:总共三种版本变化类型,接受依赖包哪种类型的更新,就把版本号准确写到前一位。

安装 package

使用 npm 安装 package 有两种方式:本地(当前项目路径)安装 或者 全局安装。

你选择哪种安装方式取决于你将如何使用这个包:

  • 如果你只是想在当前项目里用 require() 加载使用,那你可以安装到本地

    • npm install 默认就是安装到本地的
  • 如果你想要在命令行里直接使用,比如 grunt CLI,就需要安装到全局了

如果在你的项目里有 package.json 文件,运行 npm install 后它会查找文件中列出的依赖包,然后下载符合语义化版本规则的版本。

npm install 默认会安装 package.json 中 dependencies 和 devDependencies 里的所有模块。

如果想只安装 dependencies 中的内容,可以使用 --production 字段:

npm install --production
  • 1

本地安装 package

npm 使用下面的命令下载一个包:

npm install <package_name>
  • 1

后面就是要安装包的名称。这个命令会在当前目录创建一个 node_modules 目录,然后下载我们指定的包到这个目录中。

举个例子:

zhangshixindeMacBook-Pro:publish-pkg zhangshixin$ npm install lodash
zhangshixindeMacBook-Pro:publish-pkg zhangshixin$ ls
index.js package-lock.json
node_modules package.json
zhangshixindeMacBook-Pro:publish-pkg zhangshixin$ ls node_modules/
lodash
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下载后的项目文件夹:

安装指定版本:

npm install 默认安装最新版本,如果想要安装指定版本,可以在库名称后加 @版本号

$ npm install sax@latest
$ npm install sax@0.1.1
$ npm install sax@">=0.1.0 <0.2.0"
  • 1
  • 2
  • 3

如果当前项目有 package.json 文件,下载包时会下载这个文件中指定的版本;
如果当前项目中没有 package.json 文件,就会下载指定包的最新版本。

有时下载会报错:npm install error saveError ENOENT: no such file or directory, open '/Users/zhangshixin/package.json'

解决办法:
- 在目录下执行 npm init 创建 package.json,输入初始化信息
- 然后再执行下载命令

安装参数 --save 和 --save -dev

添加依赖时我们可以手动修改 package.json 文件,添加或者修改 dependencies devDependencies 中的内容即可。

另一种更酷的方式是用命令行,在使用 npm install 时增加 --save 或者 --save -dev 后缀:

  • npm install <package_name> --save 表示将这个包名及对应的版本添加到 package.json的 dependencies
  • npm install <package_name> --save-dev 表示将这个包名及对应的版本添加到 package.json的 devDependencies

使用下载好的包

下载后 node_modules 文件夹中有要使用的包,我们就可以使用其中的代码了。

比如在 Node.js 项目中,我们可以用 require(XXX) 引入它。

举个例子:
创建一个 index.js 文件,写入如下代码:

在使用 require('lodash') 后引入了 lodash 库,然后调用了它的 without() 方法,这个方法可以去除第一个数组参数中与第二个参数重复的数据。

保存这个文件后,使用 node index.js 运行这个文件,成功的话就可以得到运行结果;如果之前安装失败,可能就会遇到这个错误:

module.js:340
throw err;
^
Error: Cannot find module 'lodash'
  • 1
  • 2
  • 3
  • 4

这时你需要在这个目录下重新运行 npm install lodash 安装。

更新本地 package

有时候我们想知道依赖的包是否有新版本,可以使用 npm outdated 查看,如果发现有的包有新版本,就可以使用 npm update <package-name> 更新它,或者直接 npm update 更新所有:

上图中,我们在输入 npm update 后发现本地的 lodash 模块还不是最新的,这是为什么呢?

原来,npm update 的工作过程是这样的:

  1. 先到远程仓库查询最新版本
  2. 然后对比本地版本,如果本地版本不存在,或者远程版本较新
  3. 查看 package.json 中对应的语义版本规则
  4. 如果当前新版本符合语义规则,就更新,否则不更新

一开始我本地的 package.json 的依赖是这样的:

  "dependencies": {
"lodash": "^3.1.0"
}
  • 1
  • 2
  • 3

根据前面的介绍我们可以知道,这表示只接受小版本或者补丁版本的更新,因此在执行了一次 npm update 后它变成了这样:

  "dependencies": {
"lodash": "^3.10.1"
}
  • 1
  • 2
  • 3

第二位升到了最高,但是无法更新第一位,因此无法更新到最新的 4.17.4。

所以我需要把它修改成:

  "dependencies": {
"lodash": "*"
}
  • 1
  • 2
  • 3

这表示任何版本的更新都接受,然后再执行 npm update,就发现更新成功了:

小结一下:

执行 npm outdated 后可以看到有三个版本号:

第一个是当前 node_modules 中该模块的版本,第二个是 package.json 文件中声明的版本,第三个是远程仓库最新的版本。

只有当前模块版本低于远程,package.json 中的版本语义规则满足情况,才能更新成功。

卸载本地 package

卸载一个本地 package 很简单,npm uninstall <package-name> 即可:

官方文档说输入 npm uninstall --save lodash 才能在删除项目的同时移除 package.json 中对它的依赖。但我没加 --save 也达到了一样的效果,一脸懵逼。

卸载后再 ls node_modules/ 查看目录下,发现没有东西,删除成功。

全局安装 package

如果你想要直接在命令行中使用某个包,比如 jshint ,你可以全局安装它。

全局安装比本地安装多了个 -g:

npm install -g <package-name>
  • 1

以 jshint 为例,全局安装命令是:

npm install -g jshint
  • 1

安装后可以使用 npm ls -g --depth=0 查看安装在全局第一层的包。

全局安装的权限问题

在全局安装时可能会遇到 EACCES 权限问题,解决办法办法有如下 3 种:

1.sudo npm install -g jshint,使用 sudo 简单粗暴,但是治标不治本

2.修改 npm 全局默认目录的权限

先获取 npm 全局目录:npm config get prefix,一般都是 /usr/local
然后修改这个目录权限为当前用户:

 sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
  • 1

3.使用其他包管理器帮你解决这个问题

实在懒得弄可以直接卸载 node,然后使用 Homebrew 重装 node:

brew install node
  • 1

Homebrew 会帮我们处理好权限的问题。

更新全局的 package

想知道哪些包需要更新,可以使用 npm outdated -g --depth=0,然后使用 npm update -g <package>更新指定的包:

要更新所有全局包,可以使用 npm update -g,可以发现对比本地的,只是多了个 -g

不过官方说在 2.6.1 以下的 npm ,直接使用 npm update -g 并不安全,因为它会递归地更新所有全局依赖。

这种情况下可以使用 npm-check ,贴一张它的截图:

Github 地址:https://github.com/dylang/npm-check

卸载全局 package

一句搞定:npm uninstall -g <package>

其他命令

npm run

部分摘自 阮一峰的 NPM 教程

npm 还可以直接运行 package.json 中 scripts 指定的脚本:

{
"name": "demo",
"scripts": {
"lint": "jshint **.js",
"test": "mocha test/"
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

npm run 是 npm run-script 的缩写。

命令行输入 npm run lint 或者 npm run-script lint 就会执行 jshint **.js 。

npm run 会创建一个Shell,执行指定的命令,并临时将node_modules/.bin加入PATH 变量,这意味着本地模块可以直接运行。

package.json 中的 scripts 执行的脚本是本地项目内 node_modules -> .bin 内的脚本。

    "scripts": {
"build": "weex-builder src dist",
"build_plugin": "webpack --config ./tools/webpack.config.plugin.js --color",
"dev": "weex-builder src dist -w",
"serve": "serve -p 8080"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

直接运行 npm run 会列出当前项目的 package.json 中 scripts 属性下的所有脚本命令。

npm install from github

npm install 也可以直接从 github 下载:

$ npm install git://github.com/package/path.git
$ npm install git://github.com/package/path.git#0.1.0
  • 1
  • 2

npm info

npm info <package-name> 可以查看指定包的信息:

npm adduser

npm adduser 用于在npmjs.com注册一个用户:

$ npm adduser
Username: YOUR_USER_NAME
Password: YOUR_PASSWORD
Email: YOUR_EMAIL@domain.com
  • 1
  • 2
  • 3
  • 4

npm home/repo

npm home <package-name>命令可以打开指定模块的主页;
npm repo <package-name>命令则是打开指定模块的代码仓库。

npm prune

prune 即“修剪”的意思。

npm prune 可以检查出当前项目的 node_modules目录中,没有在 package.json里提到的模块。

npm publish

现在水平还不够,等写出可以复用的 JS 代码后,我们就可以将它发布到 npm 仓库上,类似 Github 的提交。

这部分主要摘自阮一峰的 NPM 教程

要想发布,首先需要使用 npm adduser向 npmjs.com申请用户名(当然去官网也可以)。

接着使用 npm login 在命令行中登录。

登录以后,就可以使用 npm publish命令发布。


$ npm publish
  • 1
  • 2

如果当前模块是一个beta版,比如1.3.1-beta.3,那么发布的时候需要使用tag参数,将其发布到指定标签,默认的发布标签是latest。


$ npm publish --tag beta
  • 1
  • 2

如果发布私有模块,模块初始化的时候,需要加上scope参数。只有npm的付费用户才能发布私有模块。


$ npm init --scope=<yourscope>
  • 1
  • 2

如果你的模块是用ES6写的,那么发布的时候,最好转成ES5。首先,需要安装Babel。


$ npm install --save-dev babel-cli@6 babel-preset-es2015@6
  • 1
  • 2

然后,在package.json里面写入build脚本。


"scripts": {
"build": "babel source --presets babel-preset-es2015 --out-dir distribution",
"prepublish": "npm run build"
}
  • 1
  • 2
  • 3
  • 4
  • 5

运行上面的脚本,会将source目录里面的ES6源码文件,转为distribution目录里面的ES5源码文件。

国内镜像

不翻的话有时候 npm 比较卡,可以使用国内的淘宝镜像 cnpm: https://npm.taobao.org

cnpm 支持 npm 除了 publish 之外的所有命令。

总结

经过这么一番总结,总算可以说 npm 入门了。

接触前端后发现这个圈子太复杂了,各种工具各种框架,眼花缭乱啊。一步一步来吧!

Thanks

https://docs.npmjs.com/
http://javascript.ruanyifeng.com/nodejs/npm.html#


[转载]npm 与 package.json 快速入门教程的更多相关文章

  1. npm 与 package.json 快速入门教程

    npm 与 package.json 快速入门教程 2017年08月02日 19:16:20 阅读数:33887 npm 是前端开发广泛使用的包管理工具,之前使用 Weex 时看了阮一峰前辈的文章了解 ...

  2. npm与package.json快速入门

    本文转载自npm与package.json快速入门 导语 npm 是前端开发广泛使用的包管理工具,之前使用 Weex 时看了阮一峰前辈的文章了解了一些,这次结合官方文章总结一下,加深下理解吧! 读完本 ...

  3. npm 与 package.json 快速入门

    npm 是前端开发广泛使用的包管理工具,之前使用 Weex 时看了阮一峰前辈的文章了解了一些,这次结合官方文章总结一下,加深下理解吧! 读完本文你将了解: 什么是 npm 安装 npm 更新 npm ...

  4. .NET Core快速入门教程 2、我的第一个.NET Core App(Windows篇)

    一.前言 本篇开发环境?1.操作系统: Windows 10 X642.SDK: .NET Core 2.0 Preview 二.安装 .NET Core SDK 1.下载 .NET Core下载地址 ...

  5. .NET Core快速入门教程 4、使用VS Code开发.NET Core控制台应用程序

    一.前言 为什么选择VS Code?VS Code 是一款跨平台的代码编辑器,想想他的哥哥VS,并是微软出品的宇宙第一IDE,那作为VS的弟弟,VS Code 也不会差,毕竟微软出品.反正ken是这么 ...

  6. .NET Core快速入门教程 3、我的第一个.NET Core App (CentOS篇)

    一.前言 本篇开发环境?1.操作系统:CentOS7(因为ken比较偏爱CentOS7)2.SDK版本:.NET Core 2.0 Preview 你可能需要的前置知识1.了解如何通过Hyper-V安 ...

  7. Spring Boot:快速入门教程

    什么是Spring Boot? Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人 ...

  8. Realm for Android快速入门教程

    介绍 如果你关注安卓开发的最新趋势,你可能已经听说过Realm.Realm是一个可以替代SQLite以及ORMlibraries的轻量级数据库. 相比SQLite,Realm更快并且具有很多现代数据库 ...

  9. npm的package.json字段含义中文文档

    简介 本文档有所有package.json中必要的配置.它必须是真正的json,而不是js对象. 本文档中描述的很多行为都受npm-config(7)的影响. 默认值 npm会根据包内容设置一些默认值 ...

随机推荐

  1. redis相关操作命令

    一.相关命令列表: 命令原型 时间复杂度 命令描述 返回值 KEYS pattern O(N) 时间复杂度中的N表示数据库中Key的数量.获取所有匹配pattern参数的Keys.需要说明的是,在我们 ...

  2. Linux内核编译、安装流程

    原文链接:https://blog.csdn.net/qq_28437139/article/details/83692907 此处只讲linux内核编译步骤至于安装虚拟机,安装ubuntu操作系统请 ...

  3. Hadoop Join

    1. Reduce Join工作原理 Map端的主要工作:为来自不同表或文件的key/value对,打标签以区别不同来源的记录.然后用连接字段作为key,其余部分和新加的标志作为value,最后进行输 ...

  4. U1. 广度优先搜索(BFS)和 广度优先搜索(DFS)

    广度优先搜索用栈(stack)来实现,整个过程可以想象成一个倒立的树形: 1.把根节点压入栈中. 2.每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中.并把这个元素记为它下一级元素 ...

  5. python中传统除法、真除法和Floor除法

    1.python2.6及其之前,x/y是传统除法,对于整数会省去小数部分,对于浮点数会保持小数部分. 2.python3中x/y表示真除法,无论任何数据类型都会保留小数部分. 3.python2和3中 ...

  6. JVM Java 内存区域透彻分析(转)

    出处:  Java 内存区域透彻分析  Java8内存模型—永久代(PermGen)和元空间(Metaspace) 这篇文章主要介绍Java内存区域,也是作为Java虚拟机的一些最基本的知识,理解了这 ...

  7. 『Linux』第一节: 部署虚拟环境

    一. 准备工具 1. VMware Workstation Pro下载 1.1 VMware Workstation Pro 激活许可证 UY758-0RXEQ-M81WP-8ZM7Z-Y3HDA V ...

  8. ActiveMQ Topic使用示例

    一.非持久的Topic Topic 发送 public class NoPersistenceSender { public static void main(String[] args) throw ...

  9. springboot 整合 web 项目找不到 jsp 文件

    今天遇到一个问题,就是使用springboot整合web项目的时候,怎么都访问不到 \webapp\WEB-INF\jsp\index.jsp 页面.这个问题搞了半天,试了各种方式.最后是因为在启动的 ...

  10. Prometheus Grafana监控全方位实践

    这次就不用 docker 部署服务了,这样大家会更容易接受.欢迎阅读. 引言 Prometheus 是一个监控系统,也是一个时间序列数据库,用Go语言开发的,官方文档.通过从某些特定的目标如主机,My ...