10 min read

开发环境-NPM

在现代软件开发中,NPM(Node Package Manager)成为了一项不可或缺的工具,它提供了丰富的开发资源和依赖管理能力。本文将介绍如何搭建NPM开发环境,并探讨其在项目开发中的重要性。通过合理配置和利用NPM,开发者能够更高效地管理项目依赖、共享代码、提升开发速度,为软件开发带来了巨大的便利和效益。
开发环境-NPM

前言

在现代软件开发中,NPM(Node Package Manager)成为了一项不可或缺的工具,它提供了丰富的开发资源和依赖管理能力。本文将介绍如何搭建NPM开发环境,并探讨其在项目开发中的重要性。通过合理配置和利用NPM,开发者能够更高效地管理项目依赖、共享代码、提升开发速度,为软件开发带来了巨大的便利和效益。

安装

安装 nvm, 方便在同一台机器上管理多个不同版本的Node.js.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

NVM镜像加速

Windows目录中 \AppData\Roaming\nvm, 打开settings.txt, 文本最后行中加入


node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

或者在控制台修改镜像

nvm node_mirror http://npm.taobao.org/mirrors/node/
nvm npm_mirror https://npm.taobao.org/mirrors/npm/

安装Node

nvm list available #Windows中列出
nvm ls-remote #Linux中列出
nvm install [version]

指定项目Node版本

项目存在.nvmrc 的文件时,会自动检测并读取该文件中指定的Node版本,并自动切换到该版本.
创建一个.nvmrc文件, 内容写入任意版本号, 如:

v10.16.2
找不到的修复

如果在Linux上通过npm -g全局安装pm2、yarn、pnpm等命令后无法找到它们,可以尝试通过export PATH来解决。以下是解决方法:

确定安装路径
默认情况下,它们会被安装在/usr/local/bin或/usr/bin目录下。使用以下命令来查看并记下安装路径:

npm bin -g

导出路径
使用export命令将全局包的安装路径添加到系统的环境变量中。
例如,如果全局包的安装路径是/usr/local/bin,使用以下命令将其添加到PATH环境变量中

export PATH="/usr/local/bin:$PATH"

检查命令
现在,尝试在终端中运行这些命令,如pm2、yarn或pnpm, 确保能够正常运行。


NPM源管理

源管理

nrm / yrm 是快速切换npm/yarn注册服务商,如npm、cnpm、nj、taobao等,也可以切换到内部的npm源. pnpm 可比yarn,npm 更节省了大量与项目和依赖成比例的硬盘空间。

YRM

# 安装
npm install -g yrm

# yrm ls
npm ----- https://registry.npmjs.org/
cnpm ---- http://r.cnpmjs.org/
taobao -- https://registry.npm.taobao.org/
nj ------ https://registry.nodejitsu.com/
rednpm -- http://registry.mirror.cqupt.edu.cn
skimdb -- https://skimdb.npmjs.com/registry
yarn ---- https://registry.yarnpkg.com

最后,切换与测试

$ yrm use taobao
$ yrm test taobao

NPM应用

.npmrc

.npmrc (npm running cnfiguration),即npm运行时配置文件,  能配置 Registry, 代理设置, 认证信息, 依赖解析和版本控制, 缓存路径等. 它的读取顺序是: 

项目配置文件 -> 用户配置文件 -> 全局配置文件
.npmrc (项目根目录) -> ~/.npmrc (用户目录) -> /etc/npmrc

目录位置查询

npm config get prefix #用户目录
npm config get prefix #全局目录

.npmrc 设置

.npmrc 文件是以 key=value 格式进行配置, 而 .yarnrc是没有 =, 例:

registry=https://registry.npm.taobao.org

也可以用命令方式:

npm config set registry https://registry.npm.taobao.org

scope

scope相当于npm包的命名空间,如果以@开头,那它就是一个scope package。 这样分类之后就会使结构更加清晰,

@aa:registry=https://repo.huaweicloud.com/repository/npm/

NPM镜像加速

方案一

在项目目录下配置.yarnrc(或者.npmrc文件), 通常能解决项目依赖安装失败, 下面的代码选择你需要的配置哦

