文章内容输出来源:拉勾教育高薪前端训练营
来拉勾教育学习了有一个多月了,感觉学的还是提不错的,引导作用感很强,相比之前自己一个人忙忙碌碌的却又很难提高效率,甚是困惑,有些知识概念就是很难深入理解,学习之后感觉就好很多。
以下呢就是一些关于前端包管理的一些整理点,简单分享下。。
1. npm、yarn、cnpm安装
- 只要安装node一般都会自带安装npm
- 安装 yarn:
npm install yarn -g
- 安装 cnpm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
2. npm 发布包
2.1 npm 包文件准备
步骤1: 在 github 上新建一个项目(选择 MIT 证书类型的开源协议,并勾选新建一个 README.md 文件)
步骤2: 把 github 上的该项目克隆到本地。
步骤3: 在该项目根目录下执行 npm init 初始化 package.json 文件,见下面第5点
# 初始化 package.json
npm init
示例如下:
{
"name": "xxx",
"version": "1.0.0",
"description": "Some common methods are summarized",
"main": "index.js",
"author": "xxx ",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"homepage": "https://github.com/xxx/yyy",
"bugs": "https://github.com/xxx/yyy/issues",
"repository": {
"type": "git",
"url": "https://github.com/xxx/yyy"
},
"keywords": [
"common",
"functions",
"tool"
],
"license": "MIT"
}
步骤4: 添加一些过滤文件
- 添加 .gitignore 文件。
.DS_Store
node_modules/
-
添加 npm 包过滤上传文件
.npmignore
当你上传包到npm库时,有一些本地的依赖文件和测试demo等不想上到npm库里,这时就要用到.npmignore过滤文件了
步骤5: 修改 README.md 文件,里面的首行图标可以在 https://shields.io/ 上制作。
![https://img.shields.io/badge/version-1.0.0-blue.svg](https://img.shields.io/badge/version-1.0.0-blue.svg)
![https://img.shields.io/badge/license-MIT-brightgreen.svg](https://img.shields.io/badge/license-MIT-brightgreen.svg)
## Usage
1. `cd` to your project directory, and install the package, `npm i -S xxxx` or `yarn add xxx`.
2. use the package in your project, `import Funs from 'xxx'`.
## Contribution
- [@defeng li](mailto:[email protected]) The main author.
## Questions
Feel free to [contact me](mailto:[email protected]) or [create an issue](https://github.com/xxx/xxx/issues/new)
步骤6: 添加主入口文件 index.js
function sayHelloWorld() {
console.log("Hello world !");
}
module.exports = sayHelloWorld;
至此这个简单的项目基本写好了,大致目录结构如下
xxx
├── .git // git隐藏文件
├── README.md // 说明文档
├── index.js // 项目主入口
├── .gitignore // git过滤文件
├── package.json // 包信息
└── LICENSE // github开源协议文件
2.2 登录并发布
注册 npm 账号: 在 npm 网上 https://link.jianshu.com?t=https://www.npmjs.com/signup 注册一个账号,注意注册邮箱有要求(可以使用 gmail 邮箱)。
# 使用 npm adduser 命令输入用户名(Username)、密码(Password)和邮箱(Email)登录刚才注册的 npm 账号
npm adduser
# 在包根目录下发布
npm publish --access=public --registry=https://registry.npmjs.org/
yarn publish --access=public --registry=https://registry.yarnpkg.com/
# 看看刚刚发布的包是否已成功发布,如果报404错误表示发布失败,否则表示发布成功,并在项目里安装使用下会不会有问题。
npm view some-name
注意:
- 登录和发布 npm 包的时候不能使用淘宝镜像,必须使用 npm 地址,可以使用 nrm use npm 切换到 npm 的地址,或者添加--registry参数,如果不是用的 npm 的地址一般是报
no_perms Private mode enable, only admin can publish this module
的错。 - 报
Error: EPERM: operation not permitted, unlink
错时,自己是把 package.json 文件里的 test 键值对删除了,和把export default funs
改成了module.exports = funs
解决的,希望有所参考。
2.3 更新发布的 npm 包
- 修改包的版本(package.json里的version字段,可以直接修改改文件,或者使用上面的 npm version 命令修改)
- 对于"version":"x.y.z"(major主版本 . minor次要版本 . patch小版本)
- 修复bug,小改动,增加z
- 增加了新特性,但仍能向后兼容,增加y
- 有很大的改动,无法向后兼容,增加x
- 提交项目最新的代码到 github 上。
- 在项目根目录下执行 npm publish 命令发布更新最新的 npm 包。
- 在项目上更新包查看下。
2.4 撤销发布的 npm 包
在项目的根目录下使用上面的 npm unpublish 命令。
3. 版本定义
npm包
中的模块版本都需要遵循SemVer
规范——由Github
起草的一个具有指导意义的,统一的版本号表示规则。实际上就是Semantic Version
(语义化版本)的缩写
3.1 版本命名规则
我们常见的版本命名格式为:[name].x.y.z-[state]
name 为可选字段,一般为
v
,表示 version-
x.y.z 为各版本的序号,遵循 语义化版本命名规范,实际上基于此规范,不应该在版本前出现 name 字段.
序号 格式要求 说明 x 非负整数 主版本号(major),进行不向下兼容的修改时,递增主版本号 y 非负整数 次版本号(minor),保持向下兼容,新增特性时,递增次版本号 z 非负整数 修订号(patch),保持向下兼容,修复问题但不影响特性时,递增修订号 -
0.y.z
表示开发阶段,一切可能随时改变,非稳定版。 -
1.0.0
界定此版本为初始稳定版,后面的一切更新都基于此版本进行修改。
-
-
state 可选字段,表示版本状态,例如
b
表示 beta 测试版,其他常见状态,后有详述描述方式 说明 含义 α
或a
alpha 版 内测版本,内部测试的版本,bug 较多 β
或b
beta 版 公测版本,给外部进行测试的版本,有缺陷 γ
或g
Gamma 版 相当成熟的测试版,于发行版相差无几 rc
Release Candidate 是前面三种测试版的进一步版本,实现了全部功能,清除了大部分 bug,接近发布倒计时,有时会进一步细分为 rc1,rc2
实际上大部分前端工具均遵守上述规则
在商业软件中还会见到如下字段.
描述方式 | 说明 | 含义 |
---|---|---|
Demo |
演示版 | 只集成了正式版部分功能,无法升级 |
SP |
SP1 | 是 service pack 的意思表示升级包 |
Trial |
试用版 | 试用版 |
Unregistered |
未注册 | 有功能或时间限制的版本 |
Lite |
精简版 | 只含有正式版核心功能 |
enhance |
增强版 | 属于正式版1 |
free |
免费版 | 自由使用版本 |
release |
发行版 | 有时间限制 |
upgrade |
升级版 | 有功能增强或修复 bug |
Retail |
零售版 | 单独发售 |
Cardware |
共享版 | 公用许可证 |
3.2 版本限定
-
在进行包管理时,为了保证安装依赖的兼容性,必须对依赖包版本进行限定.参考 npm 限定描述,如下示例表示安装
0.13.22
版本的 karma。{ "devDependencies": { "karma": "0.13.22" } }
-
为了方便理解,版本限定的语法简述为为: [范围描述]<版本号描述> 其中范围描述可选
范围描述:
-
<
小于某一版本号 -
<=
小于等于某一版本号 -
>
大于某一版本号 -
>=
大于等于某一版本号 -
=
等于某一版本号,没有意义和直接写该版本号一样 -
~
基于版本号描述的最新补丁版本 -
^
基于版本号描述的最新兼容版本 -
-
某个范围,他应该出现在两个版本描述中间,实际上语法应为: <版本描述>-<版本描述>,写在此处为了统一
严格来讲对
~
、^
的表述需要结合具体的包管理工具和版本号规则来确定,但是对于一般使用记住如下原则:-
^
是确保版本兼容性时,默认对次版本号的限定约束 -
~
是确保版本兼容性时,默认对补丁号的约束
版本描述:
-
*
通配符,类似glob
模式*
-
x,X
约等于*
号,通常用于次版本和补丁的通配.
-
0.x
警惕这种版本,说明该依赖还未稳定(如果它遵守语义化命名的话),此外由于0.x
版本随时可能改变,此时^,~
的都表示为对补丁版的限制。
相关举例如下:
< 1.2.3 小于1.2.3 的版本均可
= 1.2.3 只支持等于1.2.3 的版本
<= 1.2.3 只支持小于等于1.2.3 的版本
> 1.2.3 只支持大于 1.2.3 的版本
>= 1.2.3 只支持大于等于 1.2.3 的版本
1.2.3-2 支持 >=1.2.3 <3.0.0 的版本
1.x.1 支持 >=1.0.1 <1.1.0 的版本
* 支持 >= 0.0.0 的版本
"" 同 *
1 表示 >=1.0.0 <2.0.0 其余任意位置为空相似
1.0 >= 1.0.0 < 1.1.0
~1.1.1 >=1.1.1 <1.2.0
~1.1 >=1.1.0 <1.2.0
~1 >=1.0.0 <2.0.0
^1.1.1 >=1.1.1 <2.0.0
^0.1.1 >=0.1.1 <0.2.0 注意这里,不要以为是 0.1.1-1.0.0 之间
^0.0.1 >=0.0.1 <0.0.2 同上,请注意
@latest 最新的稳定版本
@next 最新未发行版本
注意:大部分包管理工具均遵守上述规则,但是在进行版本限定时,请参考包管理工具的配置项说明,确定语法格式。
4. npm常用命令
npm 模块仓库提供了一个查询服务,叫做 registry,比如 npm 的查询服务网址是 https://registry.npmjs.org/,淘宝镜像的查询服务网址是 https://registry.npm.taobao.org/,yarn 的查询服务网址是 https://registry.yarnpkg.com/。
registry + package-name 就会看到 package-name 模块所有版本的信息,比如 https://registry.npmjs.org/react,https://registry.npm.taobao.org/react,https://registry.yarnpkg.com/react
4.1 发布包常用命令
注:以下指令一般需要切换成 npm 地址再执行
# 如果报404错说明该 npm 包名可用,否则该包名已被占用(也表示已发布到 npm 上)
npm [view | v | show | info] some-name
# 搜索某一个模块
npm search [package-name]
# 查看某个 package 的最新版本
npm [view | v] [package-name] version
# 查看某个 package 在 npm 服务器上所有发布过的版本
npm [view | v] [package-name] versions
# 创建项目在模块根目录初始化 package.json
npm init [-y]
# 添加 npm 用户(第一次发布包)
npm adduser
# 登录 npm 用户(非第一次发布包)
npm login
# 发布 npm 包(--access=public设置使用权参数为公有的)
npm publish [--access=public]
# 更新 npm 包版本(如果项目最新内容没有git提交则会报 Git working directory not clean 错,可以先提交再更新版本,如果一定要更新也可以使用 --force 参数强制更新版本)其实 npm version 命令更新版本后还立即执行了一次git提交。
npm version <版本号|major|minor|patch> [--force]
# 安装或更新包,@表示指定版本,^表示该大版本下的最新次要版本,~表示该次要版本下的最新小版本,--latest 是用于 upgrade 命令的
yarn add/upgrade |@1.0.0|@~1.0.0|@^1.0.0| [--lateset]
# 撤销发布的包(一般会有 I sure hope you know what you are doing. 警告,因为可能有些项目在使用这个包,如果需要强制撤销发布的包需要加上 --force 参数)
npm unpublish [--force]
4.2 查找帮助
# 查看 npm 版本
npm -v
# 显示所有可用命令
npm -l
# 查看命令的简单使用帮助
npm [command] -h
# 查看命令的详细使用指南
npm help [command]
4.3 安装、卸载、更新模块
npm install 安装过程:
- 发出
npm install
命令 - npm 向 registry 查询模块压缩包的网址
- 下载压缩包,存放在
~/.npm
目录 - 解压压缩包到当前项目的
node_modules
目录
# 根据 package.json 文件安装相关依赖
npm [install | i]
# 局部安装某个模块,并将模块依赖写入到 package.json 文件的 dependencies 或 devDependencies 中
npm [install | i] [package-name] [--save | --save-prod | -P | --save-dev | -D]
npm install gulp # 等同于安装最新版本
npm install gulp@latest # 安装最新版本
npm install [email protected] # 安装指定版本
npm install vue@">=1.0.28 < 2.0.0" # 安装指定范围版本
npm install git://github.com/package/path.git # 通过仓库地址安装
# 全局安装依赖
npm [install | i] [package-name] -g
# 更新局部模块
npm update [package-name]
# 更细全局模块到指定版本
npm update [[email protected]] -g
# 局部卸载模块
npm [uninstall | un] [package-name] [--save | --save-prod | -P | --save-dev | -D]
# 全局卸载模块
npm [uninstall | un] [package-name] -g
# 列出当前项目安装的所有模块
npm [list | ls] [--json]
# 查看全局安装包
npm [list | ls] -g --depth=0 [--json]
# 查看 npm 全局安装的根目录
npm bin
4.4 镜像相关
# 临时使用镜像
npm install package-name --registry=https://registry.npm.taobao.org/
# 长期使用镜像
npm config set registry=https://registry.npm.taobao.org/
4.5 npm 设置类
# 设置一些变量
npm [config] set registry https://registry.npmjs.org/
npm [config] set registry=https://registry.npmjs.org/
# 获取配置
npm [config] get registry
# 删除配置
npm config delete registry
# 设置一些初始化变量
npm [config] set init-license 'MIT'
npm [config] set init-author-name 'my name jerry'
# 查看命令的绝对路径 /Users/tony/Desktop/web_front/npmtest/node_modules
npm root
# 查看配置
npm config list
# 获取 npm 本地的缓存目录(npm install 或 npm update 命令,从 registry 下载压缩包之后)
npm config get cache
# 查看 npm 缓存,储存结构是{cache}/{name}/{version}
ll ~/.npm # ~/.npm/node-sass/4.14.1/...
# 添加 npm 缓存
npm cache add
npm cache add
npm cache add
npm cache add @
# 清除 npm 缓存
npm cache clean
rm -rf ~/.npm/*
# 不指明 dir_path 则在 {prefix}/lib/node_modules 中新建一个当前目录的超链接
# 指明 dir_path 则在 ./node_modules 中新建一个 dir_path 目录的超链接
# 参考地址:https://www.jianshu.com/p/aaa7db89a5b2
npm link [dir_path]
# 列出所有环境变量
env
4.6 执行脚本
4.6.1 脚本执行原理
- 每当执行
npm run
,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。 -
npm run
新建的这个 Shell,会将当前目录的node_modules/.bin
子目录加入PATH
变量,执行结束后,再将PATH
变量恢复原样。也就是说当前目录的node_modules/.bin
子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写mocha test
就可以了。 - npm 脚本可以使用Shell通配符,
*
表示任意文件名,**
表示任意一层子目录,如果要使用字符*,要将星号转义\* - 向 npm 脚本传入参数,要使用
--
标明,如npm run lint -- --reporter checkstyle
- npm 并行执行使用
&
符号,按顺序继发执行使用&&
符号,如npm run script1.js & npm run script2.js
,npm run script1.js && npm run script2.js
{
"scripts": {
"test": "mocha test",
"lint": "jshint *.js",
"lint": "jshint **/*.js",
"test": "tap test/\*.js",
"lint:checkstyle": "npm run lint -- --reporter checkstyle > checkstyle.xml"
}
}
4.6.2 一些执行脚本命令
# 执行 package.json 文件中 scripts 里的脚本
npm run [script-key]
# 注意会默认执行指令的 pre 和 post 钩子。注:双重的pre和post无效,比如prepretest和postposttest是无效的
[npm run pretest]
npm run test
[npm run posttest]
4.6.3 一些简写命令
-
npm start
是npm run start
-
npm stop
是npm run stop
的简写 -
npm test
是npm run test
的简写 -
npm restart
是npm run stop && npm run restart && npm run start
的简写
4.6.4 获取变量
- 通过 process.env.npm_package_ + 前缀(如果是 bash 脚本则还可以通过 $npm_package_ + 前缀)npm 脚本可以拿到
package.json
里面的字段。
// === package.json ===
{
"name": "foo",
"version": "1.2.5",
"scripts": {
"view": "node view.js",
"view-name": "echo $npm_package_name",
"view-version": "echo $npm_package_version",
"view-scripts-view": "echo $npm_package_scripts_view"
}
}
// === view.js ===
console.log(process.env.npm_package_name); // foo
console.log(process.env.npm_package_version); // 1.2.5
console.log(process.env.npm_package_scripts_view); // node view.js
// === 如果是 bash 脚本 ===
npm run view-name // foo
npm run view-version // 1.2.5
npm run view-scripts-view // node view.js
- 通过 $npm_config_ + 前缀 脚本可以拿到 npm 的配置变量,即
npm config get xxx
命令返回的值。
// === package.json ===
{
"name": "foo",
// 注意, package.json 里面的 config 对象,可以被环境变量覆盖。
"config": {
"port": "8080"
},
"scripts": {
"view": "echo $npm_config_registry"
}
}
// === bash ===
npm run view // https://registry.npm.taobao.org/
上面代码中,npm_package_config_port
变量返回的是8080
。这个值可以用下面的方法覆盖。
npm config set foo:port 80
4.7 npm 与 npx
npm 是一个 node package 安装工具,安装的包是永久存在的。
npx 是临时安装,用完后删除,npx 的优势是可以执行未安装的包的命令。
-
npx 类似于 npm exec / npm x
# 使用 npx 创建一个 test-app 在本地 npx react-create-app test-app # npx 支持运行远程仓库的可执行文件 npx github:piuccio/cowsay hello npx http-server # 开启一个静态服务器 npx -p node@8 npm run build # 指定 node 版本运行 # ======= # npm 的话需要先 install npm install -g create-react-app create-react-app test-app
5. package.json相关
package.json 定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)
{
// 项目名称
"name": "Hello World",
// 项目版本号
"version": "0.0.1",
// 项目作者
"author": "zhangsan",
// 项目参与人
"contributors":[{
"name": "lisi",
"email":"[email protected]",
"url": "http://barnyrubble.tumblr.com/"
}],
// 项目描述,便于用户在npm上搜索到我们的项目
"description": "第一个node.js程序",
// 项目关键字,便于用户在npm上搜索到我们的项目
"keywords":["node.js", "javascript"],
// 项目主页地址
"homepage": "https://github.com/owner/project#readme",
// 项目许可证
"license": "MIT",
// 加载的入口文件,加载优先级是 browser = browser+mjs > module > browser+cjs > main
"main": "lib/index.js",
// ESM 规范的入口文件
"module": "lib/index.mjs", // module
// typescript 的入口文件
"types": "lib/index.d.ts", // ts
// 在 browser 环境下的入口文件,browser 可定义成和 main/module 字段一一对应的映射对象,也可以直接定义为字符串
"browser": {
"./lib/index.js": "./lib/index.browser.js", // browser+cjs
"./lib/index.mjs": "./lib/index.browser.mjs" // browser+mjs
},
// "browser": "./lib/index.browser.js" // browser
// 用来指定内部命令对应的可执行文件的位置,如下 someTool.js 会建立符号链接 ./node_modules/.bin/someTool
"bin": {
"someTool": "./bin/someTool.js"
},
// 除了根目录下的文件外还有哪些目录也要发布(当前有 bin 目录和 lib 目录)
"files": {
"bin":,
"lib"
},
// 代码仓库地址
"repository": {
"type": "git",
"url": "https://github.com/tony0511/cli.git"
},
// 指明了该模块运行的平台
"engines": {
"node": ">=0.10.3 <0.12"
},
// 项目问题反馈的 url 或报告问题的 email 地址
"bugs": {
"url":"http://path/to/bug",
"email":"[email protected]"
},
// 运行脚本
"scripts": {
"start": "node index.js"
},
// 用于添加命令行的环境变量
"config": {
"port": "8080"
},
// 项目运行所需依赖
"dependencies": {
"express": "latest",
"mongoose": "~3.8.3",
"handlebars-runtime": "~1.0.12",
"express3-handlebars": "~0.5.0",
"MD5": "~1.2.0"
},
// 项目运行开发所需依赖
"devDependencies": {
"bower": "~1.2.8",
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~0.7.2",
"grunt-contrib-uglify": "~0.2.7",
"grunt-contrib-clean": "~0.5.0",
"browserify": "2.36.1",
"grunt-browserify": "~1.3.0",
},
// 是否为私有包,如果设置为 true, 则 npm 会拒绝发布它
"private": false,
// 发布的地址
"publishConfig": {
"registry": "https://registry.npmjs.org"
},
// 指定项目运行在什么操作系统上
"os": [
"darwin",
"linux",
"!win32"
],
// 指定项目运行在什么 cpu 架构上。
"cpu": [
"x64",
"ia32",
"!arm",
"!mips"
]
}
6. yarn常用命令
# === 初始化,设置 ===
# 初始化 npm 项目,生成 package.json 文件
yarn init
# 使用淘宝镜像
yarn config set registry http://registry.npm.taobao.org
yarn config set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass -g
# 查看 yarn 全局缓存目录
yarn cache dir
# 列出匹配指定模式的已缓存的包
yarn cache list [--pattern "gulp-(match|newer)"]
# 清除缓存
yarn cache clean
# 查看当前 yarn 的 bin 的位置
yarn global bin
# 查看 yarn 全局安装的根目录
yarn global dir
# 查看全局安装包
yarn list --depth=0
# 配置项
yarn config list # 显示所有配置项
yarn config get # 显示某配置项
yarn config delete # 删除某配置项
yarn config set [-g|--global] # 设置配置项
# === 安装包管理 ===
# 安装、卸载、升级局部依赖(未指明包名将升级所有依赖项)
yarn [install]
yarn [add | remove] [package-name]@[version] [--dev / -D]
yarn upgrade [package | package@tag | package@version | @scope/]... [--ignore-engines] [--pattern]
# 安装、卸载、升级全局依赖
yarn global [add | remove] [package-name]@[version]
# 查看包相关信息
yarn info package-name
# === 执行脚本 ===
yarn [run] [script] []
7. Tink
npm 已落伍,下一代包管理器 Tink 正在孵化
参考链接:https://www.infoq.cn/article/R*5JRVuOOHBRlw411PlZ
Tink 是很值得期待的项目,但现在还没做好准备与大家见面。谁要是下载了它开始用搞不好会惹出大事的,所以还是要多等一等。Tink 使用 Virtual node_modules 作为新的运行时,具备开箱即用的 TypeScript、ESM、JSX 和 Wasm 支持。它将随 npm 的第 8 版一同发布,将来会是 npm 的一个可选组件。此外,我们将来会加入一个新的包管理 API。
require查找规则
参考阮大哥地址: http://www.ruanyifeng.com/blog/2015/05/require.html