一、目录结构
二、源码
package.json
{
"name": "react-cli-codeman",
"version": "1.0.0",
"description": "A simple cli tool",
"main": "index.js",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://gitee.com/jflyhak/react-cli-codeman"
},
"bin": {
"mycli": "bin/index.js"
},
"dependencies": {
"chalk": "^4.1.2",
"commander": "^12.1.0",
"cross-spawn": "^7.0.3",
"fs-extra": "^11.2.0"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": ""
}
bin/index.js
#!/usr/bin/env node
(async function(){
const path = require("path");
const fs = require("fs-extra");
const commander = require("commander");
const chalk = require("chalk");
const packageJson = require("../package.json");
const appPath = process.cwd();
const craPath = path.resolve(__dirname);
let projectName;
let templateName;
let templatePath;
const program = new commander.Command()
.version(packageJson.version)
.description(packageJson.description)
.arguments("<project-directory>")
.usage(`${chalk.green("<project-directory>")} [options]`)
.action((name, options) => {
projectName = name;
templateName = options.typescript
? "cra-template-typescript"
: "cra-template";
templatePath = path.resolve(craPath, `../package/${templateName}/template`);
})
.option("-t, --typescript", "是否使用ts模板");
program.parse();
const appRoot = path.resolve(appPath, projectName);
// create and copy template files
try {
await fs.mkdir(`${appPath}/${projectName}`, { recursive: true });
console.log(chalk.green(`创建目录${projectName}成功`));
await fs.copy(templatePath, path.resolve(appPath, projectName));
console.log(chalk.green(`复制${templateName}模板成功`));
const appName = path.basename(appRoot);
const packageJson = {
name: appName,
version: "0.1.0",
private: true,
scripts: {
start: "react-scripts start",
build: "react-scripts build",
test: "react-scripts test",
eject: "react-scripts eject",
},
browserslist: {
production: [">0.2%", "not dead", "not op_mini all"],
development: [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version",
],
},
};
await fs.writeFileSync(
path.join(appRoot, "package.json"),
JSON.stringify(packageJson, null, 2)
);
console.log(chalk.green(`创建package.json文件成功`));
} catch (error) {
console.log(chalk.red(error));
process.exit(1);
}
// install dependencies
install( ["react", "react-dom", "react-scripts", 'web-vitals'], isUsingYarn());
function install(dependencies, useYarn) {
process.chdir(appRoot);
const spawn = require("cross-spawn");
let command;
let args;
if (useYarn) {
command = "yarnpkg";
args = ["add", "--exact", '--production'];
} else {
command = "npm";
args = ["install", "--save", "--save-exact"];
}
args = args.concat(dependencies);
console.log(chalk.green(`开始安装依赖依赖: ${command} ${args.join(" ")}`));
const child = spawn(command, args.concat(dependencies), { stdio: "inherit" });
child.on("close", (code) => {
if (code !== 0) {
console.log(chalk.red("依赖安装失败"));
} else {
console.log(chalk.green(`${dependencies.join(" ")}: 依赖安装成功`));
}
});
}
function isUsingYarn() {
return (process.env.npm_config_user_agent || "").indexOf("yarn") === 0;
}
}());
三、发布到npm
npm login
npm publish
四、本地使用
npx react-cli-codeman test