Skip to content

NPMpackage.json

NPM

nodejs模块化命令行工具

npm的主要功能

  • npm服务器下载第三方模块到本地,比如vue
  • npm服务器下载命令行程序使用,比如vue-clirollup
  • 自己编写模块或者命令行程序上传到npm服务器供他人使用

注册使用npm

  1. 登录npm,注册账户
  2. 安装node,自带npm,常用操作:
  • npm whoami:检查是否登录
  • npm loginnpm add user 进行登录
  • npm config ls 查看配置信息
  • npm logout 退出登录

幽灵依赖 问题

当我们用 npm 安装依赖时,他会把所有的依赖和依赖中的所有东西都打包到 node_modules 文件夹下。这种方式就是所谓的“扁平化方式”。 让我们在实践中来看看。下面是 package.json

json
{
  "dependencies": {
    "unified": "10.1.0"
  }
}

在运行 npm install 之后,node_modules 会变成下面这样:

json
node_modules
├── @types
├── bail
├── extend
├── is-buffer
├── is-plain-obj
├── trough
├── unified
├── unist-util-stringify-position
├── vfile
└── vfile-message

虽然这种方式已经工作了许多年,但是这种方式会导致一些问题,我们称这种问题叫做:“幽灵依赖”。

(例如)在我们项目中声明的唯一的依赖是 unified,但我们仍然能在我们的项目代码中引用到 is-plain-obj 模块 (unified 的依赖):

js
import ob from "is-plain-obj";

console.log(ob); // [Function: isPlainObject]

因为上述这种情况是可能发生的,所以我们声明的依赖以及依赖的依赖也可能出现这种问题,即在没有声明某个依赖作为依赖或对等依赖(peerDependency)的前提下,从 node_modules 中引入了这个依赖。

package.json

用来描述项目及项目所依赖的模块信息

name

推荐使用全小写和-作为包的名称,如:validate-npm-package-name 可以使用此命令来查询模块名称是否已经被使用:npm view <packageName>

description

用于书写描述此模块的基本信息。 如果你希望你模块被更多人搜索使用,这个字段是必不可少的,它能帮助人们在npm库中快速搜索到你的模块

keywords

这是一个字符串数组,可以将一个个关键字字符串填入。 同样是为了帮助人们搜索到此模块

version

语义化版本 - semver 版本格式:主版本号.次版本号.修订号(1.0.0),版本号递增规则如下

  • 主版本号:当你做了不兼容的API修改
  • 次版本号:当你做了向下兼容的功能性新增
  • 修订号:当你做了向下兼容的问题修正

homepage

用于放置此模块的主页,可以是使用文档、demo

repository

指定代码库的存放地址,方便查看模块的源码

json
{
  "repository": {
    "type": "git",
    "url": "https://github.com/npm/cli.git",
    // 指定目录
    "directory": "packages/react-dom"
  }
}

bugs

bugs用于项目问题的反馈issue地址或者一个邮箱

json
"bugs": {
  "url" : "https://github.com/owner/project/issues",
  "email" : "project@hostname.com"
}

files:选择上传到npm的文件

  • 未配置此字段则默认忽略.gitignore中的内容
  • 指示npm publish的时候需要上传的内容,如:dist
  • package.jsonreadme.mdCHANGELOG.mdLICENSE会包含在其中

依赖:dependencies

  • dependencies:业务依赖模块 使用npm i package --save进行安装,在npm5.x开始可以忽略--save,要关闭此功能,使用npm config set save false

  • devDependencies:开发环境依赖模块 使用npm i -D或者npm i --save-dev进行安装

  • peerDependencies:使用此项目应安装的模块

安装依赖包的版本

相信大家都会经历过,我们安装一些依赖包的时候,版本号前面都会带 ^ 或者 ~ 的符号,这两个符号代表什么意思呢?

  • ~ 会匹配最近的小版本依赖包,比如 ~1.2.3 会匹配所有 1.2.x 版本,但是不包括 1.3.0
  • ^ 会匹配最新的大版本依赖包,比如 ^1.2.3 会匹配所有 1.x.x 的包,包括 1.3.0,但是不包括 2.0.0
  • * 安装最新版本的依赖包,比如 *1.2.3 会匹配 x.x.x

当我们安装模块的时候,该如何选择那种符号设置模块? 写死一个版本号,这样没问题,但是当模块发布小版本对bug修复时,我们又需要对版本号进行修改,有点麻烦。 当使用^*时,版本改动会比较大,很有可能会造成版本不兼容,不推荐使用。 建议使用~标记版本号,可以保证项目不会出现大问题,小版本的bug也可以得到修复。

