Создайте свои собственные леса, такие как vue-cli

Vue.js
Создайте свои собственные леса, такие как vue-cli

что такое строительные леса

Раньше я всегда думал, что строительные леса — это очень высокоуровневая вещь, и казалось, что кто-то, у кого есть немного вилки, может это написать, но это было недосягаемо. На самом деле мы сдаемся не из-за трудностей, а потому что сдаваться сложно (это хорошее слово и предложение 🙈). Если вы готовы потратить полтора дня✊, вы также можете написать свои собственные леса.
Ранее слово scaffolding было известно из vue-cli, и мы прошлиnpm install -g vue-cliПосле команды глобальной установки строительных лесов выполнитьvue init webpack project-nameВы можете инициализировать свой собственный проект, что и является магией Нимы 😯. Но задумывались ли вы когда-нибудь, почему мы исполняемvue initЭта команда может иметь свой собственный проект. Сегодня давайте вместе раскроем истинное лицо Лушаня!
Подождите ✋, это куча дерьма, вы, кажется, не сказали, что такое строительные леса? эммм... Это инструмент, который нам удобен для создания новых проектов.С этим проектом мы можем напрямую его развивать. На самом деле, мы могли бы использоватьgit clone urlЧтобы создать новый (копировать) проект, наиболее удобным методом является копирование и вставка всей папки, что также может достичь цели инициализации. Суть скаффолдинга заключается в загрузке шаблона из удаленного места для нового проекта. Лоб. так. . . Какая разница? Только выше 😧. Конечно, на этом Scaffolding — это клон расширенной версии, в основном он предоставляет интерактивные команды, чтобы мы могли динамически изменять шаблон, а затем сделать это раз и навсегда одной командой (конечно, его еще нужно поддерживать) Это должно быть самое главное отличие, во всяком случае, это то, что я думаю сейчас 😢.
Что ж, цель этой главы — помочь вам написать упрощенную версию скаффолдинга xr-cli (как бы она ни называлась).xr init template-name project-nameТакой порядок, прекращайте нести чушь, и начинайте переходить к делу 🚀🚀🚀.

Адрес источника:GitHub.com/Lugouqiao627628/Малый…

Предварительное знание

На самом деле простая версия xr-cli не имеет большого количества кода, поэтому здесь мы кратко представим пакеты, от которых она зависит.Если вы пользовались этими инструментами, то можете ее пропустить.Если не пользовались, то обязательно посмотреть .

commander

Это используется для написания инструкций и обработки командной строки, конкретное использование выглядит следующим образом:

const program = require("commander");
// 定义指令
program
  .version('0.0.1')
  .command('init', 'Generate a new project from a template')
  .action(() => {
    // 回调函数
  })
// 解析命令行参数
program.parse(process.argv);

Напомним, что мы использовалиvue initКоманда объявлена ​​как таковая.

inquirer

Это мощный интерактивный инструмент командной строки, конкретное использование которого заключается в следующем:

const inquirer = require('inquirer');
inquirer
  .prompt([
    // 一些交互式的问题
  ])
  .then(answers => {
    // 回调函数,answers 就是用户输入的内容,是个对象
  });

Представьте, что мы используемvue init webpack project-nameПосле этого будет несколько интерактивных вопросов, спрашивая вас о названии файла, авторе, описании, использовать ли eslint и т.д. и т.п. Это используется для записи.

chalk

Это используется для изменения стиля содержимого вывода консоли, например цвета. Конкретное использование выглядит следующим образом:

const chalk = require('chalk');
console.log(chalk.green('success'));
console.log(chalk.red('error'));

ora

Это красивая загрузка, то есть при загрузке будет круговой эффект.Использование следующее:

const ora = require('ora')
let spinner = ora('downloading template ...')
spinner.start()

download-git-repo

Название очевидно, оно используется для загрузки удаленных шаблонов, поддерживает GitHub, GitLab и Bitbucket и т. д. Использование выглядит следующим образом:

const download = require('download-git-repo')
download(repository, destination, options, callback)

