這個 package.json 小招,讓我的終端“聰明”了十倍
重復(fù)敲同樣的命令、反復(fù) rerun、長嘆一口氣——終端里最讓人心累的,就是這些機械化的手活。
其實,完全可以更優(yōu)雅。下面這招把我的 package.json 變成了一臺小型自動化機器:無需重構(gòu)工程、也不必引入龐大的腳手架,幾行配置就能把常用任務(wù)變成順手的 CLI 命令。
一起上手。
原理一線牽:用 bin 字段把腳本“變成命令”
我們先從 bin 說起。很多人只在 package.json 里寫過 scripts:
{
"scripts": {
"generate": "tsx scripts/generate.ts"
}
}然后用 npm run generate 去執(zhí)行。能用,但不夠優(yōu)雅。
更“聰明”的做法是:把腳本注冊成命令。做兩步:
1) 在 package.json 增加 bin
把命令名映射到文件路徑(推薦放到 scripts/ 或 bin/ 目錄):
{
"bin": {
"generate": "./scripts/generate.js"
}
}2) 寫一個帶 shebang 的 Node 腳本
文件開頭加上 #!/usr/bin/env node,內(nèi)容可以是你想自動化的任何事,比如生成一個 TypeScript 配置:
#!/usr/bin/env node
const fs = require("fs");
const config = `export default {
compilerOptions: {
target: "esnext",
module: "commonjs"
}
}`;
fs.writeFileSync("tsconfig.json", config);
console.log("TypeScript config generated. Happy coding!");這時候,直接來一句:
npx generate咔噠——命令就跑起來了。
想在任何地方都能用?把它“全局”一下
臨時用 npx 很方便;如果你希望在任意目錄都能敲 generate,再走兩步:
- 先安裝依賴、確??蓤?zhí)行位正確:
npm install- 用 npm link 把這個包鏈接到全局:
npm link現(xiàn)在,無論身處什么項目,終端里敲:
generate就能觸發(fā)同一份自動化邏輯。收益非常直接:
- ? 把重復(fù)性搭建一鍵化
- ? 精神力都留給“正經(jīng)事”
- ? 用 JavaScript 輕松擴展成小而美的 CLI
小擴展:把“命令”做得更像“工具”
bin 只是入口。稍加打磨,就能讓體驗更順手:
- 解析參數(shù):搭配 arg 或 yargs,支持 --out, --force, --preset 等選項
- 彩色輸出:用 chalk 或 colorette,把成功/警告/錯誤一眼區(qū)分
- 跨平臺 shebang:#!/usr/bin/env node 更穩(wěn)妥(避免硬編碼 /usr/bin/node)
- 權(quán)限與換行:提交腳本時確保可執(zhí)行位(chmod +x scripts/generate.js),同時注意 Windows 的 CRLF/LF
- 包管理器兼容:npm link 的同時,pnpm link --global / yarn link 也可以準(zhǔn)備一份說明
- 版本輸出:別忘了 --version / --help,讀 package.json 的 version 字段即可
一個稍微完整點的入口示例(含參數(shù)與幫助):
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");
const arg = require("arg");
const chalk = require("chalk");
function parseArgs(raw) {
try {
return arg(
{
"--out": String,
"--force": Boolean,
"--help": Boolean,
"--version": Boolean,
"-o": "--out",
"-f": "--force",
"-h": "--help",
"-v": "--version",
},
{ argv: raw.slice(2) }
);
} catch (e) {
console.error(chalk.red(e.message));
process.exit(1);
}
}
function printHelp() {
console.log(`
${chalk.bold("generate")} - quick scaffolding for tsconfig
Usage:
generate [--out FILE] [--force]
Options:
-o, --out Output file (default: tsconfig.json)
-f, --force Overwrite when file exists
-h, --help Show help
-v, --version Show version
`);
}
function main() {
const args = parseArgs(process.argv);
if (args["--help"]) return printHelp();
if (args["--version"]) {
const pkg = require(path.join(__dirname, "..", "package.json"));
console.log(pkg.version);
return;
}
const out = args["--out"] || "tsconfig.json";
const outPath = path.resolve(process.cwd(), out);
const exists = fs.existsSync(outPath);
if (exists && !args["--force"]) {
console.log(chalk.yellow(`File exists: ${out}\nUse --force to overwrite.`));
process.exit(0);
}
const config = `export default {
compilerOptions: {
target: "esnext",
module: "commonjs"
}
}`;
fs.writeFileSync(outPath, config);
console.log(chalk.green(`? Generated ${out}`));
}
main();常見坑與小貼士
- ESM/TS 支持:如果腳本用 ESM/TS,考慮用 tsx 或 esbuild-register 在 CLI 內(nèi)部啟動,或在發(fā)布前預(yù)編譯到 dist/
- 多命令場景:bin 可以映射多個可執(zhí)行文件,例如:
{
"bin": {
"generate": "./scripts/generate.js",
"clean": "./scripts/clean.js"
}
}- 項目內(nèi)局部使用:不想全局?在項目里也能直接 npx . generate(npx 支持以當(dāng)前目錄當(dāng)包)
- 權(quán)限問題:在某些系統(tǒng)上全局鏈接需要管理員權(quán)限;CI 環(huán)境更推薦在項目內(nèi)用 npx 執(zhí)行
總結(jié)一下
- scripts 適合項目內(nèi)部跑任務(wù),
- bin 則把腳本升級為通用命令,讓終端更貼合你的日常動作。 配上 arg / chalk 等小庫,你就擁有了一個體感超流暢的微型 CLI 套件。
下回你再想“復(fù)制某個配置、批量生成文件、初始化約定模板”,別再手敲那長串命令了——把它封到 bin 里,一行搞定。

































