Возможно, вы использовали множество инструментов для построения скаффолдинга. Вы когда-нибудь задумывались, как написать скаффолдинг, который принадлежит вам?
Инструменты формирования зависимостей
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 часов.
Наконец, я рекомендую два инструмента для создания лесов, которые я пишу.
Сверхпростое междоменное, внешнее и внутреннее решение LiveNode для междоменного разделения