我开始玩 Snowpack。它采用与 Webpack 不同的方法,在安装后立即捆绑单个包。
“问题”是,当我安装一个包时,我必须首先运行npm install --save my-package,然后我必须用npx snowpack. 在积雪文档提到,我可以包括prepare脚本,将snowpack一切都运行后npm install,但这并不适用于单个包,只是一个普通的npm install在我所有的依赖关系package.json。据我所知,npm 文档中提到的所有 npm 钩子都是这种情况。
有什么办法可以在我安装单个软件包时自动运行脚本?我能想到的唯一方法是覆盖安装脚本并向其中添加一些内容。GitHub 或其他地方是否有任何此类示例?
更新:为了澄清起见,我想在npx snowpack每次安装新软件包时运行,--save但最好不带--save-dev或不带--save. 对于任何包,这永远不会有所不同。这将特定于某个回购/项目,而不是我系统上的全局。
这是不够的运行snowpack后,只需运行npm install,你会被钩住得到postinstall或release。此外,我想确保在我的项目上工作的开发人员可以npm install --save newdep像往常一样使用然后snowpack运行。我不想要求开发人员使用自定义命名脚本。
简短回答:不幸的是,npm 不提供任何内置功能来满足您的要求。
生命周期钩子/脚本postinstall仅在运行通用npm install命令时调用,而不是npm install --save <pkg_name>在项目开发阶段有人运行时调用。
解决方法:考虑npm install --save通过npm在 shell 级别基本上覆盖命令来自定义复合命令的逻辑。
以下解决方案(尽管是 Bash 解决方案)描述了如何为特定项目实现此自定义逻辑。但是,此解决方案取决于以下条件:
npm install --save。~/.bashrc并且可能是~/.bash_profile..bashrc文件。以下三个步骤是配置您的项目和操作系统所必需的,以便在开发人员运行npm install --save <pkg_name>(或其变体)时npx snowpack随后调用该命令。
注意:第二点和第三点(以下)是开发人员需要执行(一次)以自定义其 Bash 启动文件的任务。
项目特定.bashrc文件:
首先在项目目录的根目录中创建以下“项目特定” .bashrc文件,即将其保存在与项目package.json文件所在位置相同的级别:
/some/path/to/my-project/.bashrc
npm() {
local name_badge="\x1b[37;40mpostinstall\x1b[0m"
array_includes() {
local word=$1
shift
for el in "$@"; do [[ "$el" == "$word" ]] && return 0; done
}
log_warn_message() {
local cmd_name=$1 warn_badge warn_mssg
warn_badge="\x1b[30;43mWARN!\x1b[0m"
warn_mssg="${cmd_name} command not found. Cannot run npx snowpack."
echo -e "\n${name_badge} ${warn_badge} ${warn_mssg}" >&2
}
log_run_message() {
echo -e "\n${name_badge} Running pseudo postinstall hook."
}
if [[ $* == "install "* || $* == "i "* ]] && array_includes --save "$@"; then
# 1. Run the given `npm install --save ...` command.
command npm "$@"
# 2. Check whether the `npx` command exists globally.
command -v npx >/dev/null 2>&1 || {
log_warn_message npx
return 1
}
log_run_message
# 3. Run the pseudo "postinstall" command.
command npx snowpack
else
# Run all other `npm` commands as per normal.
command npm "$@"
fi
}
Run Code Online (Sandbox Code Playgroud)
注意:要更好地了解此文件的作用,请参阅下面的“说明”部分。
该~/.bashrc文件:
为了使自定义逻辑,即npm上述.bashrc文件中的函数有效,有必要配置 Bash 以读取上述“项目特定” .bashrc文件。要配置它,请将以下代码行添加到~/.bashrc:
PROMPT_COMMAND='if [[ "$bashrc" != "$PWD" && "$PWD" != "$HOME" && -e .bashrc ]]; then bashrc="$PWD"; . .bashrc; fi'
Run Code Online (Sandbox Code Playgroud)
注意:为了更好地理解这行代码的作用,请参阅下面的“说明”部分。
该~/.bash_profile文件:
通常,您~/.bash_profile包含以下代码行来加载~/.bashrc文件(或它的某些变体):
if [ -f ~/.bashrc ]; then . ~/.bashrc; fi
Run Code Online (Sandbox Code Playgroud)
如果不存在,则必须将其添加到~/.bash_profile.
设置/配置助手:
考虑您的开发人员使用以下两个命令来帮助配置他们的 Bash 启动文件,按照上述第二步和第三步。
对于第二步,运行以下命令:
echo $'\n'"PROMPT_COMMAND='if [[ \"\$bashrc\" != \"\$PWD\" && \"\$PWD\" != \"\$HOME\" && -e .bashrc ]]; then bashrc=\"\$PWD\"; . .bashrc; fi'" >> ~/.bashrc
Run Code Online (Sandbox Code Playgroud)
这会将PROMPT_COMMAND=...代码行添加到现有~/.bashrc文件中,或者如果它不存在则创建一个新的:
对于第三步,运行以下命令以附加~/.bash_profile加载~/.bashrc文件所需的代码行:
echo $'\n'"if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile
Run Code Online (Sandbox Code Playgroud)
我的 shell 是否配置为 Bash?
要检查 shell 是否配置为 Bash,您可以创建一个新会话,即创建一个新的终端窗口并运行:
echo $0
Run Code Online (Sandbox Code Playgroud)
如果它打印,-bash那么它正在使用 Bash。
如何将我的 shell 配置为 Bash?
如果echo $0不打印,-bash则您需要更改外壳。要将其更改为 Bash 运行:
chsh -s /bin/bash
Run Code Online (Sandbox Code Playgroud)
注意:您需要创建一个新会话才能使此更改生效。
项目特定.bashrc文件:
此.bashrc文件包含一个shell函数命名npm。此函数的主体包含覆盖默认npm install|i --save命令所需的逻辑。
if语句中指定的条件,即读取的部分;
echo $0
Run Code Online (Sandbox Code Playgroud)
本质上读取$* 特殊参数以检查传递给npm函数的参数是否以任一开头;install ,或者它的速记等价物i ,以及是否--save也通过了选项/参数。
为了检查--save参数是否存在,我们将$@特殊参数传递给array_includes函数。我们以不同的方式处理这个参数,因为--save选项的位置在复合命令中可能不同。例如,用户可以通过运行它来安装一个包;
chsh -s /bin/bash
Run Code Online (Sandbox Code Playgroud)
或这个(或其他一些变体):
if [[ $* == "install "* || $* == "i "* ]] && array_includes --save "$@"; then
...
fi
Run Code Online (Sandbox Code Playgroud)
当if满足语句中指定的条件时,即它们是true,我们在其主体中执行以下任务:
npm install --save ...通过以下行按原样运行给定的命令:
# Example showing `--save` option at the end
npm install <pkg_name> --save
Run Code Online (Sandbox Code Playgroud)
npx通过读取的部分检查命令是否全局存在:
# Example showing `--save` option in the middle
npm i --save <pkg_name>
Run Code Online (Sandbox Code Playgroud)
如果该npx命令不可用(全局),我们会警告用户该npx snowpack命令无法运行,并return在退出状态为1.
注意:我在此检查中的逻辑假设您将进行npx全局安装。但是,如果您在npm项目中本地安装,则需要更改此逻辑。也许通过检查是否./node_modules/.bin/npx存在来代替。或者,您可能确信该npx命令将始终存在,因此得出此检查是不必要的结论。
如果该npx命令全局存在,则我们运行伪“postinstall”命令,即
command npm "$@"
Run Code Online (Sandbox Code Playgroud)
当if语句中指定的条件不满足时,即它们是false,用户实际上是在运行任何其他不满足的 npm 命令npm install --save <pkg_name>。因此,在else分支中,我们按原样运行命令:
command -v npx >/dev/null 2>&1 || {
log_warn_message npx
return 1
}
Run Code Online (Sandbox Code Playgroud)
~/.bashrc 文件:
在《Bash 参考手册》的5.2 Bash Variables小节中,该变量描述如下:PROMPT_COMMAND
PROMPT_COMMAND如果设置,该值将被解释为在打印每个主要提示 (
$PS1)之前执行的命令。
所以,这行代码(又来了):
command npx snowpack
Run Code Online (Sandbox Code Playgroud)
加载“项目特定” .bashrc(如果存在),这反过来又会npm用npm函数覆盖命令。这实质上提供了一种覆盖npm install --save特定项目的复合命令的机制。
见这个答案将@Cyrus作进一步的解释。