指定导出模块 exports

一个模块通常只导出一个模块,但是有时候也有需要同时导出多个模块供使用的情况:

json
{
  "exports":{
    // 默认导出
    ".":"index.js",
    // 根据引用的方式来决定导出模块
    "./sub":{
      "import":"./import.js",
      "require":"./require.js",
      "types":"./types/index.d.ts"
    },
    // 根据环境区分
    "./path":{
      "import":{
        "default":"./path/index.js",
        "node":"./path/node.js"
      }
    }
  }
}

模块入口文件

  • main:常规脚本文件,指向模块根脚本
  • module:非官方字段,打包工具会优先查找此字段获得es module模块
  • typestypescript类型入口文件,提供模块的类型声明

scripts:执行命令

添加自定义执行命令,也可以添加npm的生命周期钩子:

json
{
  "scripts":{
    // 在发布模块之前执行此命令
    "prepublishOnly":"npm run build"
  }
}

更多钩子:npm scripts

config

可以用于添加命令行的环境变量 如有一个packge.json如下:

json
{
  "name" : "writepress",
  "config" : { "port" : "8080" },
  "scripts" : { "start" : "node server.js" }
}

server.js中就可以通过此方式获得config字段:process.env.npm_package_config_port

也可以在命令行上加上标志使脚本得到配置如:

  • npm run start --port,在server.js中通过process.env.npm_config_port得到true
  • npm run start --port=8080,在server.js中通过process.env.npm_config_port得到8080

若想将参数透传给nodejs命令,可在参数前添加--,如:npm run start -- --port=8080 --env=dev透传给nodejs

发布相关问题

  • 当发布出现402错误时,表示发布的包为私有包,应该通过发布公开包的方式进行发布:

    • 通过npm publish --access public
    • package.json中配置:
    json
      "publishConfig": {
          "access": "public"
      },

package-lock.json

保证多人开发时,大家安装模块的一致性。

出现的原因

当我们使用~^*等符号标记模块时,就有可能出现每个人安装的模块版本不一致的情况:一个同事安装了模块,不久后模块更新了新版本,之后另一个同事进行了安装。

有人说:那我每个模块写死版本号,不用这些符号标记模块就好了,每个人安装的都是指定的版本号。这种方式确实保证了项目安装的模块的一致性,但是忽略了模块里面也是有依赖的,模块里面的依赖我们是不能修改成为固定版本号的。

所以package-lock.json诞生了:package-lock.json 它会在 npm 更改 node_modules 目录树 或者 package.json 时自动生成的。

当我们使用npm install时,会自动生成一个package-lock.json文件在package.json同级目录下,当我们下次npm install时,会根据package-lock.json来处理依赖,保证模块安装的一致性。

cnpm install

值得注意的是,使用其他命令时是不会生成package-lock.json,也不会按照package-lock.json来处理依赖的。 既想要淘宝源的速度,又想保证模块的一致性,可使用下面的方式将npm的默认源修改为淘宝源,使用npm命令来安装:

bash
# 修改默认源
npm config set registry https://registry.npmmirror.com
# 查看配置信息
npm config list

需要还原时:

bash
npm config set registry https://registry.npmjs.org

使用npm安装git模块

如不想额外的部署私有模块化仓库,也不想将模块发布到npm公共平台上,可以选择直接安装私有git仓库如gitlab上的模块:

如平常使用git一样,需要在gitlab上设置ssh key,使用如下方式安装git模块

  • github
bash
  npm i github:livelybone/vue-select#latest
  • git+ssh
bash
  npm i git+ssh://git@github.com/livelybone/vue-select.git
  • git+http
bash
  npm i git+http://git.gxucreate.com:8091/sgz/bh-practitioners-nucleic-web.git

使用tag来区分git模块版本

  1. git版本库指定提交设置tag并推送到远程
  2. 安装模块的的时候使用#选择指定tag安装,如:
bash
  npm i git+http://git.gxucreate.com:8091/sgz/bh-practitioners-nucleic-web.git#2.0.1

本地调试 npm 包方法

  1. 常规调试
    1. 直接全局安装进行调试
    2. 在脚手架目录使用npm link

  1. 分包调试:npm link module

  • 理解 npm link
    • npm link:将当前项目链接到node全局node_modules中作为一个库文件,并解析bin配置创建可执行文件
    • npm link module:将当前项目中node_modules下指定库module链接到node全局node_modules下的库module

  • 理解 npm unlink
    • npm unlink:将当前项目从node全局node_modules中移除
    • npm unlink module:移除当前项目中node_modules下指定库module 对全局库module的链接
    • npm unlink失败:检查是否修改过package.jsonname