Где репозиторий — это адрес удаленного хранилища; пункт назначения — это путь к файлу, в котором хранится загруженный файл, или вы можете напрямую написать имя файла, по умолчанию — текущий каталог; параметры — это некоторые параметры, такие как{ clone:boolean }Указывает, следует ли загружать в виде http-загрузки или клонирования git.

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

хорошо, после того, как у нас будет вышеуказанный запас знаний, мы официально начнем мастурбировать.

  1. Сначала нам нужно создать папку и назвать ее xr-cli;
  2. Выполнить в этом каталогеnpm initКоманда (у вас должна быть установлена ​​нода 😂), нажимайте Enter до упора, будет сгенерирован сгенерированный файл package.json, пропишите следующие зависимости в package.json и выполнитеnpm installУстановите следующим образом:
"dependencies": {
    "chalk": "^2.4.2",
    "commander": "^2.19.0",
    "download-git-repo": "^1.1.0",
    "inquirer": "^6.2.2",
    "ora": "^3.2.0"
}
  1. Создайте новую папку bin и создайте новый файл xr без суффикса в каталоге bin и напишите:
#!/usr/bin/env node
console.log('hello');

Этот файл является входным файлом всех наших лесов, мы используемnode ./bin/xrЗапустив его, вы можете вывести hello на консоль, как показано ниже:Здесь мы должны отметить в начале#!/usr/bin/env nodeЭтот оператор должен быть добавлен, в основном для того, чтобы, когда система увидит эту строку, она искала узел по пути и выполняла его, в основном для совместимости с Mac и обеспечения исполняемости.

инициализация каталога bin

В настоящее время в каталоге bin есть только один файл, который является файлом записи xr. Итак, теперь давайте сначала напишем этот файл.Поскольку контента меньше, давайте посмотрим непосредственно на код:

#!/usr/bin/env node
const program = require('commander')

// 定义当前版本
// 定义使用方法
// 定义四个指令
program
  .version(require('../package').version)
  .usage('<command> [options]')
  .command('add', 'add a new template')
  .command('delete', 'delete a template')
  .command('list', 'list all the templates')
  .command('init', 'generate a new project from a template')
  
// 解析命令行参数
program.parse(process.argv)

Основная функция этого файла — определение инструкций, сейчас мы используемnode ./bin/xrЗапустите его, и вы увидите следующие результаты:Конечно, вам может казаться, что каждый раз, когда вы печатаетеnode ./bin/xrЭтот порядок немного проблематичен, это не имеет значения, мы можем написать в Package.json было удалено:

// bin 用来指定每个命令所对应的可执行文件的位置
"bin": {
    "xr": "bin/xr"
}

Затем выполните в корневом каталогеnpm link(Это означает монтировать команду в глобальную), чтобы каждый раз, когда мы вводим xr, мы могли запускать ее напрямую, так здорово, как показано ниже:Немного не похоже 😁😁😁, тогда продолжим улучшать каталог bin! Хорошо, давайте создадим еще четыре файла в каталоге bin, соответствующих четырем инструкциям выше, а затем обработаем то, что должно быть сделано с помощью четырех инструкций соответственно, как показано ниже:Точно так же давайте изменим содержимое корзины в package.json следующим образом:

"bin": {
    "xr": "bin/xr",
    "xr-add": "bin/xr-add",
    "xr-delete": "bin/xr-delete",
    "xr-list": "bin/xr-list",
    "xr-init": "bin/xr-init"
}

затем выполнитьnpm unlinkОтмените привязку глобальной команды и выполните ее снова.npm linkПовторно привяжите команду к глобальной, например:Наконец, кстати, создайте новый файл template.json в корневом каталоге, а содержимое в нем представляет собой{}.

Напишите конкретные инструкции

Что ж, все готово, давайте запишем четыре конкретных инструкции.

xr-add

Этот контент также относительно невелик, посмотрите прямо на код:

#!/usr/bin/env node

// 交互式命令行
const inquirer = require('inquirer')
// 修改控制台字符串的样式
const chalk = require('chalk')
// node 内置文件模块
const fs = require('fs')
// 读取根目录下的 template.json
const tplObj = require(`${__dirname}/../template`)

