Пишем пет-проект на JavaScript и TypeScript в виде мини-игры, цель которой — быстро напечатать заданную фразу и уложиться в таймер.
9К открытий10К показов
Олег Рогов
Руководитель ЦК Frontend разработки Группы НЛМК
Пет-проект — это индивидуальный проект разработчика для реализации совершенно любых идей, он нужен для практики написания кода. Для того, чтобы сесть за проект, необходима идея. Для пет-проекта лучше выбирать самые интересные и сложные задачи, то, чем вы сами и ваши друзья или знакомые стали бы пользоваться. Например, это может быть трекер передвижения любимого кота, обработка и распознавание простейших математических примеров через камеру, игра в пинг-понг через сокеты c другом и т. д.
В процессе работы обязательно прописывать идеи будущего развития проекта и не забывать, что разработка должна приносить радость.
Для примера я напишу свой пет-проект. Его идея состоит в создании мини-игры, цель которой — как можно быстрее воспроизвести фразу (напечатать буквы и знаки препинания, кроме пробелов), чтобы уложиться в таймер.
Заходим в консоль и первым делом вводим команду по инициализации package.json нашего проекта. Флаг -y указывает на то, что на все вопросы мы говорим «да».
yarn init -y
Проект инициализировали, самое время определиться с тем, пишем мы сборку сами или воспользуемся уже готовым бойлерплейтом. Для себя я решил пользоваться кастомной сборкой, чтобы можно было контролировать и настраивать процесс, вносить изменения и получать новые знания. Это важно, ведь ради практики мы и пишем свои проекты.
В качестве стека у меня Webpack 5, React 18 и TypeScript.
После установки всех нужных библиотек время приступать к написанию конфига webpack: создадим папку config, внутри нее будет файл config/webpack.common.js. Он нужен, чтобы не повторять себя в development и production.
Открываем в браузере http://localhost:9000/ и видим сообщение Hello World! После этого можно сохранить сборку в отдельную ветку, как бойлерплейт, и использовать ее в остальных проектах, чтобы не писать каждый раз заново.
Теперь подумаем, чего нам не хватает, и пропишем наш сценарий. Не хватает стилей, поддержки .scss и красивого шрифта. Для добавления в проект в файле src/index.hbs добавляем:
Не забываем подключить наш файл к приложению, запустим наше приложение еще раз, и вуаля — отличный шрифт и сглаживание у нас уже есть. Мы молодцы!
Теперь, когда у нас есть правила и шрифт, подумаем над сценарием поведения нашего приложения. Я вижу его таким: пользователь заходит на страницу, видит на ней статус с описанием того, что именно от него требуется. Под описанием есть кнопка «Старт», после нажатия которой пользователь видит какую-либо цитату. Сверху виден таймер с отсчетом времени, внизу — количество букв и знаков, которые осталось ввести для победы, а рядом — общее число побед. Если пользователь вводит фразу быстрее таймера, выпускаем конфетти, а если не уложился, пишем, что игра закончена, но всегда можно нажать на старт, чтобы начать заново.
Выглядит это так:
Стартовая страница
Таймер на ввод
Конфетти которое поздравляет пользователя с победой
Статус, когда проиграли
Мы можем вводить буквы в любой последовательности, ускоряя процесс, и у нас может быть сколько угодно побед.
Планирование и написание пользовательского сценария — важный процесс работы над пет-проектом, ведь все решения в нем принимаем мы.
Напишем статус, который будет встречать нашего пользователя, а также сообщать ему о том, что можно попробовать сыграть заново в случае проигрыша src/components/Status/index.tsx.
import React, { FC } from 'react';
const Status: FC<{
start: boolean | undefined;
setStart: (value: boolean) => void;
}> = ({ start, setStart }) => (
<>
<h1>
{typeof start === 'undefined'
? `⏱ Цель игры, как можно быстрее напечатать буквы и
знаки, кроме пробелов, чтобы уложиться в таймер.`
: `???? Вы проиграли.`}
</h1>
<div className="start-btn-wrapper">
<button onClick={() => setStart(true)}>Старт</button>
</div>
</>
);
export default Status;
Осталось количество побед src/components/Victory/index.tsx:
Так у нас есть весь необходимый набор компонентов. Осталось добавить словарь с цитатами. Для этого создадим папку data c файлом src/data/quotes.json:
[
"Чем умнее человек, тем легче он признает себя дураком.",
"Никогда не ошибается тот, кто ничего не делает.",
"Менее всего просты люди, желающие казаться простыми.",
"Музыка заводит сердца так, что пляшет и поёт тело. А есть музыка, с которой хочется поделиться всем, что наболело.",
"Если тебе тяжело, значит ты поднимаешься в гору. Если тебе легко, значит ты летишь в пропасть.",
"Мой способ шутить – это говорить правду. На свете нет ничего смешнее.",
"Чем больше любви, мудрости, красоты, доброты вы откроете в самом себе, тем больше вы заметите их в окружающем мире.",
"Единственный человек, с которым вы должны сравнивать себя, – это вы в прошлом. И единственный человек, лучше которого вы должны быть, – это вы сейчас.",
"История – самый лучший учитель, у которого самые плохие ученики.",
"Человечество обладает одним поистине мощным оружием, и это смех.",
"Тренируйся с теми, кто сильнее. Не сдавайся там, где сдаются другие. И победишь там, где победить нельзя.",
"Будьте менее любопытны о людях, но более любопытны об идеях.",
"Мышление – верх блаженства и радость жизни, доблестнейшее занятие человека.",
"Я серьёзно отношусь к своей работе, а это возможно только при несерьёзном отношении к собственной персоне.",
"Успех – паршивый учитель. Он заставляет умных людей думать, что они не могут проиграть.",
"Чемпионами становятся не в тренажёрных залах. Чемпиона рождает то, что у человека внутри: желания, мечты, цели.",
"Необходимо, чтобы художник, кроме глаза, воспитывал и свою душу.",
"То, что мы знаем, это капля, а то, что мы не знаем, это океан.",
"Ни высокий интеллект, ни воображение, ни то и другое вместе не творят гения. Любовь, любовь и любовь – вот в чём сущность гения.",
"Не оборачивается тот, кто устремлён к звёздам.",
"Шире открой глаза, живи так жадно, как будто через десять секунд умрёшь. Старайся увидеть мир. Он прекраснее любой мечты, созданной на фабрике и оплаченной деньгами. Не проси гарантий, не ищи покоя – такого зверя нет на свете.",
"Видите ли, художника отличает то, что в его жизни бывают минуты, когда он ощущает себя больше чем человеком.",
"Любовь к собственному благу производит в нас любовь к отечеству, а личное самолюбие – гордость народную, которая служит опорою патриотизма."
]
Добавим для работы с .json в tsconfig.json:
"resolveJsonModule": true
Теперь нам доступен импорт .json файлов. Удаляем файл src/components/HelloWorld.tsx и вместо него добавляем src/components/Index.tsx:
И добавляем src/global.d.ts, чтобы TS не ругался на window.addEventListener('keydown', keyDownHandler, false);
import { KeyboardEvent } from 'react';
declare global {
interface WindowEventMap {
keydown: KeyboardEvent<HTMLInputElement>;
}
}
Делаем правки в src/App.ts:
import React from "react";
import { createRoot } from "react-dom/client";
import Index from "./components/Index";
const container = document.getElementById("root");
const root = createRoot(container);
root.render(<Index />);
Запускаем приложение и убеждаемся, что все работает согласно нашему сценарию.
Все работает так, как мы и предполагали
Теперь более внимательно посмотрим на код. Важная часть в пет-проектах — идеи роста. Нам, как разработчикам, важен опыт и насмотренность (что хорошо, а что плохо) на общую кодовую базу. Для себя я пишу список упражнений, которые нужно выполнить, работая внутри своего пет-проекта, и таким образом получаю и подтверждаю свой опыт, если длительное время не работаю с кодом. Я задаю себе вопрос, что можно улучшить, и создаю список.
В файле src/components/index.scss нет миксинов, и по-хорошему мы должны были разграничить стили от общих. Чтобы избежать ада глобальных имен, нам нужно использовать .module.scss или БЭМ-нотацию.
В файле src/components/Index.tsx слишком много useState, можно использовать useReducer или новые и трендовые стейт-менеджеры — Effector, Recoil, Jotai, Rematch, Zustand — либо остановиться на React Context. Для опыта и насмотренности можно сделать для каждого решения свою ветку — это даст наглядное понимание, что хорошего в решениях на рынке стейт-менеджеров есть уже сейчас.
Вынести в отдельный компонент таймер. Старайтесь писать списки и продумывать, как бы вы стали развивать свой проект, добавлять новые функции.
Нет системы уровней, для ускорения таймера.
Нет возможности посоревноваться с другом.
Можно ли сделать удобным интерфейс для планшетов и мобильных устройств?
Нет возможности поделиться результатом.
Нет возможности поставить на паузу.
Было бы здорово иметь на базе такого компонента виджет, который можно встроить на сторонний ресурс.
Когда мы описываем процесс работы с пет-проектом, у нас все время появляются новые задачи и вызовы. В принципе, это можно приравнять к постоянному стажу разработки, который помогает нам держать свои знания и насмотренность в тонусе. Это чрезвычайно важно при текущем положении дел, когда технологии и идеи развиваются со стремительной скоростью.
И напоследок скажу: чем больше мы работаем с кодовой базой проекта, тем более живым становится код. Следует не забрасывать свои пет-проекты, а стараться реализовывать в них все больше новых идей.