Как построить свои собственные леса

Node.js
Как построить свои собственные леса

написать впереди

Эта статья относительно проста, в основном с концепцией процесса. Вторая пуля вышла:портал

эффект каштана

Концепция строительных лесов

Так называемый скаффолдинг, на мой взгляд, представляет собой интегрированные процессы инициализации, отладки, сборки, тестирования, развертывания и других проектов, позволяющие пользователям сосредоточиться наcodeИнструмент. Говоря простым языком, здание уже построено, осталось только добавить кирпичи.

Полные леса обычно включают в себя три аспекта:

  • Командный скрипт скаффолдинга: Нам нужно установить глобальный скаффолдинг, с помощью которого мы можем легко начать разработку проекта. (также цель этой статьи)
  • scriptsПакет: Как правило, мы упаковываем, компилируем, тестируем и читаем пользовательские файлы конфигурации (такие какwebpackсвязанные операции настройки, содержимое, связанное с локальным сервером и т. д.), сделанные отдельноnpmМешок. Пусть пользователям не нужно заботиться об этих операциях, сосредоточьтесь наcode.
  • Файл шаблона: очевидно, что при инициализации проекта извлекается содержимое проекта.

Общие строительные леса каштаны:

  • create-react-app
  • vue-cli
  • ...

Новый проект

$ mkdir project && cd project
$ npm init -y

существуетpackage.jsonфайл, добавитьbinполе

{
  //...
  "bin": {
    "hello": "./index.js"
  },
  //...
}

binФункция в том, что официальный сайт объясняет это так:

многоnpmПакеты имеют один или несколько для установки вPATHисполняемый файл в формате .package.jsonпредоставить поле вbin, который представляет собой сопоставление имен команд с именами локальных файлов. Во время установкиnpmбудет символически ссылаться на файлprefix/binдля глобальной установки или./node_modules/.bin/Установить локально.

Грубо говоря, при установке он создаст快捷方式,пройти через快捷方式Можно использовать для удобстваnodeкоманда скрипта. Вот почему мы можем открыть командную строку напрямую и случайно, черезcraспособ создания проекта.

и соответствующийindex.jsфайл, должен начинаться с#!/usr/bin/env node.usr/bin/envсказал идтиPATHНайдите интерпретатор сценариев в каталоге и укажите использованиеnodeдля выполнения файла.

#!/usr/bin/env node

console.log('hello world!');

затем пройтиnpm link, создать симлинк в глобале, поставитьpackage.jsonвнутреннийbinСодержимое поля отображается и связывается.

$ npm link

тогда его можно использовать прямо в любом местеhelloЗаказ.

работа с командной строкой

Здесь я используюcommander.jsпрочитать команду.

командирская документация

Заказ

const program = require('commander');

program
    .command('create <name>')
    .description('请输入项目名称')
    .action(name => {
        console.log(`你要创建的项目名称:${name}`);
    });

program.parse(process.argv);

.command()Первый параметр может настроить имя команды и параметры.Параметры поддерживают обязательные (обозначаются угловыми скобками), необязательные (обозначаются квадратными скобками) и параметры переменной длины (обозначаются точками, если используется, только последний параметр).

подсказка версии

общий какcreate-react-app -V, который обычно читается самостоятельноpackage.jsonсерединаversionполе, затем используйтеprogram.version.

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

program.version(packageJson.version);

справочная информация

helpдаcommander.jsАвтоматически генерируется на основе кода, вариант справки по умолчанию-h,--help.

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

проблема взаимодействия

Многие леса взаимодействуют с пользователями, когда они используются. Это можно сделать с помощьюinquirer.jsиспользовать.

документация запросчика

//...
const answer = await inquirer.prompt([
    {
        type: 'input',
        name: 'name',
        message: '请输入项目名称',
    },
]);

оперативная обратная связь

После выполнения команды скрипта в командной строке обычно появляются дружественные подсказки, например:loading,success,errorи т.п. Это можно использоватьora

ора документация

const ora = require('ora');
const loading = ora('Loading unicorns');

loading.text = '疯狂加载中';
loading.color = 'green';
loading.start();

Также напримерcolors,chalkПодождите, я не буду объяснять это по одному.