// 自定义交互式命令行的问题及简单的校验
let question = [
  {
    name: "name",
    type: 'input',
    message: "请输入模板名称",
    validate (val) {
      if (val === '') {
        return 'Name is required!'
      } else if (tplObj[val]) {
        return 'Template has already existed!'
      } else {
        return true
      }
    }
  },
  {
    name: "url",
    type: 'input',
    message: "请输入模板地址",
    validate (val) {
      if (val === '') return 'The url is required!'
      return true
    }
  }
]

inquirer
  .prompt(question).then(answers => {
    // answers 就是用户输入的内容,是个对象
    let { name, url } = answers;
    // 过滤 unicode 字符
    tplObj[name] = url.replace(/[\u0000-\u0019]/g, '')
    // 把模板信息写入 template.json 文件中
    fs.writeFile(`${__dirname}/../template.json`, JSON.stringify(tplObj), 'utf-8', err => {
      if (err) console.log(err)
      console.log('\n')
      console.log(chalk.green('Added successfully!\n'))
      console.log(chalk.grey('The latest template list is: \n'))
      console.log(tplObj)
      console.log('\n')
    })
  })

Основное назначение этого файла - добавление шаблонов и их хранение.Комментарии выше должны быть четко написаны. мы выступаемxr addПосмотрим на эффект:Имя шаблона здесь (понимайте как хотите) эквивалентноvue init webpack project-nameсредиwebpack; Обратите внимание на адрес шаблона, его можно написать так, вот пример github:добавить сюдаxr addКак соответствовать xr-add: мы определили ранееprogram.command('add').action(() => {})Когда мы не написали функцию обратного вызова действия, и когда мы выполнилиxr add, командир попытается найти исполняемые файлы в директории скрипта входа и найтиprogram-command(вотxr-add) команда для выполнения, вероятно, означает, что следующая команда является той же причиной.

xr-delete

Если вы понимаете вышеописанный шаг, этот шаг тоже должен быть для вас окроплен! Над кодом:

#!/usr/bin/env node

const inquirer = require('inquirer')
const chalk = require('chalk')
const fs = require('fs')
const tplObj = require(`${__dirname}/../template`)

let question = [
  {
    name: "name",
    message: "请输入要删除的模板名称",
    validate (val) {
      if (val === '') {
        return 'Name is required!'
      } else if (!tplObj[val]) {
        return 'Template does not exist!'
      } else  {
        return true
      }
    }
  }
]

inquirer
  .prompt(question).then(answers => {
    let { name } = answers;
    delete tplObj[name]
    // 更新 template.json 文件
    fs.writeFile(`${__dirname}/../template.json`, JSON.stringify(tplObj), 'utf-8', err => {
      if (err) console.log(err)
      console.log('\n')
      console.log(chalk.green('Deleted successfully!\n'))
      console.log(chalk.grey('The latest template list is: \n'))
      console.log(tplObj)
      console.log('\n')
    })
  })

Это должно быть хорошо понято, поэтому я не буду слишком много объяснять, давайте выполним его напрямую.xr deleteВзгляните на эффект:

xr-list

Это проще, с двумя строками кода:

#!/usr/bin/env node

const tplObj = require(`${__dirname}/../template`)
console.log(tplObj)

Разве это не достаточно просто, чтобы взорваться 💥. мы выступаемxr listВзгляните на эффект:Поскольку в настоящее время шаблона нет, он выводится сразу после его добавления и удаления.{}.

xr-init

Это должен быть самый важный (но не сложный) шаг, ведь мы еще не инициализировали проект через команды😭. Таким образом, целью этого шага является реализацияdownloadметод и передать соответствующие параметры, подробности см. в коде:

#!/usr/bin/env node

const program = require('commander')
const chalk = require('chalk')
const ora = require('ora')
const download = require('download-git-repo')
const tplObj = require(`${__dirname}/../template`)

program
  .usage('<template-name> [project-name]')
program.parse(process.argv)
// 当没有输入参数的时候给个提示
if (program.args.length < 1) return program.help()

