对于前端开发的同学来说,npm
是必定会接触到的。当我们创建一个前端项目(npm init
)、运行项目(npm start
)、安装模块(npm install
)都会用到。虽然,目前yarn
、pnpm
等工具兴起,但npm
仍有一席之地。
在平常开发中,我也是会经常用到,但是我从未真正去仔细了解过这些命令是怎么执行的,为什么这些命令可以达到这样的效果。本文便针对这些,一一进行探索。
一、npm 命令如何执行
1.1 什么是命令行(Command-line)
命令行本质上是一个软件程序 ,为用户和操作系统或应用程序之间提供通信的桥梁。有时候也称之为终端、虚拟控制台等。
换句话说,命令行其实和我们常见的图形界面目的相同,都是让用户控制计算机。但是,真正能够控制计算机硬件(CPU、内存等)的只有操作系统内核(Kernel),命令行和图形界面只是架设在用户和内核之间的一座桥梁。(为什么用户不能直接控制操作系统内核,这里就暂不介绍)
所以为了让用户能间接操作内核,每种操作系统都提供了命令行程序。例如Window系统中的 Command-line Shell
和 PowerShell
,Linux系统中的Shell
。命令行是在内核基础上编写的一个应用程序,和微信、VsCode等其他软件差不多。但它的独特之处在于其开机立马启动,连接了用户和操作系统内核。
- 命令行如何连接用户和内核
命令行能够接收用户输入的命令,并对命令进行处理,处理完在将结果反馈给用户。运行某个命令时,命令行通常都是去调用内核暴露的接口进行处理,只不过细节被隐藏了起来。这就是命令行连接用户和内核的方式。
例如Linux系统中,在终端输入cat log.txt
命令查看 log.txt 文件中的内容。其实就是去调用内核提供的 open()
和 read()
函数。然后把函数返回的结果反馈给用户。
- 命令行也支持编程
命令行不仅能简单执行用户输入的命令,也能作为解释器,去执行和翻译代码。Linux系统中称为shell编程,Windows系统称为dos编程,它们是一种脚本语言。
- 命令行能连接其他程序
在命令行中输入的命令可以是系统提供的内置命令(不同系统有区别),也可以其他的应用程序(一个程序就是一个命令),即外部命令。
所以,当我们在命令行执行npm
、node
等这些外部命令时,其实上是在调用npm、node这些应用程序。
但是,当我们在命令行输入这些外部命令时,命令行如何知道我们调用的是系统中的哪个应用程序呢?
1.2 命令行如何解析命令
接上述问题,命令行如何知道执行的是哪个应用程序的呢?本文就以 Windows 系统为例,简单介绍一下命令行是如何调用其他应用程序的。
先简单介绍一下Windows命令行解析命令的方式,当我们在命令行输入一条命令时:
- 首先,Window命令行会首先按检查该命令是否为内部命令,如果是,则直接执行该命令
- 如果不是内部命令,Window命令行会检查该命令是否为外部命令。如果是,则执行该外部指令。
- 如果不是外部命令,Windows命令行会在Path环境变量中列出的目录查找该命令。如果找到该命令,它将执行该命令。
- 如果以上都不是,Windows命令行则会显示错误信息:'xxx' 不是内部或外部命令,也不是可运行的程序或批处理文件。
第1步其实就是执行系统提供的那些内置命令,例如mkdir
、start
等。
第2步中外部命令其实就是某些特定类型的文件,例如:可执行文件[.exe],批处理文件[/bat],命令脚本[.cmd] 等 。
只需要在命令行输入这些文件的文件名(可以不带扩展名)即可执行这些文件。但需要注意的是,一定要保证文件路径正确(可以是相对于当前命令行路径的相对路径,也可以是绝对路径),不然也会报错。
此外,如果是其他一般类型的文件(如:文本文件[.txt]),在命令行输入的时候必须带上扩展名,然后命令行会用指定软件打开该文件。
其实,在Windows命令行输入某个文件名和双击该文件的效果是差不多的。
举个例子,有个如下的commands
文件夹,打开命令行然后切换到该目录,输入如下命令:
a
:打开 a 应用程序b
:执行 b 批处理文件c.txt
:使用 notePad 打开 a.txt 文本文件
上述例子中,我们切换到了文件所在的目录下。那如果我们在其他目录下想执行这些文件,那就需要输入完整的相对路径或绝对路径。这对我们来说,非常难以记忆。
对此,我们可以将这些存在外部命令的目录添加到Path环境变量
中。正如第3步所述,命令行会去在PATH环境变量中列出的目录查找该命令,如果找到则执行。
其实,这就解释了为什么我们在命令行的任意目录下输入npm
, node
都可以执行的原因了。是因为我们在下载node
的时候,已经将node.cmd
文件所在的目录添加到了Windows的Path环境变量
中。
Path 环境变量:path环境变量的变量值是很多个文件夹路径,它的意思是告诉系统,当你想运行一个应用程序时,你可以在这些文件夹里查找。这样就能让系统快速启动这个应用程序
以我自己的电脑配置的Path环境变量
为例,当我运行npm
命令时,系统会运行C:\Software\Environment\nodejs
下的npm.cmd
文件。
1.3 npm 命令如何执行
由上述4可知,当在Windows命令行输入npm
命令时,系统实际上运行的是指定目录(我的电脑是C:\Software\Environment\nodejs
)下的npm.cmd
文件
那我们打开npm.cmd
文件,其内容如下:
从代码中我们可以看出,运行npm.cmd
脚本文件,最终其实运行的是"%NODE_EXE%" "%NPM_CLI_JS%" %*
(其中%~dp0
可以简单理解为当前文件所在目录),即最终执行的命令一般如下::
python
node node_modules\npm\bin\npm-cli.js
绕了大半天,我也终于明白了为什么很多推文上都说:在Windows系统上,命令行输入npm
命令将执行node_modules\npm\bin\npm-cli.js
文件了。
但其实我们再打开node_modules\npm\bin\npm-cli.js
看看,发现其实和node_modules\npm\lib
下的cli.js
、npm.js
等文件有关。这里就不进一步叙述了。
但至于为什么npm run
、npm start
这些命令可以执行呢?实际上,npm-cli.js
中的程序会获取命令行输入的参数,然后进行使用。可以简单理解为,npm
之后输入的那些内容其实就是在传递参数。所以无论npm
之后输入多少参数,本质上执行的还是npm-cli.js
这个文件。
二、npm 常见命令的执行流程
既然了解了 npm
是各种命令是如何执行的,那下面就继续深入了解一些常见的命令作用以及执行流程吧。
2.1 npm init
当我们想初始化一个 npm 包时,npm init
能够帮我们快速初始化。其本质上就是快速创建一个 package.json
文件。命令如下:
swift
npm init <initializer>
- 当未传递
initializer
参数时,该命令会首先给用户提示,询问name
,version
等信息(如果想跳过这些提示,可以使用-y / --yes
参数),然后创建在当前目录下创建一个package.json
文件。 - 如果传递了
initializer
参数时,initializer
则是一个名为create-<initializer>
的npm包,并由npm exec
命令安装,并执行该npm
包bin
目录下的脚本。例如:npm init foo
会被转化成npm exec create-foo
所以当我们想使用create-react-app
创建一个React项目my-react-app
可直接运行npm init react-app my-react-app
命令创建。
此外,npm init
还支持使用workspace
配置项在项目中创建新的工作区,命令如下:
bash
npm init -w <dir>
例如运行npm init -w package/a
,则会在当前项目中生成如下目录和文件:
lua
.
+-- package.json
`-- packages
`-- a
`-- package.json
需要注意的是,该配置项是在项目中 创建新的工作区,所以该目录下必须存在package.json
文件,不然会报错。
有关 npm init
的具体介绍,大家可以查看官方文档了解。
2.2 npm install *
npm install
,简单来说,就是安装一个 npm 包。
该命令会安装一个包以及它所依赖的任何包。如果一个包有 package-lock.json
文件,或者 npm-shrinkwrap.json
文件,或者yarn.lock
文件,依赖安装则会遵循以下顺序:
npm-shrinkwrap.json
package=lock.json
yarn.lock
该命令通常使用方式如下:
npm install
不加任何参数运行npm install
命令会将package.json
文件中的依赖项安装到本地 node_modules
文件夹。 如果是全局模式(即:-g 或 --global),则安装到全局目录下。
默认情况下,npm install
将安装 package.json
中列为依赖项的所有模块。
使用 --production
标志(或者当 NODE_ENV
环境变量设置为 production
时),npm 将不会安装 devDependencies
中列出的模块。当 NODE_ENV
环境变量设置为 production
时,要安装 dependencies
和 devDependencies
中列出的所有模块,您可以使用 --production=false
。
npm install <folder>
:
如果 <folder>
位于项目的根目录中,它的依赖项将被安装,并且可能会像其他类型的依赖项一样被提升到顶级 node_modules
。
如果 <folder>
位于项目的根目录之外,npm 将不会在 <folder>
目录中安装包依赖项,但它会创建指向 <folder>
的符号链接。
注意:如果您想从注册表安装目录的内容(如包)而不是创建链接,则需要使用
--install-links
选项。
npm install <tarball file>
:
安装位于文件系统上的包。压缩包要求:
- 文件名必须使用
.tar
、.tar.gz
或.tgz
作为扩展名。 - 包内容应位于 tarball 内的子文件夹中(通常称为
package/
)。 - 包必须包含具有
name
和version
属性的package.json
文件。
通常 tarball
可以通过npm pack
命令从包中创建。
bash
npm install ./package.tgz
npm install <tarball url>
:
获取 tarball url,然后安装它。参数必须以 "http://" 或 "https://" 开头
ruby
npm install https://github.com/indexzero/forever/tarball/v0.5.6
npm install [<@scope>/]<name>@<tag>
:
安装 <name>@<tag>
包,这也是平常开发中用的最多的方式,其中
<@scope/>
:可选参数,表示包的范围。每个 npm 用户/组织都有自己的范围,只有你可以在你的范围内添加包,这样就能防止包重名。<name>
:包的名称<tag>
:包的版本,若不指定,默认为latest
。
默认情况下,npm install
将任何指定的包保存到 package.json
文件中的 dependencies
项。但是也可以通过一些参数进行控制:
-P, --save-prod
:保存到dependencies
中。默认值-D, --save-dev
:保存到devDependencies
中。-O, --save-optional
:保存到optionalDependencies
中。--no-save
:防止保存到dependencies
。即:只安装,不保存到package.json
文件中。
当使用上述任何选项将依赖项保存到 package.json 时,还有两个额外的可选标志:
-E, --save-exact
:保存的依赖项将使用精确的版本进行配置,而不是使用 npm 的默认 semver 范围运算符。-B, --save-bundle
:保存的依赖项也将添加到您的bundleDependencies
列表中。
- 全局安装(-g / --gloabl)
默认情况下,npm install
会将所有包安装到当前目录下的node_modules
文件夹中。但如果是在 "global" 模式下运行,会将包安装到 prefix
文件夹中。(prefix
指的是全局安装目录, 可以通过npm config set prefix
命令设置)即:
- 包安装到
{prefix}/lib/node_modules
文件夹。 - bin 文件链接到
{prefix}/bin
- 手册页链接到
{prefix}/share/man
当然npm install
还有其它很多配置项和使用方式,大家可以到官方文档了解。接着主要介绍一下 npm install
安装一个模块的流程。
npm install
安装模块机制
- 首先查询
node_modules
目录下是否存已经存在指定模块,若存在,则不再重新安装 - 若不存在,则从
.npmrc
文件(npm配置文件)配置的registry
中查询模块压缩包的网址 - 如果查询到,则下载压缩包,存放在缓存目录 (可通过
npm config get cache
命令查看) - 解压压缩包到当前项目的
node_modules
目录下。
2.3 npm link
前面 2.2 中 介绍的 npm install
可以帮助我们快速安装一个远程或本地的包。但是如果我们正在开发一个包,并且想在其它项目中测试它。使用 npm install
便有点繁琐,因为我们每次测试都需要先打包再安装,如果有迭代更新,就需要重新打包安装。对此,npm link
能够很好地帮助我们解决这个问题。
npm link
用于创建包的符号链接
它通常是一个两步过程:
- 首先,在一个包中执行
npm link
,将在全局文件夹 中创建一个符号链接,该符号链接链接到执行npm link
命令的{prefix}/lib/node_modules/<package>
包。npm link
它还会将包中的任何 bin 链接到{prefix}/bin/{name}
. 请注意,npm link
使用全局前缀。 - 在其他需要使用该包的项目中执行
npm link package-name
,将创建从全局安装的package-name
到当前文件夹的node_modules/
的符号链接。
例如,现在有如下两个项目 project-a
, project-b
,依次执行如下命令:
bash
cd ~/projects/project-a
npm link
cd ~/projects/project-b
npm link project-a
执行完毕后,cd ~/projects/project-a
中的所有改变都会反映在~/projects/project-b/node_modules/project-a
中。
当然,也可以将上述操作简化成一步:
bash
cd ~/projects/project-b
npm link ../project-a
但是还是会先创建一个project-a
全局链接,然后将全局安装目标链接到project-b
的node_modules
文件夹中。
注意:
package-name
指的是package.json
中的name
,而不是 目录名称。例如上述例子中的project-a
,project-b
都是包名,不是目录名称。- 默认情况下, 以这种方式链接的包不会 保存
package.json
的依赖项中。如果想保存在package.json
文件中package-lock.json
,可以执行npm link <dep> --save
。
此外,我们也可以通过--workspace
参数指定创建链接的工作空间,例如:
npm link <pkg> --workspace <name>
:链接相关包作为指定工作空间的依赖项。npm link --workspace <name>
:创建指向指定工作空间的全局链接。
2.4 npm start
开发过程中,通常会使用 npm start
命令启动一个项目。实际上这将运行package.json
文件中scripts
对象的start
属性中指定的预定义命令。
如果"scripts"对象没有定义"start"属性,npm 将运行node server.js。
2.5 npm run *
npm run
用于运行 package.json
文件script
对象中定义的任意命令。如果没有提供 "command"
,它将列出可用的脚本。
其中 start
、test
、restart
、stop
命令可以直接运行,例如:2.3 小节中的 npm start
命令。
任何位置参数都会传递给指定的脚本。使用 --
传递以 -
为前缀的标志和选项,否则它们会被 npm 解析。具体语法如下所示:
xml
npm run-script <command> [-- <args>]
此外,env
脚本是一个特殊的内置命令,可用于列出脚本在运行时可用的环境变量 。如果你的包中定义了 env
命令,它将优先于内置命令。
除了 shell 预先存在的 PATH 之外,npm run 还将 node_modules/.bin
添加到提供给脚本的 PATH
中。本地安装的依赖项提供的任何二进制文件都可以在没有 node_modules/.bin
前缀的情况下使用。
工作区(workspaces)支持
可以使用工作区或工作区配置,以便在指定工作区的上下文中从包的"脚本"对象运行任意命令。如果未提供"命令",它将列出每个已配置工作区的可用脚本。
例如这样一个已配置工作区的项目:
lua
.
+-- package.json
`-- packages
+-- a
| `-- package.json
+-- b
| `-- package.json
`-- c
`-- package.json
根目录的package.json
文件中有如下配置:
json
{
"workspaces": [ "./packages/*" ]
}
每个配置的工作区的package.json
文件的scripts
中都有test
命令,那我们就可以使用npm test --workspces
执行配置的工作区中的所有test
命令。
当然我们也可以指定工作区:
- 指定单个工作区:
npm test --workspace=a
- 指定多个工作区:
npm test -w a -w b
关于 npm run
更多细节,可查看官方文档,本文主要来探讨一下npm run-script
是如何执行的。
npm run-script 是如何执行的
这里以本人一个项目中的npm run dev
为例,对应package.json
中的脚本为:
json
{
scripts{
"dev": "webpack-dev-server -c webpack.dev.js",
}
}
首先我们会想为什么我们不直接在命令行执行webpack-dev-server -c webpack.dev.js
这条命令呢?我们尝试一下,会发现命令行会报错如下:
那为什么 npm run dev
就可以执行呢?我们一步一步来探讨。
如第一节中所述,执行npm
实际上是执行node目录下的node_modules\npm\bin\npm-cli.js
文件。之所以node目录能够被命令行识别到,那是因为我们已经将node目录添加到系统环境变量中了。所以npm run dev
是可以执行,那为什么通过npm run dev
就可以执行对应的webpack-dev-server -c webpack.dev.js
命令呢。
这是因为npm run
会将当前目录下的 node_modules/.bin
(该文件夹用于存放一些包执行脚本的软连接) 添加到node的 PATH
环境变量中。我们可以看到该目录下会有如下两个文件,在Windows系统下就会执行webpack-dev-server.cmd
文件。
查看该文件内容,发现其实执行的是:
node ...\webpack-dev-server\bin\webpack-dev-server.js
npm run-script
执行流程总结一下来说就是:
npm install
安装一个包的时候,会将该包的可执行脚本软链接到node_modules/.bin
目录下。npm run
执行某个脚本时会首先把当前目录下的node_modules/.bin
添加到node的PATH
环境变量中。- 然后执行
package.json
文件scripts
中定义的对应脚本。即:npm run dev
转换成webpack-dev-server -c webpack.dev.js
。 - 执行脚本时,系统便会访问
node_modules/.bin
目录下对应的可执行文件。即webpack-dev-server.cmd
,命令就转换成node_modules/.bin/webpack-dev-server -c webpack.dev.js
- 然后执行该可执行文件,进而最终转换成
vbscript
node node_modules\webpack-dev-server\bin\webpack-dev-server.js -c webpack.dev.js
注意:
npm run
是将node_modules/.bin
添加到node的PATH
环境变量中,而并非系统环境变量。系统环境变量是在操作系统级别上定义的变量,而 Node 环境变量是特定于 Node.js 应用程序的变量,node环境变量通常包含系统环境变量
npm run
之所以能够访问到node环境变量,是因为npm
本质上执行的是node node_modules\npm\bin\npm-cli.js
,是一个node应用程序。
2.6 npm exec
npm exec
:执行本地或远程 npm 包中的命令。
上面介绍的npm run
执行的命令必须是package.json
中scripts
项定义的脚本命令。而npm exec
执行的命令无需在package.json
文件中定义。但是其运行环境和npm run
的类似。npm exec
使用方式如下:
css
npm exec -- <pkg>[@<version>] [args...]
npm exec --package=<pkg>[@<version>] -- <cmd> [args...]
npm exec -c '<cmd> [args...]'
npm exec --package=foo -c '<cmd> [args...]'
npm exec
的执行流程
下面以 npm exec -- <pkg>[@<version>] [args...]
为例,探索一下具体的执行流程:
-
首先在本地 查找是否存在
<pkg>
对应的npm包(必须包名 和版本号都相同)- 若存在,则运行这个包的
package.json
中bin
字段对应的可执行文件 - 若不存在,在远程npm仓库查找是否有
<pkg>
对应的npm包.- 若找到,则提示(可以通过
--yes
和--no
参数控制是否提示)是否将它们安装到 npm 缓存文件夹中,该文件夹将添加到执行过程中的 PATH 环境变量中。下载完成后,再运行这个包package.json
中bin
字段对应的可执行文件 - 若没找到,则退出
- 若找到,则提示(可以通过
- 若存在,则运行这个包的
-
执行
package.json
中bin
字段指定的可执行文件- 如果包在 package.json 的 bin 字段中只有单个入口,或者所有入口都是同一命令的别名,则将使用该命令。
- 如果
bin
字段有多个入口 ,并且其中之一与包名匹配,则将使用该命令。 - 如果没有 bin 字段,或者没有一个入口与包名匹配,则 npm exec 将退出并出现错误
此外 npm exec
提供如下常用配置项:
-p / --package
:指定npm exec
需要安装的包。无论--package
选项指定什么包,都将在执行命令的 PATH 中提供,以及任何本地安装的包可执行文件。可以多次指定 --package 选项,以便在所有指定的包都可用的环境中执行提供的命令-c / --call
:指定与已安装的软件包一起运行的自定义命令(类似package.json
文件中scripts
字段指定的命令)。如果未提供-c
或--call
选项,则使用位置参数来生成命令字符串。-w / --workspace
:指定命令运行的工作区,当然也可以通过--workspaces
指定多个工作区。
2.7 npx
npx
:执行本地或远程 npm 包中的命令。
css
npx -- <pkg>[@<version>] [args...]
npx --package=<pkg>[@<version>] -- <cmd> [args...]
npx -c '<cmd> [args...]'
npx --package=foo -c '<cmd> [args...]'
npx
与 npm exec
的区别
npx
与 npm exec
的作用相同,只是对于位置参数的解析方式有所不同,具体如下:
npx
执行命令时,所有options(例如:--package
等)必须在任何位置参数之前设置。npm exec
执行命令时,会优先解析设置的options,可以使用双连字符--
标志抑制对options的解析。
举个例子:
$ npx foo@latest bar --package=@npmcli/foo
在这种情况下,npx
将解析foo
包名称,并运行以下命令
$ foo bar --package=@npmcli/foo
由于--package
选项位于位置参数之后,因此它被视为执行命令的参数。
相反,由于 npm 的参数解析逻辑,运行此命令是不同的:
$ npm exec foo@latest bar --package=@npmcli/foo
--package
在这种情况下,npm 将首先解析选项,解析@npmcli/foo
包。然后,它将在该上下文中执行以下命令:
$ foo@latest bar
建议使用双连字符来明确告诉 npm 停止解析命令行选项和开关。因此,以下命令与上面的命令等效npx
:
$ npm exec -- foo@latest bar --package=@npmcli/foo
再引用官网上的两个例子:
tap
使用提供的参数运行本地依赖项中的版本:
shell
$ npm exec --tap --bail test/foo.js
$ npx tap --bail test/foo.js
通过指定选项来运行名称与包名称匹配的命令以外的 命令--package
:
ini
$ npm exec --package = foo -- bar --bar-argument
# ~ 或 ~
$ npx --package = foo bar --bar-argument
npx
与 npm
的区别
npm
全称是node package manager
,是一个node包管理器。npx
全称是node package execute
是一个npm包运行程序,npx
会随npm 5.2.0
及更高版本自动安装。
在 npx
出现之前,我们想要执行某些包中的二进制文件,需要首先npm install
下载安装该包,然后切换到该包的安装目录下,然后执行。此外,全局安装一些不经常使用的包,还会造成污染。
而npx
出现后,它可以直接执行npm包,无需安装该包。
以我们常用的create-react-app
为例,npx
出现前,需先全局安装create-react-app
lua
npm install create-react-app -g
然后执行create-react-app
命令
lua
create-react-app my-app
但实际上我们不会频繁使用create-react-app
,全局安装可能会造成软件包污染。
而使用npx
的话,只用执行如下命令即可:
lua
npx create-react-app my-app
npx
会首先查找本地是否安装了create-react-app
包,如果找到则执行该包命令。如果没有找到,则会临时安装 create-react-app
包,然后执行相关命令。即,仅在使用的时候安装,使用完之后又会卸载,不会造成软件包污染。
总结来说,npm
和npx
区别如下:
npm | npx |
---|---|
NPM 是一个包管理器,用于在计算机上安装、删除和更新 Javascript 包。 | NPX 是一个包执行器,用于直接执行 javascript 包,无需安装它们。 |
NPM 会全局安装软件包,这意味着您的机器可能会被长期不再需要的软件包污染。 | NPX 不安装软件包,因此无需担心计算机上的软件包污染。 |
要使用 NPM 来使用 create-react-app,我们首先必须全局安装它,然后运行它,这使得在这种情况下使用 NPM 变得多余。 | NPX 最常见的应用是 create-react-app 命令。由于我们只需要使用它一次,即在初始化项目时,不需要安装。 |
三、scripts
上述对npm常见命令的执行已经介绍的差不多了,但是个人感觉有必要在此继续了解一下有关package.json
文件中 scripts
项的一些知识点。
scripts
中定义的就是一些可以通过npm run
执行的脚本命令,执行时npm run
会将node_modules/.bin
目录添加到PATH
环境变量中。具体执行流程2.5中已经详细介绍,这里就不再赘述了。下面主要介绍 scripts
的一些书写规范。
支持通配符
由于 npm 脚本就是 Shell 脚本,因为可以使用 Shell 通配符。
json"lint": "jshint *.js" "lint": "jshint **/*.js"
上面代码中,*
表示任意文件名,**
表示任意一层子目录。
传递参数
向 npm 脚本传入参数,要使用--
标明。例如,有如下脚本
arduino
"webpack": 'webpack-cli'
我想要传递 --help
参数查看帮助文档,则需要运行如下命令:
arduino
npm run webpack -- --help
多任务
如果 npm 脚本里面需要执行多个任务,那么需要明确它们的执行顺序。
并行执行 (即同时执行):使用&
符号连接
arduino$ npm run script1.js & npm run script2.js
继发执行 (即只有前一个任务成功,才执行下一个任务):使用&&
符号连接
arduino$ npm run script1.js && npm run script2.js
输入输出
此外,任务之间或者任务与文件之间可以进行输入输出的传递。
<
用于将文件的内容(stdin)输入到命令>
用于重定向命令的输出(stdout)并将其转储到文件|
用于重定向命令的输出(stdout)并将其发送到另一个命令
hooks
npm 脚本有pre
和post
两个钩子。举例来说,build
脚本命令的钩子就是prebuild
和postbuild
。
json"prebuild": "echo I run before the build script", "build": "cross-env NODE_ENV=production webpack", "postbuild": "echo I run after the build script"
用户执行npm run build
的时候,会自动按照下面的顺序执行。
arduinonpm run prebuild && npm run build && npm run postbuild
快捷脚本
npm提供了一些快捷脚本,无需使用npm run
即可执行,例如以下几个常用的 npm 快捷脚本。
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
变量
- 通过
npm_package_
前缀,npm 脚本可以拿到package.json
里面的字段(注意:获取的是当前路径 下package.json
文件内部的变量)
例如:变量npm_package_name
返回包的名称
arduino
console.log(process.env.npm_package_name); // 输出包名
我们通过环境变量process.env
对象,拿到package.json
的字段值。如果是 Bash 脚本,可以用$npm_package_name
- 通过
npm_config_
前缀,拿到 npm 的配置变量,即npm config get xxx
命令返回的值。
例如:变量 npm_config_registry
返回配置的npm仓库地址。
该小结主要参考以下几位大佬的推文:
[1] npm scripts 使用指南
Ending
本文这里就结束了,以上是个人学习过程中的一些记录,如有错误,欢迎提出,共同学习。