{T}

拆分到单独文件

随着项目复杂度的增加,package.json 中的 scripts 对象可能会变得异常庞大和混乱,这会严重影响其可读性和可维护性。一个有效的解决方案是将这些复杂的脚本逻辑拆分到独立的文件中。

scripty 是一个轻量级的工具,它能帮助我们实现这一目标。通过将脚本移至单独的文件,我们可以将复杂性隔离开来,使 package.json 保持整洁,并让整个工作流更加清晰。

为什么要拆分脚本?

当单个脚本命令超过一行,或者多个脚本之间存在复杂的调用关系时,就应该考虑将其拆分。例如,一个完整的测试覆盖率任务可能包括清理、运行测试、归档报告和启动服务等多个步骤,这些逻辑都堆积在 package.json 中会非常臃肿。

使用 scripty 进行重构

以下演示了如何将一组复杂的 cover 相关脚本拆分到独立文件中。

1. 安装 scripty

bash
npm install scripty --save-dev

2. 创建脚本目录和文件

scripty 默认在项目根目录的 scripts/ 文件夹中查找脚本。其文件路径与 npm script 命令的名称直接对应。

  • npm run cover -> scripts/cover.sh
  • npm run cover:serve -> scripts/cover/serve.sh
  • npm run cover:open -> scripts/cover/open.sh

根据这个约定,我们创建相应的目录和文件:

bash
# 创建目录
mkdir -p scripts/cover

# 创建脚本文件
touch scripts/cover.sh
touch scripts/cover/serve.sh
touch scripts/cover/open.sh

# 赋予所有脚本可执行权限
chmod +x scripts/**/*.sh

3. 编写独立的脚本文件

现在,我们将原本在 package.json 中的逻辑移到这些 .sh 文件中。在这些独立的脚本文件中,我们依然可以访问 npm 提供的所有环境变量(如 $npm_package_version)。

scripts/cover.sh (合并了清理、测试、归档和预览的逻辑)

bash
#!/usr/bin/env bash

# 1. 清理旧的覆盖率报告
rimraf coverage .nyc_output

# 2. 运行测试并生成新的覆盖率报告
nyc --reporter=html npm test

# 3. 按版本号归档报告
mkdir -p coverage_archive/$npm_package_version
cp -r coverage/* coverage_archive/$npm_package_version

# 4. 启动服务并打开浏览器
npm-run-all --parallel cover:serve cover:open

scripts/cover/serve.sh

bash
#!/usr/bin/env bash

http-server coverage_archive/$npm_package_version -p $npm_package_config_port

scripts/cover/open.sh

bash
#!/usr/bin/env bash

# 等待1秒,确保HTTP服务已成功启动
sleep 1
opn http://localhost:$npm_package_config_port

注意:这些示例使用了 Bash 脚本。对于需要跨平台兼容的复杂逻辑,推荐使用 Node.js 脚本(将在下一节介绍)。

4. 更新 package.json

最后,我们清理 package.json 中的旧脚本,让它们统一调用 scripty

json
{
  "scripts": {
    "test": "cross-env NODE_ENV=test mocha tests/",
    "lint": "eslint .",
    "cover": "scripty",
    "cover:serve": "scripty",
    "cover:open": "scripty"
  }
}

现在,package.json 变得非常简洁。当我们运行 npm run cover 时,scripty 会自动找到并执行 scripts/cover.sh 文件。

5. 测试运行

执行 npm run cover,你会看到 scripty 在执行脚本前会打印出将要运行的命令内容,这对于调试非常有用。最终的执行结果应与拆分前完全一致。

scripty 还支持并行执行、通配符匹配等高级功能,详情可查阅其官方文档。

通过这种方式,我们成功地将复杂的脚本逻辑封装到了独立的文件中,极大地提升了项目的可维护性。


本节用到的代码见 GitHub,想边看边动手练习的同学可以拉下来自己改,注意切换到正确的分支 07-manage-complexity-using-scripty