跨平台兼容
npm script 的一个常见痛点是跨平台兼容性问题。在类Unix系统(Linux、macOS)中通用的Shell命令,在Windows环境下(如CMD或PowerShell)往往无法直接运行。例如,文件操作命令(rm, cp, mkdir)和环境变量的语法在不同平台间存在显著差异。
一个简单粗暴的解决方法是为不同平台编写不同的脚本,但这违背了DRY原则,并增加了维护成本。
{
"scripts": {
"bash-script": "echo Hello $npm_package_name",
"win-script": "echo Hello %npm_package_name%"
}
}幸运的是,社区提供了许多优秀的工具,可以帮助我们编写一次即可在所有主流平台运行的 npm script。
建议:在Windows环境下,推荐使用 Git Bash 作为运行
npm script的终端,它可以提供更接近类Unix系统的体验,减少兼容性问题。
文件系统操作的跨平台兼容
对于常见的文件和目录操作,我们可以使用以下跨平台工具来替代原生Shell命令:
- rimraf: 替代
rm -rf,用于强制删除文件和目录。 - cpr: 替代
cp -r,用于递归地复制文件和目录。 - make-dir-cli: 替代
mkdir -p,用于创建多层嵌套的目录。
改造步骤如下:
-
安装依赖:
bashnpm install rimraf cpr make-dir-cli --save-dev -
更新
package.json中的脚本:假设我们有以下脚本:
json{ "scripts": { "cover:cleanup": "rm -rf coverage .nyc_output", "cover:archive": "mkdir -p coverage_archive/1.0.0 && cp -r coverage/* coverage_archive/1.0.0" } }使用跨平台工具进行改造后:
json{ "scripts": { "cover:cleanup": "rimraf coverage .nyc_output", "cover:archive": "make-dir coverage_archive/1.0.0 && cpr coverage/* coverage_archive/1.0.0 -o" } }注意:
cpr命令需要使用-o(--overwrite) 参数来覆盖已存在的文件,并且其参数顺序是固定的:cpr <source> <destination> [options]。
环境变量引用的跨平台兼容
不同平台引用环境变量的语法也不同($VAR vs %VAR%)。cross-var 工具可以解决这个问题,它允许你在所有平台统一使用类Unix的 $ 语法。
-
安装依赖:
bashnpm install cross-var --save-dev -
更新脚本:
只需在需要使用变量的命令前加上
cross-var即可。如果命令中包含多个部分,需要用引号将其包裹起来。json{ "scripts": { "cover:archive": "cross-var \"make-dir coverage_archive/$npm_package_version && cpr coverage/* coverage_archive/$npm_package_version -o\"", "cover:serve": "cross-var http-server coverage_archive/$npm_package_version -p $npm_package_config_port" } }如果你关心依赖的体积,可以考虑使用
cross-var-no-babel,它是一个不依赖Babel的轻量级版本。
环境变量设置的跨平台兼容
在脚本中设置环境变量也存在平台差异(NODE_ENV=production command vs set NODE_ENV=production && command)。cross-env 是解决此问题的标准方案。
-
安装依赖:
bashnpm install cross-env --save-dev -
更新脚本:
在设置环境变量的命令前加上
cross-env即可。json{ "scripts": { "test": "cross-env NODE_ENV=test mocha tests/" } }
总结与建议
- 在
npm script中,优先使用双引号,并对特殊字符进行转义。 - 大多数前端构建工具(如
eslint,mocha,webpack)本身已经处理了跨平台兼容性问题。 - 如果遇到其他兼容性问题,可以尝试在 npmjs.com 上搜索
cross-platform或cross-前缀的包,通常都能找到成熟的解决方案。 - 对于Windows用户,可以了解并尝试使用 Windows Subsystem for Linux (WSL),它能在Windows上提供一个完整的Linux环境,从根本上解决兼容性问题。
本节用到的代码见 GitHub,想边看边动手练习的同学可以拉下来自己改,注意切换到正确的分支
06-add-cross-platform-support。