// 好比 vue init webpack project-name 的命令一样,第一个参数是 webpack,第二个参数是 project-name
let templateName = program.args[0]
let projectName = program.args[1]
// 小小校验一下参数
if (!tplObj[templateName]) {
  console.log(chalk.red('\n Template does not exit! \n '))
  return
}
if (!projectName) {
  console.log(chalk.red('\n Project should not be empty! \n '))
  return
}

url = tplObj[templateName]

console.log(chalk.white('\n Start generating... \n'))
// 出现加载图标
const spinner = ora("Downloading...");
spinner.start();
// 执行下载方法并传入参数
download (
  url,
  projectName,
  err => {
    if (err) {
      spinner.fail();
      console.log(chalk.red(`Generation failed. ${err}`))
      return
    }
    // 结束加载图标
    spinner.succeed();
    console.log(chalk.green('\n Generation completed!'))
    console.log('\n To get started')
    console.log(`\n    cd ${projectName} \n`)
  }
)

ок, выполнимxr init simple test, не забудьте выполнить его первымxr add:Теперь мы можем видеть тестовый проект в каталоге слева, как показано ниже:На этом этапе делаются небольшие подмости. 🌹🌹🌹Здесь должны быть цветы и аплодисменты👏👏👏

Опубликовать в нпм

Теперь, когда вышеуказанные команды были успешно выполнены, давайте опубликуем это в npm (напишите все, не тратьте зря 😬).

  • Удалите тестовую папку, она используется для локального тестирования, а когда она израсходуется, выбросьте ее (конечно, люди не могут этого сделать)
  • Создайте новый файл README.md в корневом каталоге, напишите несколько инструкций и притворитесь серьезным
  • Создайте новый файл .npmignore в корневом каталоге и напишите/node_modules, что означает игнорировать папку node_modules при публикации,
  • Перейдите на официальный сайт npm, чтобы зарегистрировать учетную запись (очень просто), и найдите имя xr-cli, чтобы узнать, использует ли его кто-нибудь.

Теперь вернемся в корневой каталог проекта и выполнимnpm loginВойдите в свою учетную запись npm и выполнитеnpm publishОпубликовать вот так:Все верно, вот только эти две простые команды, и мы ее успешно выпустили, что очень радует 🍺🍺🍺. Примерно через минуту или около того (во всяком случае, очень быстро) мы заходим на официальный сайт npm и ищем xr-cli, и мы видим наши строительные леса, хахахаха, вор счастлив 👍👍👍.

Вот дополнительное примечание: Согласно спецификации, выпущенный пакет можно отозвать только в течение 24 часов после выпуска пакета, поэтому, чтобы не загрязнять веб-сайт npm, если это только тест, выполните егоnpm unpublish --forceУдалите его, ведь все мы люди качественные.

Мелкий измельчитель

Не волнуйтесь, это еще не конец 🙅‍♀️. Волосы были отправлены, и они должны быть проверены волной. Что ж, это имеет смысл и не может быть опровергнуто, так что поторопитесь и примите это! Здесь мы не забываем использоватьnpm unlinkОтмените привязку команды, иначе она повлияет друг на друга. Теперь открываем терминал и вводимnpm i xr-cli -gУстановите строительные леса глобально, затем выполнитеxr, если появится изображение ниже, это означает, что установка прошла успешно.Далее переходим на рабочий стол и выполняемxr init simple xr-test, вскоре вы сможете увидеть свой проект на рабочем столе. 6️⃣6️⃣6️⃣, похвалы безграничны, здорово. . отличный. . . Безграничный! ! !

Эпилог

Пока вы знакомы с вышеуказанной операцией несколько раз, перейдите кvue-cliСтруктура исходного кода, у вас будет ощущение, что вы видите луну в облаках (это просто намного, намного лучше, чем наши строительные леса 😭😭😭).
Конечно, это только шлаковая версия шлака. Вы можете заполнить его, добавить больше вещей, таких как автоматизация построения и динамический шаблон ах (на самом деле, динамические шаблоны - это большая голова), а затем попытаться написать больше и улучшить интерактивность и функциональность, чтобы вы могли иметь строительные леса из своих собственных друзей. , понял, так что не 998, лишь бы клавиатуру, скорей стучать товарищи, Поехали! 🌈