NPM 条件脚本(Windows / Mac)应执行不同的命令)

NPM conditional script (Windows / Mac) shall execute different commands)

用例:

我正在 NPM 中设置一个 prepublishOnly 挂钩,它会删除 "lib" 文件夹,然后将 typescript 源文件转译到一个新的 lib 文件夹中,然后进行 运行 测试.

问题:

两个人应该发布 NPM 包,他们都在不同的 OS (Windows / Mac) 上工作。因此删除文件夹的命令不同

  "scripts": {
    "build": "tsc",
    "clean": "rm -rf lib",
    "clean:windows": "if exist lib rmdir /s /q lib",
    "lint": "tslint --project tsconfig.json --format stylish src/**/*.ts",
    "format": "prettier --write \"**/*.ts\""
  },
  "husky": {
    "hooks": {
      "pre-push": "npm run clean:windows && npm run build && npm run test"
    }
  },

问题:

有没有办法有条件地 运行 NPM 脚本(基于使用的 OS)或者是否有一个删除文件夹命令可以跨这些 OS?

我解决此类问题的方法是使用 gulp 定义一组特定于 os 的任务,因为您在那里编写的代码是 OS-agnostic.

您需要安装 gulp 作为依赖项并在根目录中创建一个 gulpfile.js。 在其中,定义一个删除文件夹的任务。

var gulp = require('gulp'),
    path = require('path'),
    fs = require('fs-extra');

const rootFolder = path.join(__dirname);
const libFolder = path.join(rootFolder, 'lib');

gulp.task('clean:lib', function () {
  return deleteFolder(libFolder);
});

function deleteFolder(folder) {
  return fs.removeSync(folder);
}

gulp.task('deleteLib', ['clean:lib']);

然后,在您的 package.json 脚本中,您可以执行 && gulp deleteLib。 (确保 gulp 文件中使用的包作为开发依赖项安装在 package.json 中!

代码未经测试,写在我的脑海中,但这只是给你一个大概的想法。

添加 gulp 到你的工具列表似乎是不必要的,如果你想做的只是通过 npm 脚本在交叉平台方式。对于轻量级解决方案,请考虑以下两种解决方案:


解决方案 1

看看rimraf,它被描述为:

The UNIX command rm -rf for node.

用法

  1. cd 到您的项目目录和 运行 以下命令:

    npm install rimraf --save-dev
    
  2. package.json 中的 clean 脚本更改为以下内容:

    "scripts": {
      "clean": "rimraf lib",
      ...
    },
    
  3. 从您的 package.json 中删除 clean:windows 脚本,因为它现在是多余的。

注意 我在将它作为本地依赖项安装时并没有取得很大的成功,因此我使用下面的解决方案二。然而,您可能会取得更大的成功 - 所以值得一试。


解决方案 2

以下解决方案使用 shelljs rm command which is analogous to the Unix rm -rf 命令,但它用于节点 - 因此它是一个跨平台等效项。

以下步骤显示了如何实现:

  1. cd 到您的项目目录并通过 运行 安装 shelljs 以下命令:

    npm install shelljs --save-dev
    
  2. 创建自定义节点脚本如下,我们将文件命名为clean.js:

    const shell = require('shelljs');
    
    process.argv.slice(2).forEach(function(_path) {
      shell.rm('-rf', _path);
    });
    

    并将其保存到项目根目录中名为 .scripts 的隐藏目录中。例如:

    .
    ├── .scripts
    │   └── clean.js
    ├── lib
    │   └── ...
    ├── node_modules
    │   └── ...
    ├── package.json
    ├── src
    │   └── ...
    └── ...
    
  3. package.json 中的 clean 脚本替换为以下内容:

    "scripts": {
      "clean": "node .scripts/clean lib",
      ...
    },
    

    您也可以将多个路径参数传递给 clean.js。例如:

    "scripts": {
      "clean": "node .scripts/clean lib another/folder/path foo/bar",
      ...
    },
    

    文件路径也被处理。例如:

    "scripts": {
      "clean": "node .scripts/clean path/to/quux.js",
      ...
    },
    
  4. 从您的 package.json 中删除 clean:windows 脚本,因为它现在是多余的。

注释

  1. clean.js 利用节点内置 process.argv 获取调用脚本时传递给 Node 的命令行参数数组。

  2. 然后我们 slice() 来自索引 2 的参数数组以确保我们只包含 folder/file 路径参数(例如 lib) .

  3. 最后,我们使用 forEach() 遍历数组中的每个文件夹路径,并在循环的每一轮中调用 shell.rm('-rf', _path); 来删除资产。


编辑/更新:

另一种跨平台解决方案(最初发布此答案时不可用)是利用 shx 包,描述为:

shx is a wrapper around ShellJS Unix commands, providing an easy solution for simple Unix-like, cross-platform commands in npm package scripts

  1. 运行以下命令安装shx:

    npm i -D shx
    
  2. 然后在package.json中重新定义你的clean脚本如下:

    "scripts": {
      "clean": "shx rm -rf lib"
    }