今天我们学习几个npm快速开发技巧,希望这些技巧帮助你更好的认识和使用npm这个命令。
基本的快捷键方式
我们从最基本的命令开始:
npm init
这个命令用于整个项目的初始化,当执行完这个命令后将会在本项目的目录下新增一个package.json的文件夹。这个命令执行完之后会进入输入配置阶段,如果不想进入,可以在这个命令加上 -y
npm init -y
如果想知道默认的配置模板在哪里,可以执行以下的命令
npm config get userconfig
执行这个命令后,我们可以找到我们的配置文件所在的位置
home=https://www.npmjs.org
registry=https://registry.npmjs.org/ ## 安装的源
执行下面的命令可以对.npmrc中的内容进行编辑
npm config edit
npm install , 简写:npm i
这个命令是用于安装项目的依赖包,每个项目都拥有自己的依赖包。执行这个命令后会创建一个node_module和package.json的目录或文件。
在我们上一个命令的前提下,我们继续来探寻 npm i 这个技巧
npm i
帮助检测与当前的node最匹配的npm的版本号,并匹配出相应的npm包的升级的版本号(效果同npm i -S)
npm i -S 或npm i --save
会将即将安装的包的名称及版本号放在dependecies里面
此时的package.json
{
"name": "no",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.21"
}
}
npm i -D 或npm i --save-dev
会将即将安装的包的名称及版本号放在devDependencies里面
此时的package.json
{
"name": "no",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"lodash": "^4.17.21"
}
}
npm -O 或npm --save-optional
此时的package.json
{
"name": "no",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {},
"description": "",
"optionalDependencies": {
"lodash": "^4.17.21"
}
}
注意:optionalDependencies会覆盖dependencies中的同名依赖包,因此不要在两个地方都写。
区别
package.json文件里面的devDependencies、dependencies和optionalDependencies`对象有什么区别呢?
devDependencies里面的依赖用于于开发环境,不用于生产环境dependencies是需要发布到生产环境的 待处理- optionalDependencies是可选依赖包,此种依赖不是程序运行所必须的,但是安装后可能会有新功能,例如一个图片解码库,安装了 optionalDependencies 后会支持更多的格式(webp,png,jpeg等)
dependencies 是项目正常运行所需要的依赖,devDependencies则是开发阶段整个项目所需的依赖(如会有一些测试依赖之类的),optionalDependencies是为了更好的扩充原有项目的功能所需要的依赖。
npm i xx@
这个命令可以精确化安装某个版本
npm 版本修饰前缀与依赖含义
在依赖声明列表中,我们看到各包的后面还会带着版本号,版本号前则有不同的前缀修饰。npm 正是通过这种前缀修饰决定版本下载方式。 当安装一个包并添加了 –save 等参数要求保存到 package.json 中时,默认使用的是 ^。通过修改 save-prefix 配置,可以修改这个默认的设置。如:
npm config set save-prefix="~" 常见的版本号表达式示例:
| 表达式 | 版本范围 |
|---|---|
| >=1.2.7 | 大于等于1.2.7 |
| >=1.2.7 <1.3.0 | 1.2.7,1.2.8,1.2.9 |
| 1.2.3 – 2.3.4 | >=1.2.3 <=2.3.4 |
| 1.2 – 2.3.4 | >=1.2.0 <=2.3.4 |
| 1.2.3 – 2.3 | >=1.2.3 <2.4.0 |
| 1.2.3 – 2 | >=1.2.3 <3.0.0 |
| * | >=0.0.0 |
| 1.x(等价于1.X) | >=1.0.0 <2.0.0 |
| 1.2.x | >=1.2.0 <1.3.0 |
| “”(等价于*) | >=0.0.0 |
| 1(等价于1.x.x) | >=1.0.0 <2.0.0 |
| 1.2(等价于1.2.x) | >=1.2.0 <1.3.0 |
| ~1.2.3(>=1.2.3 <1.(2+1).0) | >=1.2.3 <1.3.0 |
| ~1.2(>=1.2.0 <1.(2+1).0) | >=1.2.0 <1.3.0 |
| ~1(>=1.0.0 <(1+1).0.0) | >=1.0.0 <2.0.0 |
| ~0.2.3(>=0.2.3 <0.(2+1).0) | >=0.2.3 <0.3.0 |
| ~0.2(>=0.2.0 <0.(2+1).0) | >=0.2.0 <0.3.0 |
| ~0(>=0.0.0 <(0+1).0.0) | >=0.0.0 <1.0.0 |
| ~1.2.3-beta.2 | >=1.2.3-beta.2 <1.3.0 |
| ^1.2.3 | >=1.2.3 <2.0.0 |
| ^0.2.3 | >=0.2.3 <0.3.0 |
| ^0.0.3 | >=0.0.3 <0.0.4 |
| ^1.2.3-beta.2 | >=1.2.3-beta.2 <2.0.0 |
| ^0.0.3-beta | >=0.0.3-beta <0.0.4 |
| ^1.2.x | >=1.2.0 <2.0.0 |
| ^0.0.x | >=0.0.0 <0.1.0 |
| ^0.0 | >=0.0.0 <0.1.0 |
| ^1.x | >=1.0.0 <2.0.0 |
| ^0.x | >=0.0.0 <1.0.0 |
让脚本跨平台兼容
任何在命令行上运行的代码都有兼容性问题的风险,特别是在Windows和基于unix的系统(包括Mac和Linux)之间。如果你只处理特定的项目,但是在许多情况下,跨平台兼容性很有必要的:任何开放源码或协作项目,以及示例和教程项目,都应该能够工作,而不管操作系统是什么。
有几个选项可供选择,但效果最好的是cross-env,执行
npm i -D cross-env
将其作为开发依赖项安装。然后在任何环境变量之前包括关键字cross-env,就像这样:
{
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config build/wepack.config.js"
}
}
cross-env是 实现跨平台兼容性的最无缝的方法,但还有其他两个流行的工具,它们可以帮助实现跨平台兼容性:
在不同的目录中运行脚本
有时,在同一个文件夹里可能存在多个不同的项目,但此时我们想在一个项目里访问另外项目的脚本命令,我们该如何操作?有两种方法可以执行此操作:
第一种方式
第一种是手动 cd 并运行对应的命令:
cd common && npm start && cd ..
第二种方式
但还有一个更优雅的解决方案,即使用--prefix标志指定路径:
npm run [command] --prefix 相对路径
备注:除了npm start 之外的命令都需要在对应的命令前加run(npm run [command])
举个栗子:
目前有两个目录下都有对应个package.json文件夹
我们需要在 no这个目录下执行另一个package.json中的脚本
--prefix后的路径是 相对路径
列举已安装的package
为什么我们需要花费我们的时间打开 package.json 文件去检查我们安装了哪些
package 依赖? 只需要简单的运行 npm ls --depth=0 就可以得到我们需要了解的信息
数字0待研究
npm ls --depth=0 或 npm ls --depth 0
通过执行这个命令,我们可以查看到我们在common项目目录下安装的依赖。除此之外,如果想要知道全局安装了哪一些依赖,可以执行
npm ls --depth 0 -g
注意:–depth 表示深度,我们使用的模块会有依赖,深度为 0 的时候,不会显示依赖模块
列出并选择可用脚本
列出packgage.json文件中可用的脚本很简单:
在项目的根目录并在终端中执行以下命令:
npm run
控制应用程序版本
与手动更改应用程序的版本相比,npm 提供了一些有用的快捷方式来完成这一点。
版本号解释
major: 主版本号
premajor: 预备主版本
minor: 次版本号
preminor: 预备次版本
patch: 修订号
prepatch: 预备修订版
prerelease: 预发布版本
案例
假设初始版本为0.1.0
➜ xxx git:(master) npm version preminor
v0.1.0-0
➜ xxx git:(master) npm version minor
v0.1.0
➜ xxx git:(master) npm version prepatch
v0.1.1-0
➜ xxx git:(master) npm version patch
v0.1.1
➜ xxx git:(master) npm version prerelease
v0.1.2-0
➜ xxx git:(master) npm version premajor
v1.0.0-0
➜ xxx git:(master) npm version major
v1.0.0
自定义npm init脚本
在项目开发过程中,我们可以自定义我们自己的npm init 脚本来初始化我们的项目。
首先在我们的项目目录中创建一个.npm-init.js文件
为了确保npm init被指向正确的文件,可以运行:
npm config set init-module ./.npm-init.js
在集成git之前,这里有一个简单的.npm-init.js文件,它模拟了默认npm init的问题。
module.exports = {
name: prompt('package name', basename || package.name),
version: prompt('version', '0.0.0'),
decription: prompt('description', '?'),
main: prompt('entry point', 'index.js'),
repository: prompt('git repository', 'https://github.com/xjingmo'),
keywords: prompt(function (s) { return s.split(/\s+/) }),
author: prompt('author', 'Gmo'),
license: prompt('license', 'ISC')
}
现在执行
npm init
此时每个命令都会依据我们提供的.npm-init.js文件中代码执行
每个问题都遵循nameInPackage模式:prompt('nameInPrompt','defaultValue'),要在缺省情况下设置值而不带问题,只需删除prompt方法。如果要返回默认设置,只需删除.npm-init.js。
使用自定义npm init脚本将你的第一个 Commit 提交到 GitHub
为了将git命令合并到.npm-init.js文件中,需要一种方法来控制命令行,我们可以使用child_process 模块
在文件的顶部引入它,因为我们只需要execSync函数,所以可以使用析构赋值语法自己获取它:
const { execSync } = require('child_process');
创建了一个helper函数,它将函数的结果打印到控制台:
function run(func) {
console.log(execSync(func).toString())
}
最后,将提示输入GitHub存储库URL,如果提供,我们将生README.md文件,并启动我们的第一次提交。
repository: prompt('github repository url', '', function (url) {
if (url) {
run('touch README.md');
run('git init');
run('git add README.md');
run('git commit -m "first commit"');
run(`git remote add origin ${url}`);
run('git push -u origin master');
}
return url;
})
.npm-init.js文件大概如下:
const { execSync } = require('child_process');
function run(func) {
console.log(execSync(func).toString())
}
module.exports = {
name: prompt('package name', basename || package.name),
version: prompt('version', '0.0.0'),
decription: prompt('description', '?'),
main: prompt('entry point', 'index.js'),
repository: prompt('github repository url', '', function (url) {
if (url) {
run('touch README.md');
run('git init');
run('git add README.md');
run('git commit -m "first commit"');
run(`git remote add origin ${url}`);
run('git push -u origin master');
}
return url;
}),
keywords: prompt(function (s) { return s.split(/\s+/) }),
author: prompt('author', 'Gmo'),
license: prompt('license', 'ISC')
}
命令执行:
package.json文件:
{
"name": "no",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/xjingmo/JavaScript.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/xjingmo/JavaScript/issues"
},
"homepage": "https://github.com/xjingmo/JavaScript#readme"
}
更多npm命令,请查看npm命令