如何生成属于自己的vue-cli

1. 准备项目

首先,确保您的项目结构和package.json文件已经准备好。

  • 项目结构示例:
my-cli
├── bin
│   └── my-cli.js
├── lib
│   └── commands
│       └── create.js
├── templates
│   └── my-vue-template
│       ├── public
│       ├── src
│       ├── .gitignore
│       ├── package.json
│       └── README.md
├── package.json
└── README.md

各个文件和目录的作用

bin目录: 存放CLI的入口文件。

bin/my-cli.js: CLI的主入口文件,处理命令行输入和执行相应的操作。

lib目录: 存放CLI的业务逻辑代码。

lib/commands/create.js: 处理create命令的业务逻辑代码。

templates目录: 存放项目模板文件。

package.json: npm包的配置文件,包含项目的依赖、命令和其他元数据。

README.md: 项目的说明文档,解释如何使用您的CLI工具。

.gitignore: 指定要忽略的文件和目录,通常用于排除不需要上传到git仓库的文件,如node_modules。

  • package.json示例:
{
  "name": "my-cli",
  "version": "1.0.0",
  "description": "My custom CLI tool for Vue projects",
  "main": "lib/index.js",
  "bin": {
    "my-cli": "./bin/my-cli.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/username/my-cli.git"
  },
  "keywords": [
    "cli",
    "tool",
    "vue"
  ],
  "author": "Your Name",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/username/my-cli/issues"
  },
  "homepage": "https://github.com/username/my-cli#readme",
  "dependencies": {
    "commander": "^8.0.0",
    "ejs": "^3.1.6",
    "fs-extra": "^10.0.0"
  }
}

2. 创建命令行入口文件

创建一个bin/my-cli.js文件,用于处理CLI命令。

  • bin/my-cli.js示例:
#!/usr/bin/env node

const { program } = require('commander');
const create = require('../lib/commands/create');

program
  .version('1.0.0')
  .command('create <project-name>')
  .description('create a new Vue project')
  .action((projectName) => {
    create(projectName);
  });

program.parse(process.argv);

3. 创建命令处理文件

创建一个处理命令的文件,例如lib/commands/create.js。

  • lib/commands/create.js示例:
const fs = require('fs-extra');
const path = require('path');

module.exports = async (projectName) => {
  const projectPath = path.join(process.cwd(), projectName);
  if (fs.existsSync(projectPath)) {
    console.error(`Project ${projectName} already exists`);
    process.exit(1);
  }
  
  const templatePath = path.join(__dirname, '../../templates/my-vue-template');
  
  try {
    await fs.copy(templatePath, projectPath);
    console.log(`Project ${projectName} created at ${projectPath}`);
    console.log('Run the following commands to get started:');
    console.log(`cd ${projectName}`);
    console.log('npm install');
    console.log('npm run serve');
  } catch (err) {
    console.error(err);
  }
};

4. 添加执行权限

chmod +x bin/my-cli.js

5. 登录npm

在终端中登录到npm:

npm login

6. 发布包到npm

将包发布到npm:

npm publish

7. 全局安装和测试

npm install -g my-cli
my-cli create my-project

8.create项目自动执行install和server

修改lib/commands/create.js
更新create.js文件,添加自动执行命令的逻辑:

const fs = require('fs-extra');
const path = require('path');
const { exec } = require('child_process');

module.exports = async (projectName) => {
  const projectPath = path.join(process.cwd(), projectName);
  if (fs.existsSync(projectPath)) {
    console.error(`Project ${projectName} already exists`);
    process.exit(1);
  }

  const templatePath = path.join(__dirname, '../../templates/my-vue-template');

  try {
    await fs.copy(templatePath, projectPath);
    console.log(`Project ${projectName} created at ${projectPath}`);

    // 自动安装依赖
    console.log('Installing dependencies...');
    exec('npm install', { cwd: projectPath }, (error, stdout, stderr) => {
      if (error) {
        console.error(`Error installing dependencies: ${error.message}`);
        return;
      }
      if (stderr) {
        console.error(`npm install stderr: ${stderr}`);
        return;
      }
      console.log(stdout);

      // 自动运行服务器
      console.log('Starting the development server...');
      exec('npm run serve', { cwd: projectPath }, (error, stdout, stderr) => {
        if (error) {
          console.error(`Error starting the server: ${error.message}`);
          return;
        }
        if (stderr) {
          console.error(`npm run serve stderr: ${stderr}`);
          return;
        }
        console.log(stdout);
      });
    });
  } catch (err) {
    console.error(err);
  }
};

