5-4 项目创建 + 模板下载

1 脚手架初始化项目模板开发

1.1 手动创建项目模板

mkdir zmoon-cli-dev-template
cd ./zmoon-cli-dev-template
npm init -y
mkdir zmoon-cli-dev-template-vue3
cd ./zmoon-cli-dev-template-vue3
mkdir template
cd ./template
vue create vue-test[vue3 default]
## 删除旁支文件[node_modules .git等]
cd ../ 
## zmoon-cli-dev-template-vue3 目录下发布包
npm publish

1.2 基于 vue-element-admin 开发通用的中后台项目模板

  • zmoon-cli-dev-template>zmoon-cli-dev-template-vue-element-admin>template
  • zmoon-cli-dev-template-vue-element-admin 目录下 npm publish

2 脚手架请求项目模板 API 开发

2.1 脚手架请求项目模板 API 开发

1. 修改数据库数据

{
  "_id" : ObjectId("638083ff03e979ad500afd50"),
  "name": "vue3标准模板",
  "npmName": "zmoon-cli-dev-template-vue3",
  "version": "^1.0.0"
}
{
  "_id" : ObjectId("638083ff03e979ad500afd50"),
  "name": "vue-element-admin模板",
  "npmName": "zmoon-cli-dev-template-vue-element-admin",
  "version": "^1.0.0"
}

2. 新建功能包 utils>request

'use strict';

const axios = require('axios')
const BASE_URL = process.env.ZMOON_CLI_BASE_URL ?? 'http://book.zmoon-cli-dev-server.com:7002'
const request = axios.create({
  baseURL: BASE_URL,
  timeout: 5000
})
request.interceptors.response.use(
  response => response.data,
  error => Promise.reject(error)
)
module.exports = request;

3. 新建文件使用 request 功能

  • commands>init>lib>getProjectTemplate
const request = require('@zmoon-cli-dev/request')
module.exports = function() {
  request({
    url: '/project/template'
  })
}

4. 准备阶段判断模板是否存在

  • commands>init>lib>index
async prepare() {
  // 0. 判断项目模板是否存在
  const template = await getProjectTemplate()
  if(!template || template.length === 0) {
    throw new Error('项目模板不存在')
  }
  this.template = template
  // ...
}

2.2 通过环境变量配置默认URL + 选择项目模板功能开发

1. 通过环境变量配置默认URL

  • set ZMOON_CLI_BASE_URL=http://book.zmoon-cli-dev-server.com:7002

2. 获取项目信息--选择项目模板

async getProjectInfo() {
  let projectInfo = {}
  // 1. 选择创建项目或组件...
  if(type === TYPE_PROJECT) {
    // 2. 获取项目的基本信息
    const project = await inquirer.prompt([
      // ...
      {
        type: 'list',
        name: 'projectTemplate',
        message: '请选择项目模板',
        choices: this.createTemplateChoice()
      }
    ])
    projectInfo = {
      type,
      ...project
    }
  }
  // return 项目的基本信息 object
  return projectInfo
}
createTemplateChoice() {
  return this.template.map(item => ({
    value: item.npmName,
    name: item.name
  }))
}

3 脚手架下载项目模板功能开发

3.1 回顾准备工作

通过项目模板API获取项目模板信息

获取模板数据this.template + 获取项目模板信息

  1. 通过egg.js搭建一套后台系统
  2. 通过npm存储项目模板(vue-cli/vue-element-admin)
  3. 将项目模板信息存储到mongodb数据库中
  4. 通过egg.js获取mongodb中的数据并通过API返回

3.2 脚手架下载项目模板功能开发

  • commands>init>lib>index
async downloadTemplate() {
  const { projectTemplate } = this.projectInfo
  const templateInfo = this.template.find(item => item.npmName === projectTemplate)
  const targetPath = path.resolve(userHome, '.zmoon-cli-dev', 'template') 
  const storeDir = path.resolve(userHome, '.zmoon-cli-dev', 'template', 'node_modules')
  const { npmName, version } = templateInfo
  const templateNpm = new Package({
    targetPath, // package的目标路径
    storeDir, // 缓存package的路径
    packageName: npmName,
    packageVersion: version
  })
  if(!await templateNpm.exists()) {
    await templateNpm.install()
  } else {
    await templateNpm.update()
  }
}

3.3 通过 spinner 实现命令行 loading 效果

1. utils工具文件使用 cli-spinner

  • utils>utils>lib>index
function spinnerStart(msg, spinnerString = '|/-\\') {
  const Spinner = require('cli-spinner').Spinner;
  const spinner = new Spinner(msg + '%s');
  spinner.setSpinnerString(spinnerString);
  spinner.start();
  return spinner
}

function sleep(timeout = 1000) {
  return new Promise(resolve => setTimeout(resolve, timeout))
}

2. 模板下载函数中使用

  • commands>init>lib>index
async downloadTemplate() {
  // ...
  if(!await templateNpm.exists()) {
    const spinner = spinnerStart('正在下载模板...')
    await sleep()
    await templateNpm.install()
    spinner.stop(true)
    log.success('下载模板成功')
  } else {
    const spinner = spinnerStart('正在更新模板...')
    await sleep()
    await templateNpm.update()
    spinner.stop(true)
    log.success('更新模板成功')
  }
}

3.4 功能调试

async downloadTemplate() {
  // ...
  if(!await templateNpm.exists()) {
    const spinner = spinnerStart('正在下载模板...')
    await sleep()
    try {
      await templateNpm.install()
      log.success('下载模板成功')
    } catch(e) {
      throw e
    } finally {
      spinner.stop(true)
    }
  } else {
    const spinner = spinnerStart('正在更新模板...')
    await sleep()
    try {
      await templateNpm.update()
      log.success('更新模板成功')
    } catch(e) {
      throw e
    } finally {
      spinner.stop(true)
    }
  }
}
posted on 2022-12-30 11:33  pleaseAnswer  阅读(26)  评论(0编辑  收藏  举报