В этой статье мы изучим, что такое zx.js, какие возможности он предоставляет и как мы можем применить его для написания скриптов, а затем научимся использовать все его фичи, разработав инструмент, который можно запустить из командной строки.
Код инструмента zx доступен на github.
Что такое zx.js и почему его используют?
Командная оболочка Bash хороша, но когда дело доходит до написания скриптов, люди часто выбирают более удобный язык программирования, и JavaScript прекрасно для этого подходит. Перед началом работы стандартная библиотека Node.js требует множества дополнительных операций, таких как инсталляция и ее внедрение. zx обеспечивает обертку модулю child_process, которая экранирует параметры и предоставляет смердженные значения по умолчанию.
Сначала рассмотрим официальный пример:
#!/usr/bin/env zx // From https://github.com/google/zx#-zx await $`cat package.json | grep name` let branch = await $`git branch --show-current` await $`dep deploy --branch=${branch}` await Promise.all([ $`sleep 1; echo 1`, $`sleep 2; echo 2`, $`sleep 3; echo 3`, ]) let name = 'foo bar' await $`mkdir /tmp/${name}`
Официальный пример
Синтаксис JavaScript в приведенном выше примере может показаться немного странным. Он использует фичу языка, которая называется тегированные шаблонные литералы (tagged template literals).
Но это же круто, правда? Так что давайте начнем!
Инсталляция
// Глобальная инсталляция. // Также вы можете установить его отдельно в своем проекте. npm i zx -g
Требование:
Убедитесь, что версия вашего node >= 16.00.0.
Принцип работы zx.js
Он предоставляет функции, которые оборачивают процедуру создания дочерних процессов и обработку stdout
и stderr
из них.
Использование
-
Для быстрого тестирования скрипта можно использовать символ пайплайна
$ echo "console.log(await (await fetch('http://orange.tw')).text())" | zx $ fetch http://orange.tw 183.133.12.121 Your country
-
Другой способ — разработать скрипт в проекте, как мы часто делаем.
Сначала инициализируйте проект,
mkdir zx-demo cd zx-demo touch index.mjs npm init -y // Note: the zx documentation suggests installing the library globally with npm. // By installing it as a local dependency of our project instead, // we can ensure that zx is always installed, as well as control the version that our shell scripts use. npm i zx -D
Основной файл должен содержать следующие заголовки файлов:
#!/usr/bin/env zx
Сначала нужно добавить разрешения на выполнение, а затем запустить скрипт:
chmod +x ./index.mjs ./index.mjs // Or use this command zx ./index.mjs
Теперь он может отображать какое-то содержимое, zx.js предоставляет много черной магии, у него есть встроенные fetch, question и асинхронные операции (круто), и теоретически он способен выполнять shell и другие скрипты типа tree и прочие команды, установленные самостоятельно, что очень мощно.
Дальше давайте имплементируем инструмент командной строки, который обычно используется для создания библиотеки компонентов!
Инструмент командной строки
Этот проект поможет нам генерировать общие каталоги и файлы компонентов, а также автоматически заполнять components.ts
, что значительно упрощает повторные операции по созданию новых файлов.
Сначала необходимо создать проект ноды в соответствии с приведенной выше частью, а затем создать соответствующий каталог/файл, как показано на рисунке. После завершения операции структура ваших каталогов должна выглядеть следующим образом. Не забудьте создать новый файл index.ts
в каталоге компонентов (игнорируйте файл протокола и каталог .vscode)
Инициализация проекта
-
Для начала нам нужно создать первый файл шаблона, который является компонентом React и по умолчанию экспортирует тип Props, и, в итоге, генерирует содержимое каталога и файла.
export default (fileName) => ({ content: ` // Generated with index.js, Assume this is a react project import React from "react"; export interface I${fileName}Props {} const ${fileName}: React.FC<I${fileName}Props> = () => { return ( <div>{/** Todo... */}</div> ); } export default ${fileName}; `, suffix: `tsx`, });
-
Экспорт файла шаблона
import componentMain from "./component-main.mjs"; const templates = [componentMain]; export default templates;
-
Нам нужен основной файл, который экспортирует все компоненты (например, Button, Select, Card); это является хорошей практикой программирования.
#!/usr/bin/env zx import _fs from "fs"; import { chalk } from "zx"; const fs = _fs.promises; /** * @description This function is subduquered according to the file name generated by `npm run generate your filename`, * then automatically injects imported import export in src/components/index.js. * * @param { string } directoryName * @returns { void } */ const additionalEntryContent = async (directoryName) => { const originalFile = "./src/components/index.ts"; // Read original file content const entryFileContent = await fs.readFile(originalFile, "utf-8"); // Additional content fs.writeFile( originalFile, entryFileContent.concat( ` export type { I${directoryName}Props } './${directoryName}'; export { default as ${directoryName} } from "./${directoryName}";\n` ) ); console.log( chalk.green(`Successfully additional content in: ${originalFile}`) ); }; export default additionalEntryContent;
-
Напишите основной логический код в файле
index.mjs
, который отвечает за получение информации о параметрах командной строки, вводимой пользователем, определение существования каталога, создание каталога и окончательное обновление каждого файла.
#!/usr/bin/env zx import { $, chalk } from "zx"; import fs from "fs"; import templates from "./scripts/templates/index.mjs"; import additionalEntryContent from "./scripts/additional-entry.mjs"; $.verbose = false; const directoryName = process.argv[2]; if (!directoryName) { console.error( chalk.red("[Error]: Create file error, please supply a valid directoryName") ); process.exit(1); } // The Directory address of the generated file const componentDirectory = `./src/components/${directoryName}`; if (fs.existsSync(componentDirectory)) { console.error(chalk.red(`Directory ${directoryName} already exists`)); process.exit(1); } fs.mkdirSync(componentDirectory); try { const generatedTemplates = templates.map((template) => template(directoryName) ); generatedTemplates.forEach((template) => { fs.writeFileSync( `${componentDirectory}/index.${template.suffix}`, template.content ); }); console.log(chalk.green("Successfully created directory:", directoryName)); // Add the context to the imported content in Index.js additionalEntryContent(directoryName); } catch (error) { console.error(error); process.exit(1); }
-
Приступаем к созданию компонента, открываем терминал, например, мы хотим создать компонент Button.
Успешно, мы создали компонент Button, и экспортируемый связанный код автоматически загружается в components/index.ts, отлично.
Перевод статьи подготовлен в рамках специализации «Fullstack Developer».
ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/670112/
Добавить комментарий