Ну что за цирк! Это абсолютно неподдерживаемый код: 4 простеньких компонента, а уже какая-то каша.
Статья явно рассчитана на здешнюю публику: бэкенд-разработчиков предпенсионного возраста, которые в последний раз фронт еще на таблицах верстали и сейчас жестко ненавидят текущие фронтенд фреймворки, потому что им слишком лень переучиваться; они уверены, что всё можно делать по старинке, хотя сложность задач на фронте возросла с тех пор в десятки, если не в сотни, раз.
подход с использованием глобального состояния... пытаются время от времени переизобретать (как в редаксе каком-нибудь), но этот антипаттерн по понятным причинам не взлетает и взлететь не может
Redux – 61.2k звезд на Github, 4.8 млн пользователей, 995 контрибьюторов и через 10 лет существования всё еще 12 млн еженедельных скачиваний на npm – это Вы про это говорите "по понятным причинам не взлетает и взлететь не может" 🤦♂️
Большинство современных сайтов в интернете, которыми Вы пользуетесь, работают через Redux. Включая сайт, на котором Вы сейчас находитесь. Ваш комментарий про то, как Redux не работает, скорее всего, хранится в Redux-сторе, видите, какая ирония.
Голословно обвинять неизвестного вам человека в том, что он не умеет программировать – это хамство. Я могу на куче разных фреймворках один и тот же фронт написать – это не значит, что мне "всё равно" на чем писать. Разные фреймворки – это разные паттерны, разные библиотеки, разные окружения. Есть best practices, а есть откровенные антипаттерны.
Если вы можете написать бэкенд на 10 разных языках, это не значит, что вы во фронтенде разбираетесь.
Если автор еще поизучает проблемы фронтенда, то он поймет, что лучше всего подписываться не на конкретные ивенты, а иметь единый источник истины в виде хранилища данных и реагировать на изменения конкретных значений в этом хранилище. И окажется, что некто Дэн Абрамов еще десять лет назад про это подумал и создал библиотеку Redux конкретно, чтобы решить эту проблему)
Я не против добавить изменения на брейкпоинты, просто правильнее их делать через sm: и т.п. по тем же самым причинам, что я описал ранее: у нас уже есть заданные брейкпоинты, лучше от них не отклоняться
У меня совсем иной опыт того, что "на практике" происходит. Обычно все неопытные разработчики, наоборот, пытаются надробить побольше компонентов и переиспользовать там, где этого делать не надо.
Вы же в коде наверняка пытаетесь избавляться от магических констант, а Tailwind, наоборот, поощряет их создание.
Проблема с магическими константами в том, что непонятно, что они значат. И это действительно может быть проблемой, если весь код написан в одном файле на TailwindCSS, – не разберешь, где что.
Но это не проблема, если мы используем компоненты, тогда смыслы мы закладываем в названиях этих компонентов. А как плюс мы получаем возможность не перенагружать смыслами те элементы, которые в них не нуждаются.
Необходимость придумывать название для элемента, только потому что мы хотим задать ему какие-то стили, вынужденная. Стили не всегда имеют смысл. Именно поэтому, например, CSS-in-JS подход (например, styled-components) тоже проигрывает TailwindCSS. Потому что он только усугубляет эту проблему, а не решает её.
Если у Content 2 чуть-чуть поменяются стили, очень удобно то, что мне не надо придумывать название для нового класса; место, где оно должно храниться; переживать за специфичность; и т.д. и т.п.
Например, какая боль в этом примере, если Content 1 и Content 2 одинаковые, но только надо добавить margin-top второму.
Вы дали пример, где в реальности TailwindCSS сильно выигрывает у классического подхода.
Перед началом проекта мы пишем конфиг, где прописываем все доступные цвета, размеры и т.п. Если мы пишем через @apply, у нас все правила сохраняются, подсказки IDE помогают не накосячить. Мы теряем все эти рамки, если пишем чистый CSS. Плюс удобнее в одном стиле всё записать, раз весь код уже TailwindCSS.
P.S. В примере выше я использовал @media зря, тут надо было тоже через брейкпоинты TailwindCSS делать, на самом деле. Не обратил внимание на плохую подсказку ИИ
Т.е. по вашему в круг анонимных живодеров не надо вмешиваться да? Пусть там себе спокойно мучают животных. Ты же не хочешь их мучать, вот и не лезь, не мешай им.
Такую чушь несете... Я даже слушать дальше не буду. Испугаюсь и убегу лучше)
ибо противопоставить код с примером реальной кнопки вы боитесь. И всё что вы можете это бла бла бла и съезжать с темы. вместо того чтобы взять и написать код.
Вы мне предлагаете лекцию по TailwindCSS Вам теперь расписать? Мне образовывать тех, кто не хочет образовываться, неинтересно.
Например, мне придется объяснять, что пример с кнопкой не очень репрезентативен, так как никто не станет такие базовые стили копипастить для каждой кнопки, они выносятся в стили кнопки в глобальном CSS-файле:
Соболезную. Может для вас ещё очевидно что земля плоская?
Этот комментарий отлично демонстрирует, как Вы, не имея возможности опереться на факты, начинаете язвить, передергивать и притягивать за уши. Классическая манипуляция, которая лишний раз доказывает, что Вы не правы.
И показали типичную вырвиглаз кашу и мешанину.
Любой код – каша и мешанина, если вы не умеете его читать.
там есть прям конкретный пример с scss для одной лишь кнопки
Я прекрасно представляю, как выглядить код на SCSS, и я знаю, что код на TailwindCSS в реальных проектах смотрится лучше.
Главный вопрос – это что Вы тут потеряли? Если Вы не хотите писать на TailwindCSS, не пишите, вас никто не заставляет. Зачем Вы вообще в чужой монастырь со своим уставом лезете? Мы тут обсуждаем TailwindCSS, а вот это нытье про то, насколько SCSS лучше, мы уже тысячу раз слышали.
Ваши аргументы убедят любого новичка, который никогда не сталкивался с версткой, это точно. В реальности же Вы просто спрятали всю сложность своего примера в других файлах, как это обычно делается в подобных манипуляциях. А пример с TailwindCSS максимально нелепый, вы просто накопипастили какую-то белиберду, чтобы она и выглядела, как белиберда. На самом деле же, код с TailwindCSS зачастую намного читабельнее Вашего.
Вот Ваш пример, примерно написанный на TailwindCSS:
Может отпугнуть, если не знаешь, что значат эти классы. Но даже если не знаешь, можно разобраться, если напрячься. А если умеешь с таким работать, это становится максимально удобно и понятно. В Вашем же примере я не вижу, как всё стилизовано; чтобы что-то поправить, мне приходится искать файлы со стилями, а так еще импорты в десять других файлов и пошло поехало; если у меня уже есть класс, а конкретно тут нужно еще отступ добавить, что мне делать, это целая проблема; нужно придумывать имена для каждого элемента на странице; нужно переживать на специфичность, чтобы стили не накладывались; для каждого компонента нужно держать отдельный CSS-файл, а значит количество файлов и папок сразу удваивается; и т.д. и т.п.
Я делал и так, и так, и прекрасно понимаю все подводные камни обоих вариантов. И для меня абсолютно очевидно, что TailwindCSS намного превосходит любые Ваши предложения. А Вы никогда не писали на TailwindCSS, и в своем невежестве продолжаете проталкивать устаревшие подходы.
Валидация данных с API и валидация форм – это как раз таки самые очевидные кейсы использования.
Неочевидный кейс – это, например, использовать Zod вместо автотестов на фронтенде. Вместо того, чтобы писать тесты, вы можете любые данные на входе, например, в функцию проверять через z.parse. Тогда при любой несостыковке при ручном проходе по интерфейсу тут же выпадает понятная ошибка на весь экран и баг тут же фиксится.
Или же, когда два типа вроде как должны сходиться, но не сходятся, и TypeScript не понимает и ругается, можно вместо использования as <type>, как это сейчас делается, писать тот же z.parse, чтобы подогнать тип. Тогда и TypeScript доволен, и вы уверены, что нигде не накосячили.
Еще можно валидировать параметры функции более тщательно, чем TypeScript это может. Вот, например у меня функция, которая создает новый id:
В приведенной цитате из доки, когда говорится о "static type inference", имеется в виду как раз то, что Вы называете, "преобразование типов в runtime", а не z.infer<typeof userSchema>.
Если на Ваш взгляд это не является необходимым – окей, Ваше право не использовать это. Тогда Вам действительно не нужен zod, Ваша библиотека подходит куда лучше.
Но Вы не правы, если считаете, что не это, а что-то другое, является основной фишкой zod.
Zod is a TypeScript-first schema declaration and validation library. <...> The goal is to eliminate duplicative type declarations. With Zod, you declare a validator once and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures.
То есть основная идея – это то, что парсишь данные и получаешь на выходе корректно типизированные значения. Твоя же библиотека делает только самую простую часть – валидацию.
Классно, что есть такое упрощенное решение, но говорить, что ты сделал тот же zod, но в 10 раз быстрее, как ты описываешь себя в описании, мягко говоря, некорректно.
Если ты зачем-то хочешь тот же zod, но более оптимизированный (как будто в этом основная проблема твоего приложения), то стоит, скорее, смотреть в сторону Valibot. Но и то, это лишнее, жертвуем DX, чтобы сэкономить пару миллисекунд.
Ну что за цирк! Это абсолютно неподдерживаемый код: 4 простеньких компонента, а уже какая-то каша.
Статья явно рассчитана на здешнюю публику: бэкенд-разработчиков предпенсионного возраста, которые в последний раз фронт еще на таблицах верстали и сейчас жестко ненавидят текущие фронтенд фреймворки, потому что им слишком лень переучиваться; они уверены, что всё можно делать по старинке, хотя сложность задач на фронте возросла с тех пор в десятки, если не в сотни, раз.
А какой сайт работает хорошо? Можно пример? И, желательно, чтобы он не использовал Redux или любое другое глобальное хранилище данных.
Redux – 61.2k звезд на Github, 4.8 млн пользователей, 995 контрибьюторов и через 10 лет существования всё еще 12 млн еженедельных скачиваний на npm – это Вы про это говорите "по понятным причинам не взлетает и взлететь не может" 🤦♂️
Большинство современных сайтов в интернете, которыми Вы пользуетесь, работают через Redux. Включая сайт, на котором Вы сейчас находитесь. Ваш комментарий про то, как Redux не работает, скорее всего, хранится в Redux-сторе, видите, какая ирония.
Голословно обвинять неизвестного вам человека в том, что он не умеет программировать – это хамство. Я могу на куче разных фреймворках один и тот же фронт написать – это не значит, что мне "всё равно" на чем писать. Разные фреймворки – это разные паттерны, разные библиотеки, разные окружения. Есть best practices, а есть откровенные антипаттерны.
Если вы можете написать бэкенд на 10 разных языках, это не значит, что вы во фронтенде разбираетесь.
Если автор еще поизучает проблемы фронтенда, то он поймет, что лучше всего подписываться не на конкретные ивенты, а иметь единый источник истины в виде хранилища данных и реагировать на изменения конкретных значений в этом хранилище. И окажется, что некто Дэн Абрамов еще десять лет назад про это подумал и создал библиотеку Redux конкретно, чтобы решить эту проблему)
А какое решение? Отказаться от TS? Попробуйте, потом расскажите, как прошло)
Я не против добавить изменения на брейкпоинты, просто правильнее их делать через
sm:и т.п. по тем же самым причинам, что я описал ранее: у нас уже есть заданные брейкпоинты, лучше от них не отклонятьсяУ меня совсем иной опыт того, что "на практике" происходит. Обычно все неопытные разработчики, наоборот, пытаются надробить побольше компонентов и переиспользовать там, где этого делать не надо.
Проблема с магическими константами в том, что непонятно, что они значат. И это действительно может быть проблемой, если весь код написан в одном файле на TailwindCSS, – не разберешь, где что.
Но это не проблема, если мы используем компоненты, тогда смыслы мы закладываем в названиях этих компонентов. А как плюс мы получаем возможность не перенагружать смыслами те элементы, которые в них не нуждаются.
Необходимость придумывать название для элемента, только потому что мы хотим задать ему какие-то стили, вынужденная. Стили не всегда имеют смысл. Именно поэтому, например, CSS-in-JS подход (например, styled-components) тоже проигрывает TailwindCSS. Потому что он только усугубляет эту проблему, а не решает её.
Если у Content 2 чуть-чуть поменяются стили, очень удобно то, что мне не надо придумывать название для нового класса; место, где оно должно храниться; переживать за специфичность; и т.д. и т.п.
Например, какая боль в этом примере, если Content 1 и Content 2 одинаковые, но только надо добавить
margin-topвторому.Вы дали пример, где в реальности TailwindCSS сильно выигрывает у классического подхода.
Перед началом проекта мы пишем конфиг, где прописываем все доступные цвета, размеры и т.п.
Если мы пишем через
@apply, у нас все правила сохраняются, подсказки IDE помогают не накосячить.Мы теряем все эти рамки, если пишем чистый CSS.
Плюс удобнее в одном стиле всё записать, раз весь код уже TailwindCSS.
P.S. В примере выше я использовал
@mediaзря, тут надо было тоже через брейкпоинты TailwindCSS делать, на самом деле. Не обратил внимание на плохую подсказку ИИТакую чушь несете... Я даже слушать дальше не буду. Испугаюсь и убегу лучше)
Вы мне предлагаете лекцию по TailwindCSS Вам теперь расписать? Мне образовывать тех, кто не хочет образовываться, неинтересно.
Например, мне придется объяснять, что пример с кнопкой не очень репрезентативен, так как никто не станет такие базовые стили копипастить для каждой кнопки, они выносятся в стили кнопки в глобальном CSS-файле:
Теперь они есть у всех
<button>по умолчанию, а особенности мы будем дописывать классами индивидуально.Этот комментарий отлично демонстрирует, как Вы, не имея возможности опереться на факты, начинаете язвить, передергивать и притягивать за уши. Классическая манипуляция, которая лишний раз доказывает, что Вы не правы.
Любой код – каша и мешанина, если вы не умеете его читать.
Я прекрасно представляю, как выглядить код на SCSS, и я знаю, что код на TailwindCSS в реальных проектах смотрится лучше.
Главный вопрос – это что Вы тут потеряли? Если Вы не хотите писать на TailwindCSS, не пишите, вас никто не заставляет. Зачем Вы вообще в чужой монастырь со своим уставом лезете? Мы тут обсуждаем TailwindCSS, а вот это нытье про то, насколько SCSS лучше, мы уже тысячу раз слышали.
Ваши аргументы убедят любого новичка, который никогда не сталкивался с версткой, это точно.
В реальности же Вы просто спрятали всю сложность своего примера в других файлах, как это обычно делается в подобных манипуляциях. А пример с TailwindCSS максимально нелепый, вы просто накопипастили какую-то белиберду, чтобы она и выглядела, как белиберда. На самом деле же, код с TailwindCSS зачастую намного читабельнее Вашего.
Вот Ваш пример, примерно написанный на TailwindCSS:
Может отпугнуть, если не знаешь, что значат эти классы. Но даже если не знаешь, можно разобраться, если напрячься. А если умеешь с таким работать, это становится максимально удобно и понятно.
В Вашем же примере я не вижу, как всё стилизовано; чтобы что-то поправить, мне приходится искать файлы со стилями, а так еще импорты в десять других файлов и пошло поехало; если у меня уже есть класс, а конкретно тут нужно еще отступ добавить, что мне делать, это целая проблема; нужно придумывать имена для каждого элемента на странице; нужно переживать на специфичность, чтобы стили не накладывались; для каждого компонента нужно держать отдельный CSS-файл, а значит количество файлов и папок сразу удваивается; и т.д. и т.п.
Я делал и так, и так, и прекрасно понимаю все подводные камни обоих вариантов. И для меня абсолютно очевидно, что TailwindCSS намного превосходит любые Ваши предложения. А Вы никогда не писали на TailwindCSS, и в своем невежестве продолжаете проталкивать устаревшие подходы.
Валидация данных с API и валидация форм – это как раз таки самые очевидные кейсы использования.
Неочевидный кейс – это, например, использовать Zod вместо автотестов на фронтенде. Вместо того, чтобы писать тесты, вы можете любые данные на входе, например, в функцию проверять через
z.parse. Тогда при любой несостыковке при ручном проходе по интерфейсу тут же выпадает понятная ошибка на весь экран и баг тут же фиксится.Или же, когда два типа вроде как должны сходиться, но не сходятся, и TypeScript не понимает и ругается, можно вместо использования
as <type>, как это сейчас делается, писать тот жеz.parse, чтобы подогнать тип. Тогда и TypeScript доволен, и вы уверены, что нигде не накосячили.Еще можно валидировать параметры функции более тщательно, чем TypeScript это может.
Вот, например у меня функция, которая создает новый id:
TypeScript проверит на число, но мне нужно именно целое и только положительное.
Zod поможет:
То, что Вы описали, легко делается через
.refine(документация)В приведенной цитате из доки, когда говорится о "static type inference", имеется в виду как раз то, что Вы называете, "преобразование типов в runtime", а не
z.infer<typeof userSchema>.Если на Ваш взгляд это не является необходимым – окей, Ваше право не использовать это. Тогда Вам действительно не нужен zod, Ваша библиотека подходит куда лучше.
Но Вы не правы, если считаете, что не это, а что-то другое, является основной фишкой zod.
Как в доке описывается zod:
Zod is a TypeScript-first schema declaration and validation library. <...> The goal is to eliminate duplicative type declarations. With Zod, you declare a validator once and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures.
То есть основная идея – это то, что парсишь данные и получаешь на выходе корректно типизированные значения. Твоя же библиотека делает только самую простую часть – валидацию.
Классно, что есть такое упрощенное решение, но говорить, что ты сделал тот же zod, но в 10 раз быстрее, как ты описываешь себя в описании, мягко говоря, некорректно.
Если ты зачем-то хочешь тот же zod, но более оптимизированный (как будто в этом основная проблема твоего приложения), то стоит, скорее, смотреть в сторону Valibot. Но и то, это лишнее, жертвуем DX, чтобы сэкономить пару миллисекунд.
Что-то мне подсказывает, что вы не относитесь ни к первым, ни ко вторым)