运行 package.json 中的另一个 yarn/npm 任务,没有指定 yarn 或 npm
Run another yarn/npm task within a package.json, without specifying yarn or npm
我的package.json"deploy"有一个任务需要先调用"build"。我是这样指定的:
"deploy": "yarn run build; ./deploy.sh",
问题是这个硬编码 yarn
作为包管理器。所以如果有人不使用yarn
,那是行不通的。切换到 npm
会导致类似的问题。
在对 npm
或 yarn
的选择保持不可知的同时实现这一目标的好方法是什么?
这可能并不理想,但您可以 运行 在您的项目根目录下创建一个 .js
文件来进行这些检查...
您可以在您的项目根目录下创建一个名为 yarnpm.js
(或其他名称)的文件,然后在您的 package.json
deploy
命令中调用该文件..
// package.json (trimmed)
"scripts": {
"deploy": "node yarnpm",
"build": "whatever build command you use"
},
// yarnpm.js
const fs = require('fs');
const FILE_NAME = process.argv[1].replace(/^.*[\\/]/, '');
// Command you wish to run with `{{}}` in place of `npm` or `yarn'
// This would allow you to easily run multiple `npm`/`yarn` commands without much work
// For example, `{{}} run one && {{}} run two
const COMMAND_TO_RUN = '{{}} run build; ./deploy.sh';
try {
if (fs.existsSync('./package-lock.json')) { // Check for `npm`
execute(COMMAND_TO_RUN.replace('{{}}', 'npm'));
} else if (fs.existsSync('./yarn.lock')) { // Check for `yarn`
execute(COMMAND_TO_RUN.replace('{{}}', 'yarn'));
} else {
console.log('\x1b[33m', `[${FILE_NAME}] Unable to locate either npm or yarn!`, '3[0m');
}
} catch (err) {
console.log('\x1b[31m', `[${FILE_NAME}] Unable to deploy!`, '3[0m');
}
function execute(command) { // Helper function, to make running `exec` easier
require('child_process').exec(command,
(error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(stdout);
});
}
希望这对您有所帮助!干杯。
编辑:
...或者如果您想参数化 yarnpm.js
脚本,使其易于重用,并将所有 "commands" 保存在 package.json
文件中,您可以做一些事情像这样..
// package.json (trimmed, parameterized)
"scripts": {
"deploy": "node yarnpm '{{}} run build; ./deploy.sh'",
"build": "node build.js"
},
// yarnpm.js (parameterized)
const COMMAND_TO_RUN = process.argv[2]; // Technically, the first 'parameter' is the third index
const FILE_NAME = process.argv[1].replace(/^.*[\\/]/, '');
if (COMMAND_TO_RUN) {
const fs = require('fs');
try {
if (fs.existsSync('./package-lock.json')) { // Check for `npm`
execute(COMMAND_TO_RUN.replace('{{}}', 'npm'));
} else if (fs.existsSync('./yarn.lock')) { // Check for `yarn`
execute(COMMAND_TO_RUN.replace('{{}}', 'yarn'));
} else {
console.log('\x1b[33m', `[${FILE_NAME}] Unable to locate either npm or yarn!`, '3[0m');
}
} catch (err) {
console.log('\x1b[31m', `[${FILE_NAME}] Unable to deploy!`, '3[0m');
}
function execute(command) { // Helper function, to make running `exec` easier
require('child_process').exec(command,
(error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(stdout);
});
}
} else {
console.log('\x1b[31m', `[${FILE_NAME}] Requires a single argument!`, '3[0m')
}
如果在 运行 之前检查怎么办?
您可以创建一个名为 build.sh
的新文件,其内容如下:
# check if current user installed node environment, if not, auto install it.
if command -v node >/dev/null 2>&1; then
echo "version of node: $(node -v)"
echo "version of npm: $(npm -v)"
else
# auto install node environment, suppose platform is centos,
# need change this part to apply other platform.
curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash -
yum -y install nodejs
fi
npm run build
那么您的脚本将是:
{
"deploy": "./build.sh && ./deploy.sh"
}
所以我想我有一个更简单的解决方案:
"deploy": "yarn run build || npm run build; ./deploy.sh",
它唯一真正的缺点是在yarn存在的情况下,但是构建失败,那么npm run build
也会发生。
一种简单的方法是使用 npm-run-all 包,其文档说明:
Yarn Compatibility
If a script is invoked with Yarn, npm-run-all will correctly use Yarn to execute the plan's child scripts.
所以你可以这样做:
"predeploy": "run-s build",
"deploy": "./deploy.sh",
predeploy
步骤将使用 npm 或 yarn,具体取决于您调用 deploy
任务的方式。
我认为让 package.json 中的运行保持包管理器不可知是很好的,这样它们就不会绑定到特定的包管理器,但在一个项目中,就使用单个包管理器,这样您就不会处理冲突的锁文件。
我的package.json"deploy"有一个任务需要先调用"build"。我是这样指定的:
"deploy": "yarn run build; ./deploy.sh",
问题是这个硬编码 yarn
作为包管理器。所以如果有人不使用yarn
,那是行不通的。切换到 npm
会导致类似的问题。
在对 npm
或 yarn
的选择保持不可知的同时实现这一目标的好方法是什么?
这可能并不理想,但您可以 运行 在您的项目根目录下创建一个 .js
文件来进行这些检查...
您可以在您的项目根目录下创建一个名为 yarnpm.js
(或其他名称)的文件,然后在您的 package.json
deploy
命令中调用该文件..
// package.json (trimmed)
"scripts": {
"deploy": "node yarnpm",
"build": "whatever build command you use"
},
// yarnpm.js
const fs = require('fs');
const FILE_NAME = process.argv[1].replace(/^.*[\\/]/, '');
// Command you wish to run with `{{}}` in place of `npm` or `yarn'
// This would allow you to easily run multiple `npm`/`yarn` commands without much work
// For example, `{{}} run one && {{}} run two
const COMMAND_TO_RUN = '{{}} run build; ./deploy.sh';
try {
if (fs.existsSync('./package-lock.json')) { // Check for `npm`
execute(COMMAND_TO_RUN.replace('{{}}', 'npm'));
} else if (fs.existsSync('./yarn.lock')) { // Check for `yarn`
execute(COMMAND_TO_RUN.replace('{{}}', 'yarn'));
} else {
console.log('\x1b[33m', `[${FILE_NAME}] Unable to locate either npm or yarn!`, '3[0m');
}
} catch (err) {
console.log('\x1b[31m', `[${FILE_NAME}] Unable to deploy!`, '3[0m');
}
function execute(command) { // Helper function, to make running `exec` easier
require('child_process').exec(command,
(error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(stdout);
});
}
希望这对您有所帮助!干杯。
编辑:
...或者如果您想参数化 yarnpm.js
脚本,使其易于重用,并将所有 "commands" 保存在 package.json
文件中,您可以做一些事情像这样..
// package.json (trimmed, parameterized)
"scripts": {
"deploy": "node yarnpm '{{}} run build; ./deploy.sh'",
"build": "node build.js"
},
// yarnpm.js (parameterized)
const COMMAND_TO_RUN = process.argv[2]; // Technically, the first 'parameter' is the third index
const FILE_NAME = process.argv[1].replace(/^.*[\\/]/, '');
if (COMMAND_TO_RUN) {
const fs = require('fs');
try {
if (fs.existsSync('./package-lock.json')) { // Check for `npm`
execute(COMMAND_TO_RUN.replace('{{}}', 'npm'));
} else if (fs.existsSync('./yarn.lock')) { // Check for `yarn`
execute(COMMAND_TO_RUN.replace('{{}}', 'yarn'));
} else {
console.log('\x1b[33m', `[${FILE_NAME}] Unable to locate either npm or yarn!`, '3[0m');
}
} catch (err) {
console.log('\x1b[31m', `[${FILE_NAME}] Unable to deploy!`, '3[0m');
}
function execute(command) { // Helper function, to make running `exec` easier
require('child_process').exec(command,
(error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(stdout);
});
}
} else {
console.log('\x1b[31m', `[${FILE_NAME}] Requires a single argument!`, '3[0m')
}
如果在 运行 之前检查怎么办?
您可以创建一个名为 build.sh
的新文件,其内容如下:
# check if current user installed node environment, if not, auto install it.
if command -v node >/dev/null 2>&1; then
echo "version of node: $(node -v)"
echo "version of npm: $(npm -v)"
else
# auto install node environment, suppose platform is centos,
# need change this part to apply other platform.
curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash -
yum -y install nodejs
fi
npm run build
那么您的脚本将是:
{
"deploy": "./build.sh && ./deploy.sh"
}
所以我想我有一个更简单的解决方案:
"deploy": "yarn run build || npm run build; ./deploy.sh",
它唯一真正的缺点是在yarn存在的情况下,但是构建失败,那么npm run build
也会发生。
一种简单的方法是使用 npm-run-all 包,其文档说明:
Yarn CompatibilityIf a script is invoked with Yarn, npm-run-all will correctly use Yarn to execute the plan's child scripts.
所以你可以这样做:
"predeploy": "run-s build",
"deploy": "./deploy.sh",
predeploy
步骤将使用 npm 或 yarn,具体取决于您调用 deploy
任务的方式。
我认为让 package.json 中的运行保持包管理器不可知是很好的,这样它们就不会绑定到特定的包管理器,但在一个项目中,就使用单个包管理器,这样您就不会处理冲突的锁文件。