更新bin/my-cli.js
确保您的bin/my-cli.js文件是正确的,没有需要修改的地方,但确保其完整性:

#!/usr/bin/env node

const { program } = require('commander');
const create = require('../lib/commands/create');

program
  .version('1.0.0')
  .command('create <project-name>')
  .description('create a new Vue project')
  .action((projectName) => {
    create(projectName);
  });

program.parse(process.argv);

发布和测试

9.创建时询问用户是否需要install和server

  1. 安装inquirer
npm install inquirer
  1. 更新lib/commands/create.js
const fs = require('fs-extra');
const path = require('path');
const { exec } = require('child_process');
const inquirer = require('inquirer');

module.exports = async (projectName) => {
  const projectPath = path.join(process.cwd(), projectName);
  if (fs.existsSync(projectPath)) {
    console.error(`Project ${projectName} already exists`);
    process.exit(1);
  }

  const templatePath = path.join(__dirname, '../../templates/my-vue-template');

  try {
    await fs.copy(templatePath, projectPath);
    console.log(`Project ${projectName} created at ${projectPath}`);

    // 询问用户是否需要安装依赖和启动服务器
    const answers = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'install',
        message: 'Do you want to install dependencies?',
        default: true
      },
      {
        type: 'confirm',
        name: 'serve',
        message: 'Do you want to start the development server?',
        default: true,
        when: (answers) => answers.install
      }
    ]);

    if (answers.install) {
      console.log('Installing dependencies...');
      exec('npm install', { cwd: projectPath }, (error, stdout, stderr) => {
        if (error) {
          console.error(`Error installing dependencies: ${error.message}`);
          return;
        }
        if (stderr) {
          console.error(`npm install stderr: ${stderr}`);
          return;
        }
        console.log(stdout);

        if (answers.serve) {
          console.log('Starting the development server...');
          exec('npm run serve', { cwd: projectPath }, (error, stdout, stderr) => {
            if (error) {
              console.error(`Error starting the server: ${error.message}`);
              return;
            }
            if (stderr) {
              console.error(`npm run serve stderr: ${stderr}`);
              return;
            }
            console.log(stdout);
          });
        }
      });
    } else {
      console.log('You can manually install dependencies by running "npm install" and start the server by running "npm run serve".');
    }
  } catch (err) {
    console.error(err);
  }
};
  1. 确保CLI入口文件正确
#!/usr/bin/env node

const { program } = require('commander');
const create = require('../lib/commands/create');

program
  .version('1.0.0')
  .command('create <project-name>')
  .description('create a new Vue project')
  .action((projectName) => {
    create(projectName);
  });

program.parse(process.argv);
  1. 发布和测试

10.create时发现并未询问或者变化

先uninstall卸载my-cli再重新安装
确认是否sodu

11.多个template,通过询问用户来安装哪一个

  1. 准备模板
    假设您有两个模板,template1和template2,它们存放在templates目录下:
my-cli
├── bin
│   └── my-cli.js
├── lib
│   └── commands
│       └── create.js
├── templates
│   ├── template1
│   │   ├── public
│   │   │   └── index.html
│   │   ├── src
│   │   │   ├── assets
│   │   │   ├── components
│   │   │   ├── App.vue
│   │   │   └── main.js
│   │   ├── .gitignore
│   │   ├── package.json
│   │   └── README.md
│   └── template2
│       ├── public
│       │   └── index.html
│       ├── src
│       │   ├── assets
│       │   ├── components
│       │   ├── App.vue
│       │   └── main.js
│       ├── .gitignore
│       ├── package.json
│       └── README.md
├── package.json
└── README.md
  1. 更新lib/commands/create.js
    修改create.js文件,以便在创建项目时询问用户选择使用哪个模板:
