Автор оригинала: FreeCodeCamp Community Member.
Прежде чем начать: Эта статья использует код примера JavaScript/Node.js, но вы можете портировать эти концепции на любом языке, используя правильные инструменты.
Захватывающее введение
Вы когда-нибудь оказываетесь, создавая одни и те же файлы снова и снова в ваших проектах?
Я тоже.
Мои пальцы болят!
Я не удивлен. Вы принимаете работу от роботов.
Создание одних и тех же файлов несколько раз – скучно и ненужно.
TLDR? Я получил тебя – вот демо
Покажите мне код
Я уважаю свое чувство срочности – я порежу на погоню.
Код
Мы хотим автоматизировать создание файлов – вот почему вы все появились сегодня. Во-первых, нам нужно определить файлы, которые мы хотим создавать.
В последнее время я создавал много компонентов реагирования, поэтому моя настройка вращается вокруг этого – но вы можете настроить это буквально что угодно.
Я разделил это на четыре шага. Просто говорите вам сейчас, чтобы вы могли управлять своими ожиданиями. Если вы не можете справиться с чем-то более тремя шагами, то мы в беде …
Шаг 1: Шаблоны
Установите их один раз и прибыль.
Нам нужны шаблоны. Я использовал Шаблонные литералы Но сделайте это любым способом для вас чувства – будь творческим.
Это файлы, которые я создаю каждый раз, когда делаю компонент React:
- index.jsx.
- {Компонент} .test.js
- {Компонент} .sass
Примечание: {Компонент} подразумевает Струнная интерполяция Отказ
Я тестирую с Jest и используя Create-React-App котельная. Я знаю, что многие люди предпочитают CSS-in-js В эти дни – но эй. Дайте мне знать в комментариях, в чем вы находитесь.
В любом случае – здесь мы идем:
const templates = { index: name => `// @flow import React from 'react'; import './${name}.css'; // TODO: write rest of ${name} component const ${name} = () => (rest of component); export default ${name};`, test: name => `// TODO: TDD import { shallow, render } from 'enzyme'; import renderer from 'react-test-renderer'; import React from 'react'; import ${name} from '.'; const component = <${name} />; describe('The ${name} component', () => { it('renders correctly', () => { const wrapper = render(component); expect(wrapper.hasClass('${name.toLowerCase()}')).toBeTruthy(); const tree = renderer.create(component).toJSON(); expect(tree).toMatchSnapshot(); }); });`, sass: name => `.${name.toLowerCase()} background: initial`, };
Это мрачный кусок кода, который вы увидите здесь – Pinky Promise.
Итак, у нас есть объект с тремя свойствами: индекс, тест и SASS. Каждый ходит функцию, которая принимает имя и возвращает шаблон с таким именем, интерполированным. Выглядит вполне законно.
Шаг 2: Давайте сделаем некоторые функции!
Мы используем ФС модуль упакованы с узлом. Это потрясающий. Это делает много вещей.
Мы собираемся использовать некоторые Функции стрелки и немного Функциональное программирование Отказ Не бойся – просто иди с этим.
Синтаксис функции двойной стрелки называется Carrying Отказ Это нормально, если это выглядит странно. Я был взволнован, когда я впервые увидел это, но это позволяет Супер прохладные вещи Отказ На самом деле, вот быстрое демонстрация:
const fs = require('fs'); const fileExists = path => file => fs.existsSync(`${path}/${file}`); const fileExistsInSrc = fileExists('/src'); // file => fs.existsSync(`${path}/${file}`) fileExistsInSrc('index.js') // true || false
Так что это Carrying с Частичное приложение – Это тоже закрытие Отказ
Боковая панель : Надеюсь, никто не зовет меня здесь на некоторые технические средства, но, пожалуйста, предавайте меня в комментариях, если вы чувствуете необходимость.
Давайте продолжим:
const fs = require('fs'); const fileExists = path => file => fs.existsSync(`${path}/${file}`); const writeToPath = path => (file, content) => { const filePath = `${path}/${file}`; fs.writeFile(filePath, content, err => { if (err) throw err; console.log("Created file: ", filePath); return true; }); };
Сначала нам нужно ФС Отказ Нам нужно это в нашей жизни.
Тогда мы объявляем Fileexists как Функция выражение Отказ
Наконец у нас есть еще один Функция выражение называется WriteTopath. Требуется путь и возвращает другую функцию, которая принимает Файл строка и Содержание этого файла. Затем он записывает файл или бросает ошибку (худший сценарий).
Ты правильно думаешь? Мы создаем некоторые файлы.
Шаг 3: Познакомьтесь с Chokidar
Веселый факт: это Хинди слово Отказ
Мы говорим о Пакет NPM хоть. Он основан на нашем новом друге ФС И вы могли бы использовать его для многих восхитительных вещей.
Он смотрит наши файлы для нас Как ястреб Отказ
Ну не совсем как ястреб.
Это не птица.
Как вообще.
Во всяком случае, вот код …
const chokidar = require("chokidar"); const watcher = chokidar .watch("src/components/**", { ignored: /node_modules/ }) .on("addDir", (path, event) => { const name = path.replace(/.*\/components\//, ""); const goodToGo = /^[^\/_]*$/.test(name); if (goodToGo) createFiles(path, name); });
Сначала нам нужно это.
Далее мы определяем, что мы хотим посмотреть. Я смотрю SRC/Компоненты каталог, но вы можете смотреть любой набор путей. Вы даже можете пройти Массив путей Отказ Если вы не узнаете ** Часть в SRC/Компоненты/** – это называется шаблон шара Отказ
После этого мы определяем, какие события мы хотим слушать. Я просто слушаю только добавление каталога с .on (“adddid”) Но вы можете слушать Другие события тоже.
Давайте давайте извлеченем имя компонента, заменив чего-либо перед именем компонента:
src/components/Header/components/Title
становится
Title
Наконец мы проверим, что имя компонента проходит это регез:
/^[^\/_]*$/
Так что до тех пор, пока у него нет форвардной косылки или подчеркивания – это хорошо идти. Это позволяет избежать загрязнений __tests__ папок или вложенных/каталогов по ошибке.
Шаг 4: Время сделать некоторые файлы!
Вы достигли последнего шага. Поздравляю! Это было довольно здорово.
Эта следующая функция открыто названа createfiles Отказ
Это немного грязно – это может быть восстановлено.
Заранее прошу прощения, если код ниже оскорбляет вас.
Давайте копать:
function createFiles(path, name) { const files = { index: "index.jsx", test: `${name}.test.js`, sass: `${name}.sass` }; if (name !== "components") { const writeFile = writeToPath(path); const toFileMissingBool = file => !fileExists(path)(file); const checkAllMissing = (acc, cur) => acc && cur; const noneExist = Object.values(files) .map(toFileMissingBool) .reduce(checkAllMissing); if (noneExist) { console.log(`Detected new component: ${name}, ${path}`); Object.entries(files).forEach(([type, fileName]) => { writeFile(fileName, templates[type](name)); }); } } }
Так что сверху мы объявляем Файлы Объект – это список строк имени файла, которые мы впрыскиваем Имя параметр в. Вы могли бы заметить, что у него есть такие же ключи, как Шаблоны объект. Это важно.
Если Заявление очень специфично для моей установки. Я не хочу создавать свои файлы Если Новая папка называется компонентами. Я только создаю компоненты внутри Подппозиция компонентов.
- writefile Наша функция WriteTopath частично применяется Отказ Это функция, которая создает файл в данном пути при вызове с именем файла и некоторым контентом.
- TOFILEMISSINGBOOL принимает имя файла и возвращает true, если этот файл не существует в данном пути. Я знаю, что имена функций странные, но я обещаю, что она имеет больше смысла в нескольких линиях.
- CheckallySing это функция, которую мы собираемся передать на Уменьшить Отказ Требуется два логических и возвращается истина, если оба верны. Это логическая алгебра Отказ Мы также используем Уменьшить метод Массив Отказ Не бойся уменьшить. Это очень круто и действительно полезно в такой ситуации.
Давайте поговорим о переменной нерешитель Отказ Если это правда, то ни один из файлов, которые мы не хотим создавать, существуют в новой папке. Идея состоит в том, что вы не связываетесь с папкой только потому, что у него нет тестового файла или файла SASS. Может быть, эта папка не нужна.
const noneExist = Object.values(files) .map(toFileMissingBool) .reduce(checkAllMissing);
Вот почему я создал эти странно названные функции выше.
Мы карта Значения в Файлы к логический который представляет, если этот файл отсутствует или нет. Тогда мы берем это Массив логических островов и Уменьшить их в один логический Значение, которое представляет, существуют ли все файлы или нет.
Так что если они все Правда, Тогда нерешитель тоже правда. Но если даже один это Ложь, Тогда нерешитель будет ложь Отказ
Я надеюсь, что вы все это получили. Это кусочек глотки Отказ
Последний бит кода:
Object.entries(files).forEach(([type, fileName]) => { writeFile(fileName, templates[type](name)); });
Мы берем ключ ( тип) и ценность (Имя файла) И напишите файл в данном пути с контентом из соответствующего шаблона.
Плавник.
Эта картина морской черепахи представляет, как бесплатно вы должны чувствовать, что теперь вы все автоматизируете.
Если вы хотите весь код для автоматического создания компонентов React, Это здесь Отказ
Дайте мне знать, что вы думали – поддерживайте связь.
Подскажите, если вы найдете какие-либо ошибки.