registry "https://registry.npm.taobao.org"
sharp_binary_host "https://npm.taobao.org/mirrors/sharp" 
sharp_libvips_binary_host "https://npm.taobao.org/mirrors/sharp-libvips"
disturl "https://npm.taobao.org/dist" 
sass_binary_site "https://npm.taobao.org/mirrors/node-sass/" 
phantomjs_cdnurl "http://cnpmjs.org/downloads" 
electron_mirror "https://npm.taobao.org/mirrors/electron/" 
sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/" 
profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/" 
chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver" 
nvm_nodejs_org_mirror "http://npm.taobao.org/mirrors/node" 
NODEJS_ORG_MIRROR "http://npm.taobao.org/mirrors/node" 
SQLITE3_BINARY_SITE "http://npm.taobao.org/mirrors/sqlite3" 
node_inspector_cdnurl "https://npm.taobao.org/mirrors/node-inspector" 
selenium_cdnurl "http://npm.taobao.org/mirrors/selenium" 
puppeteer_download_host "https://npm.taobao.org/mirrors" 
operadriver_cdnurl "https://npm.taobao.org/mirrors/operadriver" 
fse_binary_host_mirror "https://npm.taobao.org/mirrors/fsevents"

如果上传到github上,可用命令快速下载:

$ wget https://gist.githubusercontent.com/Rick2077/a115d9bbce45d7183a5a06fe16aa1cea/raw/48b51adbcd449384c200ff79bb652f41a85acb9a/.yarnrc 

方案二

使用命令配置sharp的镜像地址

# npm 
npm config set sharp_binary_host "https://npm.taobao.org/mirrors/sharp"
npm config set sharp_libvips_binary_host "https://npm.taobao.org/mirrors/sharp-libvips"
npm install sharp

# yarn 
yarn config set sharp_binary_host "https://npm.taobao.org/mirrors/sharp"
yarn config set sharp_libvips_binary_host "https://npm.taobao.org/mirrors/sharp-libvips"
yarn add sharp

有时在Linux上遇到sharp的奇怪问题, 可以通过`yarn add --platform=linux --arch=x64 sharp` 解决.

NPM常用命令

npm config set <key> <value> [-g|--global]  #给配置参数key设置值为value;
npm config get <key>          #获取配置参数key的值;
npm config delete <key>       #删除置参数key及其值;
npm config list [-l]      #显示npm的所有配置参数的信息;
npm config edit     #编辑配置文件
npm get <key>     #获取配置参数key的值;
npm set <key> <value> [-g|--global]    #给配置参数key设置值为value;

运行多脚本

项目开发中通常有执行单个或多个脚本情景,会是以下:

串行

用 && 把多条脚本按先后串起来. 执行时,如前其中一命令失败,后续全部命令将终止.

$ npm run build && npm run start

并行

为提高效率,用& 把多条脚本按先后串起来.

$ npm run build & npm run start

更好的两种方式

npm-run-all

使用方式只需要加上一参数, --parelle 或 -p. 更多用法,查看文档 npm-run-all.

它提供了三个命令: npm-run-all / run-s / run-p, 后两者是all带参数简写. 

# 安装
$ npm i npm-run-all -D
# package.json script中添加
"scripts": {
  "frotend": "echo \"Frontend service started\"",
  "server": "echo \"Backend service started\"",
  "all": "npm-run-all frotend server",
}

其中串行的方式还可以使用通配符,如:

"scripts": {
  "test": "npm-run-all test:*",
  "test:unit": "mocha",
  "test:integration": "jasmine",
  "test:system": "codecept"
}

运行 npm run test 将按该顺序执行 test:unit 、 test:integration 和 test:system.

concurrently

功能类似,详情查看文档 concurrently

# 安装
$ npm i concurrently -D
# package.json script中添加
"scripts": {
  "frotend": "echo \"Frontend service started\"",
  "server": "echo \"Backend service started\"",
  "all": "concurrently \"npm run frotend\" \"npm run server\""
}

如果运行的script在子目录,可以这样:

"scripts": {
  "client": "cd client && npm start",
  "server": "cd server && npm start",
  "assets": "cd assets && ionic serve",
  "start": "concurrently \"npm run client\" \"npm run server\" \"npm run assets\" ",
},
...
"devDependencies": {
  "concurrently": "^1.0.0"
}

npm script 传参

为简化配置,可通过传参减少配置条目,提高灵活度。 如代码检测:

"lint": "eslint js/*.js",
"lint:fix": "eslint js/*.js --fix"

通过传参后,只需保留一条命令, 然后执行npm run lint -- fix

"lint": "eslint js/*.js",

script 日志控制

如果不加日志参数得到的输出 ,能显示执行的命令与结果.

更少的

如需显示更少,只需在运行时传 --loglevel silent 或者 --silent 或更简单的 -s.

