Напишите интерфейсный инструмент для построения лесов, который принадлежит вам

внешний интерфейс Командная строка React.js NPM

Возможно, вы использовали множество инструментов для построения скаффолдинга. Вы когда-нибудь задумывались, как написать скаффолдинг, который принадлежит вам?

Инструменты формирования зависимостей

commander.jsинструмент командной строки

download-git-repoскачать код репозитория git

chalkУлучшение стиля вывода командной строки

Inquirer.jsвзаимодействие с командной строкой

oraЭффект загрузки командной строки

Строительство проекта

Инициализировать проект

Выполнить после создания каталога проектаnpm initСледуйте инструкциям, чтобы завершить проект инициализации.

Установить зависимости

Установите зависимости скаффолдинга, о которых мы упоминали выше, и выполнитеnpm install chalk commander download-git-repo inquirer ora --saveЗаканчивать

Установить.

Структура проекта

После инициализации проекта создайтеbinдокументы иcommandsдокумент. Файл bin — это каталог ввода исполняемых команд, а commands отвечает за запись некоторых командных взаимодействий.

файл react-cli в каталоге bin

#!/usr/bin/env node
process.env.NODE_PATH = __dirname + '/../node_modules/'
const { resolve } = require('path')
const res = command => resolve(__dirname, '../commands/', command)
const program = require('commander')

program.version(require('../package').version )

program.usage('<command>')

program.command('init')
  .option('-f, --foo', 'enable some foo')
  .description('Generate a new project')
  .alias('i')
  .action(() => {
    require(res('init'))
  })

if(!program.args.length){
  program.help()
}

создать этоreact-cli.jsЭто исполняемый файл ввода команды, который определяет команду «инициализация».После выполнения команды он перейдет в каталог команд, чтобы найти соответствующую команду.init.jsдокумент

файл init в каталоге команд

const {prompt} = require('inquirer')
const program = require('commander')
const chalk = require('chalk')
const download = require('download-git-repo')
const ora = require('ora')
const fs = require('fs')
const path = require('path')

const option =  program.parse(process.argv).args[0]
const defaultName = typeof option === 'string' ? option : 'react-project'
const tplList = require(`${__dirname}/../templates`)
const tplLists = Object.keys(tplList) || [];
const question = [
  {
    type: 'input',
    name: 'name',
    message: 'Project name',
    default: defaultName,
    filter(val) {
      return val.trim()
    },
    validate(val) {
      const validate = (val.trim().split(" ")).length === 1
      return validate || 'Project name is not allowed to have spaces ';
    },
    transformer(val) {
      return val;
    }
  }, {
    type: 'list',
    name: 'template',
    message: 'Project template',
    choices: tplLists,
    default: tplLists[0],
    validate(val) {
      return true;
    },
    transformer(val) {
      return val;
    }
  }, {
    type: 'input',
    name: 'description',
    message: 'Project description',
    default: 'React project',
    validate (val) {
      return true;
    },
    transformer(val) {
      return val;
    }
  }, {
    type: 'input',
    name: 'author',
    message: 'Author',
    default: 'project author',
    validate (val) {
      return true;
    },
    transformer(val) {
      return val;
    }
  }
]
module.exports = prompt(question).then(({name, template, description, author}) => {
  const projectName = name;
  const templateName = template;
  const gitPlace = tplList[templateName]['place'];
  const gitBranch = tplList[templateName]['branch'];
  const spinner = ora('Downloading please wait...');
  spinner.start();
  download(`${gitPlace}${gitBranch}`, `./${projectName}`, (err) => {
    if (err) {
      console.log(chalk.red(err))
      process.exit()
    }
    fs.readFile(`./${projectName}/package.json`, 'utf8', function (err, data) {
      if(err) {
        spinner.stop();
        console.error(err);
        return;
      }
      const packageJson = JSON.parse(data);
      packageJson.name = name;
      packageJson.description = description;
      packageJson.author = author;
      var updatePackageJson = JSON.stringify(packageJson, null, 2);
      fs.writeFile(`./${projectName}/package.json`, updatePackageJson, 'utf8', function (err) {
        if(err) {
          spinner.stop();
          console.error(err);
          return;
        } else {
          spinner.stop();
          console.log(chalk.green('project init successfully!'))
          console.log(`
            ${chalk.bgWhite.black('   Run Application  ')}
            ${chalk.yellow(`cd ${name}`)}
            ${chalk.yellow('npm install')}
            ${chalk.yellow('npm start')}
          `);
        }
      });
    });
  })
})

