NPM 与 package.json
NPM
nodejs模块化命令行工具
npm的主要功能
- 从
npm服务器下载第三方模块到本地,比如vue - 从
npm服务器下载命令行程序使用,比如vue-cli、rollup - 自己编写模块或者命令行程序上传到
npm服务器供他人使用
注册使用npm
- 登录npm,注册账户
- 安装
node,自带npm,常用操作:
npm whoami:检查是否登录npm login或npm add user进行登录npm config ls查看配置信息npm logout退出登录
幽灵依赖 问题
当我们用 npm 安装依赖时,他会把所有的依赖和依赖中的所有东西都打包到 node_modules 文件夹下。这种方式就是所谓的“扁平化方式”。 让我们在实践中来看看。下面是 package.json:
{
"dependencies": {
"unified": "10.1.0"
}
}在运行 npm install 之后,node_modules 会变成下面这样:
node_modules
├── @types
├── bail
├── extend
├── is-buffer
├── is-plain-obj
├── trough
├── unified
├── unist-util-stringify-position
├── vfile
└── vfile-message虽然这种方式已经工作了许多年,但是这种方式会导致一些问题,我们称这种问题叫做:“幽灵依赖”。
(例如)在我们项目中声明的唯一的依赖是 unified,但我们仍然能在我们的项目代码中引用到 is-plain-obj 模块 (unified 的依赖):
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
指定代码库的存放地址,方便查看模块的源码
{
"repository": {
"type": "git",
"url": "https://github.com/npm/cli.git",
// 指定目录
"directory": "packages/react-dom"
}
}bugs
bugs用于项目问题的反馈issue地址或者一个邮箱
"bugs": {
"url" : "https://github.com/owner/project/issues",
"email" : "project@hostname.com"
}files:选择上传到npm的文件
- 未配置此字段则默认忽略
.gitignore中的内容 - 指示
npm publish的时候需要上传的内容,如:dist package.json、readme.md、CHANGELOG.md、LICENSE会包含在其中
依赖:dependencies
dependencies:业务依赖模块 使用npm i package --save进行安装,在npm5.x开始可以忽略--save,要关闭此功能,使用npm config set save falsedevDependencies:开发环境依赖模块 使用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
一个模块通常只导出一个模块,但是有时候也有需要同时导出多个模块供使用的情况:
{
"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模块types:typescript类型入口文件,提供模块的类型声明
scripts:执行命令
添加自定义执行命令,也可以添加npm的生命周期钩子:
{
"scripts":{
// 在发布模块之前执行此命令
"prepublishOnly":"npm run build"
}
}更多钩子:npm scripts
config
可以用于添加命令行的环境变量 如有一个packge.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得到truenpm 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命令来安装:
# 修改默认源
npm config set registry https://registry.npmmirror.com
# 查看配置信息
npm config list需要还原时:
npm config set registry https://registry.npmjs.org使用npm安装git模块
如不想额外的部署私有模块化仓库,也不想将模块发布到npm公共平台上,可以选择直接安装私有git仓库如gitlab上的模块:
如平常使用git一样,需要在gitlab上设置ssh key,使用如下方式安装git模块
github
npm i github:livelybone/vue-select#latestgit+ssh
npm i git+ssh://git@github.com/livelybone/vue-select.gitgit+http
npm i git+http://git.gxucreate.com:8091/sgz/bh-practitioners-nucleic-web.git使用tag来区分git模块版本
- 为
git版本库指定提交设置tag并推送到远程 - 安装模块的的时候使用
#选择指定tag安装,如:
npm i git+http://git.gxucreate.com:8091/sgz/bh-practitioners-nucleic-web.git#2.0.1本地调试 npm 包方法
- 常规调试
- 直接全局安装进行调试
- 在脚手架目录使用
npm link
- 分包调试:
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.json的name