$ npm run all -s

更多的

只需在运行script的时传--loglevel verbose或者 --verbose或者更简单的 -d 

$ npm run all -d

script 钩子

钩子的设计目的是增加生命周期的机制,通常是 pre 与 post钩子脚本. 这特性可帮助某些操作前后的检查或清理. 例:

"lint": "eslint js/*.js",
"prelint": "eslint js/*.js --fix",
"postlint": "echo \"eslint执行完毕\""

只执行 npm run lint, 它将执行三条命令: npm run prelint, npm run lint, npm run postlint.

script 变量

npm script 中可使用预定义变量与自定义变量.

预定义变量

通过解析整个package.json 获取各字段与值. 运行 npm run env 能拿到完整的列表, 但太长. 
可使用 npm run env | grep npm_package | sort 拿到部分排序后的预定义变量.

npm_package_json=/home/jojo/devs/react-app/package.json
npm_package_name=react-app
npm_package_version=0.1.0

使用方法遵循 shell 语法,在 npm script 给要引用的变量前面加上 $ 符号即可.

  "scripts": {
    "getName": "echo $npm_package_name"
  },

运行getName, 结果如下:

jojo@JoJo_PC:~/devs/react-app$ npm run getName -s
react-app

自定义变量

在config字段时可添加自定义变量.

  "config": {
    "say": "hello jojo"
  },

运行结果如下:

jojo@JoJo_PC:~/devs/react-app$ npm run sayName

> react-app@0.1.0 sayName
> echo $npm_package_config_say

hello jojo

linux / mac下使用 $npm_package_name, windows下用 %npm_package_name%

跨平台

由于Linux / Mac / Windows 引用变量方式不同, 这时就需要处理兼容问题.
暴力的方式为各写一份:

{
  "name": "test",
  "scripts": {
    "bash-script": "echo Hello $npm_package_name",
    "win-script": "echo Hello %npm_package_name%"
  }
}

以下有更好的方式:

Cross-var

#安装

$ npm i cross-var -D

#命令添加

"var3": "cross-var echo %npm_package_config_say%",
"var4": "cross-var echo $npm_package_config_say"

Cross-env

$ npm i cross-env -D

设置环境变量的时候,加上cross-env 即可.

"envDev": "cross-env NODE_ENV=development"

命令列表

对于快速了解项目, 有简单快捷方式罗列 scripts 对象中的所有命令, 即 npm run:

jojo@JoJo_PC:~/devs/react-app$ npm run
Lifecycle scripts included in react-app@0.1.0:
  start
    react-scripts start
  test
    react-scripts test

available via `npm run-script`:
  build
    react-scripts build
  eject
    react-scripts eject
  getName
    echo $npm_package_name
  sayName
    echo $npm_package_config_say

 npm run xxx机制

 执行 npm run xxx 命令时,会在项目的 package.json 文件中的 scripts 部分查找对应的 xxx 命令并执行。例如,运行 npm run serve 实际上是执行 vue-cli-service serve 命令。

使用 npm run xxx 而不是直接执行命令的原因是,直接执行 vue-cli-service serve 会报错,因为操作系统中没有对应的指令。

npm run xxx 的执行方式是先在项目的 node_modules/.bin 目录中查找命令,如果找到则执行,否则在全局的 node_modules/.bin 目录中查找。如果仍未找到,会检查系统的 PATH 环境变量中是否有其他同名的可执行程序。当安装依赖时,npm 会在 node_modules/.bin/ 目录中创建对应的可执行文件。

因此,执行 npm run serve 实际上是在 ./node_modules/.bin 目录中找到 vue-cli-service 文件并执行,相当于执行了 ./node_modules/.bin/vue-cli-service serve。

全局安装依赖时(使用 npm i -g xxx),会在全局的 node_modules/.bin 目录中创建可执行程序,从而可以在任何目录下运行相应的命令。

其他

Exit

exit 用来执行后退出的指令,相当于process.exit(1)

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },

Wait

并行执行多条命令, 在命名最后跟上 wait 可阻塞当前进程, 直到所有并行命令执行完毕才会结束进程

"scripts": {
  "print": "node ./src/script_3.js & node ./src/script_2.js & node ./src/script_1.js & wait"
}

规范校验

使用以下工具可实现git提交前的 eslint 校验, 与及commit 信息的规范校验:

husky

现代化的本地Git钩子使操作更加轻松

pre-commit

自动在您的git储存库中安装git pre-commit脚本,该脚本在pre-commit上运行您的npm test