1.program.parse(process.argv)Параметры, переданные при выполнении init, могут быть проанализированы.Мы можем получить этот параметр как имя каталога, созданного проектом.Если этот параметр не передается, установите для него имя каталога по умолчанию.

2.Интерактивные вопросы и ответы в командной строке

  • questionМассив настроен на интерактивные команды, и каждый объект в массиве соответствует проблеме при выполнении команды
  • typeдля типа вопроса,nameДля имени вопроса пользователь, который может получить вопрос через имя, позже вводит ответ.
  • messageподсказки к вопросам
  • defaultпредоставлять ответ пользователю по умолчанию, когда он не вводит
  • validateМетод может проверить содержимое, введенное пользователем. Если он возвращает true, проверка пройдена. Если он неверен, он может вернуть соответствующий строковый текст подсказки.
  • transformerПосле того, как пользователь вводит ответ на вопрос, соответствующий ответ отображается на позиции вопроса, и требуется возвращаемое значение, а возвращаемая строка является отображаемым содержимым.специальная документация

3.Обратный звонок по окончании вопросов и ответов

  • Параметр в методе приглашения представляет собой объект, из которого вы можете получить содержимое пользовательского ввода, определяемое именем вопроса.
  • В соответствии с содержимым, введенным пользователем, для него может быть сгенерирован шаблон загрузки, который используется здесь.download-git-repoИнструмент для загрузки кода репозитория git
  • Первым параметром метода загрузки является местоположение загружаемого репозитория кода.Если это репозиторий кода GitHub, вам нужно только написать имя пользователя и имя проекта, например'Hzy0913/react-template'То есть загрузить код мастера склада.Если вам нужно переключить соответствующую ветку, добавьте название соответствующей ветки после адреса склада, например'Hzy0913/react-template#complete'.
  • Вторым параметром метода загрузки является имя файла сгенерированного файла загрузки. Я сохраняю его в каталоге выполнения команды. В имени файла используется имя, введенное пользователем. Например, параметр'./projectName', Для генерации соответствующего имени файла в текущем каталоге выполняют команду.
  • oraМодуль может генерировать вращающийся значок для нас при загрузке.Первый параметр, передаваемый методом ora, — это подсказка при ожидании и создании экземпляра.Вызовите метод start() для объекта экземпляра, чтобы запустить вращающуюся анимацию и подсказку, и метод stop() останавливается.
  • После загрузки шаблона его необходимоpackage.jsonФайл генерирует определяемый пользователем входной контент, узлыfsмодульныйreadFileметод может помочь нам получить содержимое сгенерированного файла,writeFileтогда вы можете написать контент
  • После окончательного завершения вы можете использовать консольный метод на панели командной строки, чтобы дать некоторые подсказки,chalkМодули могут помочь нам украсить наш вывод.

Пример кода скаффолдинга в статье можно увидетьbuild-react-cli

Тестирование и выпуск инструмента

  • В процессе написания неизбежно тестирование локально, потому что сам проект является инструментом node, мы можем выполнить его в каталоге проекта.node bin/react-cliбегать.
  • Конечно, эту команду нельзя использовать после публикации, в это время перед публикацией добавьтеpackage.jsonсерединаbinObject, Key — имя, исполняемое сценарием, а Value — каталог выполнения, например"bin": {"build-react": "bin/react-cli"}, что эквивалентно выполнению при входе в build-reactnode bin/react-cliКоманда, когда мы устанавливаем скаффолдинг глобально, содержимое объекта bin может стать глобальной исполняемой командой.
  • Публикация пакетов npm.Публиковать пакеты npm очень просто.После регистрации учетной записи npm вы можете войти в систему локально и выполнить ее в каталоге проекта.npm publishВы можете опубликовать его. Обратите внимание, что имя пакета не может совпадать с именем в существующем npm. Его необходимо изменять каждый раз, когда выпускается новая версия пакета.package.jsonНомер версии в опубликованном пакете можно удалить только в течение 24 часов.

Наконец, я рекомендую два инструмента для создания лесов, которые я пишу.

Build-React-CLI - помочь вам быстро создать инструмент для лесов, который генерирует проект React, настраивает множество необязательных различных типов шаблонов проекта.

Сверхпростое междоменное, внешнее и внутреннее решение LiveNode для междоменного разделения