Создание фасадных строительных лесов с нуля

внешний интерфейс Командная строка JavaScript Yeoman

Vue.js — одна из самых популярных интерфейсных сред, поэтому разработка компонента на основе Vue.js — это желание каждого фронтенда. Каждый раз, когда вы разрабатываете новый компонент Vue.js, вы делаете следующее:

  • Создать каталог проекта
  • инициализация git
  • инициализация нпм
  • Создайте среду разработки
    • Проверка грамматики
    • компиляция кода
    • упаковка кода
    • Локальный предварительный просмотр и горячая перезагрузка
  • Создайте производственную среду
    • Проверка грамматики
    • компиляция кода
    • Упаковка и сжатие кода
  • Конфигурация непрерывной интеграции

Так почему бы не извлечь эти задания и не позволить ему генерировать их одним щелчком мыши? В настоящее время существует множество инструментов для генерации в один клик, таких какyeomanЖдать. Пакет строительных лесов yoman должен быть предоставлен для создания проекта с помощью yoman. Пакет строительных лесов yeoman по сути представляет собой шаблон проекта с полной файловой структурой.Пользователям необходимо вручную загрузить эти пакеты строительных лесов на локальный сервер, после чего yeoman автоматически создаст различные проекты на основе этих пакетов строительных лесов.

yoman прост в использовании, но добавить еще один шаг всегда проблематично, и вам нужно загрузить пакет поддержки. Популярна на рынке и технология cli, то есть шаблон удаленного склада подтягивается к локальному по некоторым конфигурациям. Судя по всему с модом кли все в порядке, качать не надо. На основе этого принципа мы построилиfecliстроительных лесов.

стек технологий

  • Среда разработки: OS X El Capitan 10.11.6
  • Инструменты разработки:Atom
  • Node.js: Рабочая среда всех строительных лесов. Версия этого каркаса для Node.js: 9.11.1.
  • es6: Новый синтаксис для JavaScript.
  • commander: Инструмент, разработанный TJ для лучшей организации и обработки ввода командной строки. Командирский вариант этой лески: 2.15.1.
  • co: Инструмент управления асинхронным потоком. Совместная версия этого скаффолдинга: 4.6.0.
  • co-prompt: Пошаговый прием пользовательского ввода. Совместная версия этого скаффолда: 1.0.0.
  • chalk: красочный терминальный инструмент. меловая версия этой лески: 2.3.2.
  • ora: Элегантный счетчик терминала, который может управлять выводом терминала. Версия ora этого скаффолдинга: 2.0.0.

ядро проекта

Схема, иллюстрирующая общую архитектуру. ⤵️

fecli 架构图

О шаблонах

шаблонЭто то, что будет снесено в будущем. Этот шаблон часто содержит некоторую конфигурацию среды, конфигурацию обнаружения синтаксиса, конфигурацию модульного теста, конфигурацию непрерывной интеграции и т. д.

Информация о шаблоне будет храниться вtemplates.jsonв файле. Пользователи также могут работать с помощью некоторых командtemplates.jsonсодержание в .

Файловая структура скаффолдинга

.
├── bind/                     # 运行命令的入口文件
│   └── ...
├── lib/                      # 核心代码
│   ├── table.js              # 模板列表表格形式的封装
│   ├── tip.js                # 终端提示信息的封装
│   ├── cli/                  # 命令管理
│   │   └── ...
│   └── cmd/                  # 命令操作
│   │   └── ...
├── public/                   # 命令预览
│   └── ...
└── templates.json            # 模板管理

Настроить глобальное использование

создать новый каталогmkdir fecliи введитеcd fecli. Затем npm инициализирует егоnpm init. Чтобы быть доступными по всему миру, нам нужноpackage.jsonУстановите его внутри:

"bin": {
  "fe": "./bin/fe.js"
},

При локальной отладке выполняйте в корневом каталоге проекта:npm link.
положитьfecliКоманда привязана к глобальной и может быть использована напрямую в будущем.feначать с команды.

Параметры файла ввода

Запишите зависимости в package.json и выполнитеnpm installилиyarn install:

"dependencies": {
  "chalk": "^2.3.2",
  "co": "^4.6.0",
  "co-prompt": "^1.0.0",
  "commander": "^2.15.1",
  "ora": "^2.0.0"
}

Создал в корневом каталоге\binпапку, создайтеfe.jsдокумент. этоbin/fe.jsФайл является входным файлом для всего скаффолдинга, поэтому давайте сначала напишем его.

Первый — это некоторый код инициализации, очень просто обратиться к файлу, управляемому командой (lib/cli/index.js):

require('../lib/cli/');

командное управление (lib/cli/index.js)

Сначала некоторые вещи инициализации:

const program = require('commander');
const packageInfo = require('../../package.json');


program
    .version(packageInfo.version)

мы проходимcommanderдля установки различных команд.commandМетод заключается в установке имени команды.descriptionМетод заключается в установке описания.aliasМетод задается сокращенно.actionСпособ - установить обратный вызов.

program
    .command('init') // fe init
    .description('生成一个项目')
    .alias('i') // 简写
    .action(() => {
      require('../cmd/init')();
    });

program
    .command('add') // fe add
    .description('添加新模板')
    .alias('a') // 简写
    .action(() => {
      require('../cmd/add')();
    });

program
    .command('list') // fe list
    .description('查看模板列表')
    .alias('l') // 简写
    .action(() => {
      require('../cmd/list')();
    });

program
    .command('delete') // fe delete
    .description('查看模板列表')
    .alias('d') // 简写
    .action(() => {
      require('../cmd/delete')();
    });

Если аргументов нет, запустите вспомогательный метод. Далее следует разбор аргументов в program.args :

