[英]Run another yarn/npm task within a package.json, without specifying yarn or npm
I have a task in my package.json "deploy", which needs to first call "build".我的 package.json 中有一个任务“deploy”,需要先调用“build”。 I have specified it like this:
我已经这样指定了:
"deploy": "yarn run build; ./deploy.sh",
"deploy": "纱线运行构建;./deploy.sh",
The problem is that this hard codes yarn
as the package manager.问题是这个硬编码
yarn
作为包管理器。 So if someone doesn't use yarn
, it doesn't work.所以如果有人不使用
yarn
,它就行不通。 Switching to npm
causes a similar issue.切换到
npm
会导致类似的问题。
What's a good way to achieve this while remaining agnostic to the choice of npm
or yarn
?在不
npm
或yarn
的选择的同时实现这一目标的好方法是什么?
One simple approach is to use the npm-run-all package, whose documentation states:一种简单的方法是使用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.
如果使用 Yarn 调用脚本,npm-run-all 将正确使用 Yarn 执行计划的子脚本。
So you can do this:所以你可以这样做:
"predeploy": "run-s build",
"deploy": "./deploy.sh",
And the predeploy
step will use either npm or yarn depending on how you invoked the deploy
task. predeploy
步骤将使用 npm 或 yarn,具体取决于您调用deploy
任务的方式。
I think it is good to have the runs in package.json remain package manager agnostic so that they aren't tied to a specific package manager, but within a project, it is probably prudent to agree on the use of a single package manager so that you're not dealing with conflicting lockfiles.我认为让 package.json 中的运行保持与包管理器无关是很好的,这样它们就不会绑定到特定的包管理器,但在一个项目中,同意使用单个包管理器可能是谨慎的,所以你没有处理冲突的锁文件。
It's probably not ideal, but you could run a .js
file at your project root to make these checks...这可能并不理想,但您可以在项目根目录下运行
.js
文件来进行这些检查...
You could create a file at your project root called yarnpm.js
(or whatever), and call said file in your package.json
deploy
command..您可以在您的项目根目录创建一个名为
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!`, '\033[0m');
}
} catch (err) {
console.log('\x1b[31m', `[${FILE_NAME}] Unable to deploy!`, '\033[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);
});
}
Hope this helps in some way!希望这在某种程度上有所帮助! Cheers.
干杯。
EDIT:编辑:
...or if you wanted to parameterize the yarnpm.js
script, to make it easily reusable, and to keep all "commands" inside the package.json
file, you could do something like this.. ...或者如果你想参数化
yarnpm.js
脚本,使其易于重用,并将所有“命令”保存在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!`, '\033[0m');
}
} catch (err) {
console.log('\x1b[31m', `[${FILE_NAME}] Unable to deploy!`, '\033[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!`, '\033[0m')
}
What if check before run?如果在运行前检查怎么办?
You can create a new file called build.sh
, and it's content below:您可以创建一个名为
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
Then your script will be:那么你的脚本将是:
{
"deploy": "./build.sh && ./deploy.sh"
}
So I think I have a much simpler solution:所以我想我有一个更简单的解决方案:
"deploy": "yarn run build || npm run build; ./deploy.sh",
Its only real downside is in the case where yarn exists, but the build fails, then npm run build
will also take place.它唯一真正的缺点是在存在纱线的情况下,但构建失败,然后
npm run build
也会发生。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.