Вытащите файл шаблона

Наиболее важной частью формирования шаблонов является извлечение различных файлов шаблонов на основе пользовательского ввода. Например, я ввожу выбор языкаtypescript, то вытащенный файл шаблона естественно поддерживаетсяtypescriptДа, эта часть используетdownload-git-repo.

скачать документацию-git-repo

download-git-repoПоддержка трех платформ для загрузки:

  • GitHub - github:owner/name or owner/name
  • GitLab - gitlab:owner/name
  • Bitbucket - bitbucket:owner/name

Он также поддерживает#Чтобы вытащить код на разные ветки, конечно, по умолчаниюmaster. Затем мы можем получать различные типы данных непосредственно через пользовательский ввод.branchПриведенный выше код используется для извлечения различных файлов шаблонов. (Или просто создайте несколько складов и используйте разные коды складов).

const download = require('download-git-repo');
const downloadAdress = lang => `owner/name#${LANG_LIST[lang]}`;

program
  .command('create')
  .description('初始化项目')
  .action(async () => {
    const answer = await inputer.prompt([
      //...
      {
        type: 'list',
        message: '使用哪种语言进行开发',
        name: 'lang',
        choices: ['typescript', 'javascript'],
      },
    ]);
    
    download(
      downloadAdress(answer.lang),
      `./${answer.name}`,	// path
      downloadCallback.bind(null, answer),	// callback
    );
  });

Изменить package.json

Из-за извлеченного файла шаблонаpackage.jsonВсе фиксировано. И большинство скаффолдов заменяются в соответствии с пользовательским вводом во время инициализации.package.jsonСоответствующее поле среды.

Это операция чтения и записи файла черезreadFileSyncПрочитайте содержимое файла, замените соответствующие поля и перезапишите.

const filename = `${answer.name}/package.json`;

if (fs.existsSync(filename)) {
  let newPagJson = fs.readFileSync(filename).toString();

  newPagJson = JSON.parse(newPagJson);
  newPagJson = {...newPagJson, ...answer};
  newPagJson = JSON.stringify(newPagJson, null, '\t');

  fs.writeFileSync(filename, newPagJson);
  
  //...
}

использоватьstringifyдругие параметры будутnewPagJsonФорматирование так, чтобы оно перезаписывалось, также является правильным.

выпускать

После завершения разработки мы обычно выбираем публикацию наnpmна платформе.

нпм ссылка

Процесс публикации также прост:

  • npm login
  • npm publish, не забудьте обновитьversion

удалить пост

Потому что каждый раз, когда выпускается обновление, оно будетnpmсохранить его в истории, если вы хотите удалить определенный или весьnpmпакет, вы можете использоватьnpm unpublish.

Он также очень прост в использовании

$ npm unpublish [<@scope>/]<pkg>@<version>
$ npm unpublish [<@scope>/]<pkg> --force

Первый означает удаление версииnpmпакет, сразу после удаленияversionбольше нельзя использовать или переиздаватьversion.

Последнее означает удаление всегоnpmпакет, необходимый после удаления24часов до повторной публикации.

Проверить наличие обновлений

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

Поскольку для извлечения версии требуется время, это, как правило, интервальная оценка.

Здесь я сохраняю последнее время растяжения, и разница между текущей временной меткой и последней извлеченной временной меткой определяется, нужно ли оценивать это время.

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

const resolve = _path => path.join(__dirname, _path);

const timePath = resolve('index.txt');

const MAX_TIME = 86400000;

const checkTime = () => {
  const lastTime = +fs.readFileSync(timePath).toString();
  const nowTime = new Date().getTime();

  if (lastTime && nowTime - lastTime <= MAX_TIME) {
    return;
  }

  fs.writeFileSync(timePath, nowTime);

  const lastV = execSync('npm view yourNpmPackage version', { encoding: 'utf8' });
  return lastV;
};

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

документация узла

Вышеупомянутое содержание, по сути, все еще является базовым упражнением.

У меня также была идея в свободное время на этой неделе, и я решил сам сделать строительные леса, чтобы изучить их во время обзора. После этого я постараюсь его максимально улучшить, и если в будущем появится новый контент, я им тоже поделюсь.