const fs = require('fs-extra');
const path = require('path');
const { exec } = require('child_process');
const inquirer = require('inquirer');

module.exports = async (projectName) => {
  const projectPath = path.join(process.cwd(), projectName);
  if (fs.existsSync(projectPath)) {
    console.error(`Project ${projectName} already exists`);
    process.exit(1);
  }

  // 询问用户选择模板
  const { template } = await inquirer.prompt([
    {
      type: 'list',
      name: 'template',
      message: 'Which template would you like to use?',
      choices: ['template1', 'template2'],
    }
  ]);

  const templatePath = path.join(__dirname, '../../templates', template);

  try {
    await fs.copy(templatePath, projectPath);
    console.log(`Project ${projectName} created using ${template} at ${projectPath}`);

    // 询问用户是否需要安装依赖和启动服务器
    const answers = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'install',
        message: 'Do you want to install dependencies?',
        default: true
      },
      {
        type: 'confirm',
        name: 'serve',
        message: 'Do you want to start the development server?',
        default: true,
        when: (answers) => answers.install
      }
    ]);

    if (answers.install) {
      console.log('Installing dependencies...');
      exec('npm install', { cwd: projectPath }, (error, stdout, stderr) => {
        if (error) {
          console.error(`Error installing dependencies: ${error.message}`);
          return;
        }
        if (stderr) {
          console.error(`npm install stderr: ${stderr}`);
          return;
        }
        console.log(stdout);

        if (answers.serve) {
          console.log('Starting the development server...');
          exec('npm run serve', { cwd: projectPath }, (error, stdout, stderr) => {
            if (error) {
              console.error(`Error starting the server: ${error.message}`);
              return;
            }
            if (stderr) {
              console.error(`npm run serve stderr: ${stderr}`);
              return;
            }
            console.log(stdout);
          });
        }
      });
    } else {
      console.log('You can manually install dependencies by running "npm install" and start the server by running "npm run serve".');
    }
  } catch (err) {
    console.error(err);
  }
};
  1. 确保CLI入口文件正确
    确保bin/my-cli.js文件内容正确,无需修改,但检查其完整性:
#!/usr/bin/env node

const { program } = require('commander');
const create = require('../lib/commands/create');

program
  .version('1.0.0')
  .command('create <project-name>')
  .description('create a new Vue project')
  .action((projectName) => {
    create(projectName);
  });

program.parse(process.argv);
  1. 发布和测试

11.inquirer 报错

inquirer 降版本至8.2.0 重新发包测试

12.my-cli update

修改 CLI 入口文件

#!/usr/bin/env node

const { program } = require('commander');
const path = require('path');
const fs = require('fs');
const create = require('../lib/commands/create');
const update = require('../lib/commands/update');

// 读取 package.json 中的版本号
const packageJsonPath = path.join(__dirname, '../package.json');
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));

program
  .version(pkg.version) // 设置版本号
  .command('create <project-name>')
  .description('create a new Vue project')
  .action((projectName) => {
    create(projectName);
  });

program
  .command('update')
  .description('update the CLI tool')
  .action(() => {
    update();
  });

program.parse(process.argv);

更新 CLI 入口文件
首先,确保您的 CLI 入口文件 bin/my-cli.js 能够处理 update 命令。更新您的 bin/my-cli.js 文件如下:

#!/usr/bin/env node

const { program } = require('commander');
const create = require('../lib/commands/create');
const update = require('../lib/commands/update');

program
  .version('1.0.0')
  .command('create <project-name>')
  .description('create a new Vue project')
  .action((projectName) => {
    create(projectName);
  });

program
  .command('update')
  .description('update the CLI tool')
  .action(() => {
    update();
  });

program.parse(process.argv);

发布新版本
卸载重装

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值