program.parse(process.argv);

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

бегатьfeРезультат после:

运行 fe 结果

commanderКонкретный метод использования не будет здесь раскрываться, вы можете перейти непосредственно кОфициальный сайтСм. подробную документацию.

Обработка пользовательского ввода

Установлено в соответствии с корневым каталогом проекта/lib/cmdПапка, специально используемая для хранения файлов обработки команд.
Создал в корневом каталогеtemplates.jsonфайл и напишите следующее содержимое для хранения информации о шаблоне:

{"tpl":{}}

Добавьте шаблон (fe add)

Перейдите в /lib/cmd и создайте новыйadd.jsдокумент.

'use strict'
const co = require('co');
const prompt = require('co-prompt');
const fs = require('fs');

const table = require('../table');
const tip = require('../tip');
const tpls = require('../../templates');

const writeFile = (err) => {
  // 处理错误
  if (err) {
    console.log(err);
    tip.fail('请重新运行!');
    process.exit();
  }

  table(tpls);
  tip.suc('新模板添加成功!');
  process.exit();
};

const resolve = (result) => {
  const { tplName, gitUrl, branch, description, } = result;
  // 避免重复添加
  if (!tpls[tplName]) {
    tpls[tplName] = {};
    tpls[tplName]['url'] = gitUrl.replace(/[\u0000-\u0019]/g, ''); // 过滤unicode字符
    tpls[tplName]['branch'] = branch;
    tpls[tplName]['description'] = description;
  } else {
    tip.fail('模板已经存在!');
    process.exit();
  };

  // 把模板信息写入templates.json
  fs.writeFile(__dirname + '/../../templates.json', JSON.stringify(tpls), 'utf-8', writeFile);
};

module.exports = () => {
  co(function *() {
    // 分步接收用户输入的参数
    const tplName = yield prompt('模板名字: ');
    const gitUrl = yield prompt('Git https 链接: ');
    const branch = yield prompt('Git 分支: ');
    const description = yield prompt('模板描述: ');
    return new Promise((resolve, reject) => {
      resolve({
        tplName,
        gitUrl,
        branch,
        description,
      });
    });
  }).then(resolve);
};

удалить шаблон (fe delete)

Перейдите в /lib/cmd и создайте новыйdelete.jsдокумент.

'use strict'
const co = require('co');
const prompt = require('co-prompt');
const fs = require('fs');

const table = require('../table');
const tip = require('../tip');
const tpls = require('../../templates');

const writeFile = (err) => {
  if (err) {
    console.log(err);
    tip.fail('请重新运行!');
    process.exit();
  }
  tip.suc('新模板删除成功!');

  if (JSON.stringify(tpls) !== '{}') {
    table(tpls);
  } else {
    tip.info('还未添加模板!');
  }

  process.exit();
};

const resolve = (tplName) => {
  // 删除对应的模板
  if (tpls[tplName]) {
    delete tpls[tplName];
  } else {
    tip.fail('模板不经存在!');
    process.exit();
  }

  // 写入template.json
  fs.writeFile(__dirname + '/../../templates.json', JSON.stringify(tpls), 'utf-8', writeFile);
};

module.exports = () => {
  co(function *() {
    // 分步接收用户输入的参数
    const tplName = yield prompt('模板名字: ');
    return new Promise((resolve, reject) => {
      resolve(tplName);
    });
  }).then(resolve);
};

Инициализировать проект (fe init)

Перейдите в /lib/cmd и создайте новыйinit.jsдокумент.

'use strict'
// 操作命令行
const exec = require('child_process').exec;
const co = require('co');
const ora = require('ora');
const prompt = require('co-prompt');

const tip = require('../tip');
const tpls = require('../../templates');

const spinner = ora('正在生成...');

const execRm = (err, projectName) => {
  spinner.stop();

  if (err) {
    console.log(err);
    tip.fail('请重新运行!');
    process.exit();
  }

  tip.suc('初始化完成!');
  tip.info(`cd ${projectName} && npm install`);
  process.exit();
};

const download = (err, projectName) => {
  if (err) {
    console.log(err);
    tip.fail('请重新运行!');
    process.exit();
  }
  // 删除 git 文件
  exec('cd ' + projectName + ' && rm -rf .git', (err, out) => {
    execRm(err, projectName);
  });
}

const resolve = (result) => {
  const { tplName, url, branch, projectName, } = result;
  // git命令,远程拉取项目并自定义项目名
  const cmdStr = `git clone ${url} ${projectName} && cd ${projectName} && git checkout ${branch}`;

  spinner.start();

  exec(cmdStr, (err) => {
    download(err, projectName);
  });
};

module.exports = () => {
 co(function *() {
    // 处理用户输入
    const tplName = yield prompt('模板名字: ');
    const projectName = yield prompt('项目名字: ');

    if (!tpls[tplName]) {
      tip.fail('模板不存在!');
      process.exit();
    }

    return new Promise((resolve, reject) => {
      resolve({
        tplName,
        projectName,
        ...tpls[tplName],
      });
    });
  }).then(resolve);
}

Показать список шаблонов (fe list)

Перейдите в /lib/cmd и создайте новыйlist.jsдокумент.

'use strict'
const table = require('../table');

module.exports = () => {
  table(require('../../templates'));
  process.exit();
};

Теперь нашfecliИнструмент для строительных лесов создан, давайте попробуем вместе!

использовать тест

  • fe addДобавить шаблон

fe add 运行结果

  • fe deleteДобавить шаблон

fe delete 运行结果

  • fe listДобавить шаблон

fe list 运行结果

  • fe initДобавить шаблон

fe init 运行结果

Исходный код проекта

Для получения дополнительной информации об источнике, пожалуйста, переместитеfecli.