Это произошло в понедельник 13 февраля, мир больше не будет прежним. Открыта вакансия:



Для работы над нашими проектами мы ищем сильного front-end разработчика. Вам предстоит амбициозная задача: внедрить компонентный подход в разработку всех текущих и новых проектов компании.

Отлично, работаем дальше! Выполняю "тестовое задание".


Процесс переноса нашего любимого сайта в react-компоненты черезвычайно прост. Нужно кликнуть кнопку [квадратик со стрелочкой курсора] в Chrome DevTools, скопировать выбранный HTML-блок в файл temp.html, добавить аттрибуты вида data-component="MyReactComponent" к будущим компонентам, и запустить в консоли:


> html2react ./temp.html

Результат в ./components/ — готовые JSX-скрипты.


В чем прелесть компонентов? Декомпозиция задач более очевидна, оценивать трудозатраты можно точнее, в итоге проще управление процессом разработки. Постепенно сформируется понимание, как разделять блоки верстки на компоненты: просто много кода на один компонент, какой-то интерактив, дополнительный функционал. Главное пока не увлекаться, первая задача — Minimum Viable Product (MVP).


Ох, сколько же бывалых веб-разработчиков оттолкнула каша из HTML-тегов внутри JavaScript-кода. У меня аллергия прошла через три года, а тут ещё ES6 подоспел — кошмар ретрограда. Но всё к лучшему, за это время экосистема React-а выросла и окрепла. Как раньше люди жили без Redux-а, наверно мучились. :)


Отличная штука create-react-app, избавляет от небходимости настройки node-приложения на текущем начальном этапе, при том что не навязывает ничего лишнего.




И вот появилась первая страничка Хабра на localhost:3000 почти неотличимая от оригинала — это щастье!


Встречаются и ошибки в верстке, и legacy-блоки; код требует вдумчивого просмотра и редактуры. Заменил ссылки по шаблону "https://habrahabr.ru/" на "/#/", благо они почти везде абсолютные. Подключил @font-face, восстановил работоспособность плашки "#scroll_to_top".


// Переписал вызовы 

<a ... onclick="if (typeof ga === 'function') { ga('send', 'event', 'footer', 'links', 'ios_app'); }" >

// на новый лад 

<a ... onClick={ga.bind(void 0, 'footer', 'links', 'ios_app')} >

// и добавил функцию

export const ga = (eventCategory, eventAction, eventLabel) => {
  if (typeof window.ga === 'function') {
    window.ga('send', 'event', eventCategory, eventAction, eventLabel)
  }
}

Задействую Redux, пока наполнил фейковые данные в initialState. Уже можно добавить новую статью из формы в Store. Сделал некоторые статические страницы по ссылкам из колонки "Инфо" в подвале, роутинг работает сносно, но требуется реализовать крошки в разделе "Помощь". Применяя "react-helmet", разблюдовал подключение css-файлов (т.к. страница 404 оформлена иначе). Использую "reselect" (пример в components/PostTeaserList.js — фильтр по потокам), "redux-act" (пример в reducers/editPost.js). Для обработки сайд-эффектов подключил "redux-thunk". Инлайновые стили добавляю с помощью "styled-components" (пример в components/InfoHelpPost.js).


Общее правило — не зацикливаться на деталях. Если задача не решается за 15 минут, или просто отвлекает, то откладываю с пометкой TODO. Есть мнение, что 85% времени занимают мелкие доработки. Важно быстро вырастить скелет, а наращивать мясо — последующие этапы через итеративную непрерывную интеграцию.


PS


Если вам нужно быстро реинкарнировать старое веб-приложение, тогда примерьте модный компонентный подход (привет, Delphi'95 & Rapid Application Development).


Леонид Аркадьевич, пользуясь случаем, ещё передаю приветы Mail.ru и Fast Line Ventures; упрощается "адаптация" успешных забугорных проектов. Кстати, для инди-разработчиков это способ поднять свой маленький свечной заводик: экономия на ТЗ, на дизайне, на верстке. Помните, что идеи ничего не стоят? Реализация тоже подвержена удешевлению.


Описанный метод переноса верстки в react-компоненты отлично применим и для текущих проектов на React, если ваша команда разделена на верстальщиков и разработчиков.


Когда хочется освоить новую технологию (например React), то лучший метод обучения — это копирование существующего проекта с использованием требуемой технологии. Как минимум, для портфолио на GitHub. Исходники проекта обновляются тут.


Демо: yobr.ru

Поделиться с друзьями
-->

Комментарии (49)


  1. denismaster
    18.02.2017 09:43
    +5

    Ох, сколько же бывалых веб-разработчиков оттолкнула каша из HTML-тегов внутри JavaScript-кода. У меня аллергия прошла через три года, а тут ещё ES6 подоспел — кошмар ретрограда. Но всё к лучшему, за это время экосистема React-а выросла и окрепла. Как раньше люди жили без Redux-а, наверно мучились. :)

    В том то и дело, что каша из кода и тегов — это далеко не серебрянная пуля, как бы React не был хорош. Да, модно, да, решает задачу, но всегда найдется альтернативный подход, а у него — сторонники.


    1. comerc
      18.02.2017 14:17
      +2

      Беда в том, что нет единственно правильного ответа. Пока React победил в моих изысканиях. Предыдущая ставка на Meteor — потерянное время.


      1. vintage
        18.02.2017 15:32
        +5

        С нетерпением ждём следующей серии в изысканиях :-)


        1. comerc
          18.02.2017 15:40

          Вообще-то я очарован Clojure. Но такую корову не продать.


      1. S_A
        18.02.2017 16:12

        Можете пару слов о Метеоре, пожалуйста? Начинаю на нём сейчас серьезный проект, интересны чужие грабли.


        1. comerc
          18.02.2017 16:27
          +1

          Слишком интимный вопрос, многих ранила моя статья эту тему. Отвечу в личку.


        1. comerc
          18.02.2017 16:45
          +1

          1. S_A
            18.02.2017 16:50

            Спасибо, очень полезно. Как-то упустил статью.


        1. comerc
          18.02.2017 16:51
          +1

          Вот это самая лучшая статья по React+Redux из тех, что я перелопатил. Три раза перечитывал. И постиг Дзен.


        1. comerc
          19.02.2017 00:01

          Ещё хочу дать самые лестные рекомендации проекту Monster Lessons: JavaScript, React, Redux. Превосходная подача материала!


        1. movl
          19.02.2017 06:28
          +2

          У меня был опыт работы с метеором только на внутренних проектах, и ни разу не разочаровался в нем. Из примеров — это приложение, интегрированное с основным проектом на рельсах, созданное для совместной обработки заказов пользователей, и приложение для администрирования нескольких игровых серверов (mongodb).


          Мне понятно, что примеры достаточно специфичные, также стоит учитывать, что я писал их один. И также я представляю, что с проектами на метеоре может быть множество проблем. Но категорически не могу согласиться с проведением параллелей с React, эти инструменты решают разные задачи, причем могут это делать совместно, по моему мнению, метеор — это в первую очередь протокол клиент-серверного общения.


          Из того, что мне очень нравится в метеоре: он дает высокую скорость при создании скелета приложения, дает возможность писать минимум серверного кода (и, как правило, синхронного кода) и дает данные в реальном времени на клиенте. Из специфичного, мне нравится blaze, и вообще, то как реализована реактивность на фронтэнде. Из главных минусов, по моему мнению: это то что все завязано на монге и ddp, и, как следствие, узкая область применимости, но это и есть суть фреймворка. Я не считаю, что клиентская часть приложения может быть проблемой в принципе, так как есть полная свобода в выборе инструментов, но, конечно, есть свои особенности, вытекающие из протокола. Также я не могу судить о возможных проблемах, связанных с высокой нагрузкой, но судя по различным публикациям в интернете — дела обстоят более-менее, и это уже индивидуальный вопрос для каждого проекта.


          Сам бы я решился начать новый проект на метеоре, если нужны данные в реальном времени на клиенте, если не нужна сложная бизнес-логика и если монга подходит в качестве хранилища, со всеми вытекающими критериями. Наверное, такими условиями отбрасываются 95% проектов, если не больше, и, конечно, есть множество других вопросов, которыми стоит задаться при выборе. Но в общем случае, я считаю, что метеор хорошо подходит для приложений, где важна коллаборация в реальном времени, например: форумы, хелпдески, системы управления задачами и т. д.


          Возможно из-за удачного стечения обстоятельств, но я не натыкался на как таковые грабли, связанные с метеором. Была особенность: одно приложение надо было завязать на множество различных баз данных, но решение с полпинка было найдено, причем с сохранением всех плюшек метеора. Периодически мне встречается мнение, что метеору место на помойке, с чем никак не могу согласиться, и имея опыт работы с ним, в будущем с удовольствием выберу его снова, если будет такая возможность и если будет подходящий проект. Это все несколько общие слова, но если есть конкретные вопросы, готов ответить в личных сообщениях.


          1. S_A
            19.02.2017 09:32

            Спасибо за развернутый комментарий!

            Но в общем случае, я считаю, что метеор хорошо подходит для приложений, где важна коллаборация в реальном времени, например: форумы, хелпдески, системы управления задачами и т. д.
            Разделяю это мнение, правда кругозор в JS-фреймворках у меня не особо большой.


          1. comerc
            21.02.2017 16:29

            Ваш коммент больше, чем моя статья. Спасибо за аргументы.


  1. vintage
    18.02.2017 10:40
    +2

    При переходе между страницами сначала появляется контент, а только чрез пол секунды — к нему подцепляются стили — всё очень неприятно скачет. И это на одностраничном сайте.


    Добавление поста не работает, да и выглядит паршиво. Не удалось реализовать за 15 минут?


    Я так и не понял, зачем вам тут потребовался реакт, чтобы нарисовать несколько статичных html-шаблонов, практически без динамики.


    1. comerc
      18.02.2017 11:16
      -1

      При переходе между страницами сначала появляется контент, а только чрез пол секунды — к нему подцепляются стили — всё очень неприятно скачет. И это на одностраничном сайте.

      Подправил костылем, как заставить Helmet подключать стили правильно — может кто подскажет?


    1. comerc
      18.02.2017 11:20

      Добавление поста не работает

      F12, после отправки формы нужно смотреть сюда:



      Я говорил про добавление в Store.


      1. vintage
        18.02.2017 11:37

        А что толку от добавления в стор без обновления интерфейса?


        А helmet правильно стили добавляет, но делает это динамически, во время рендеринга. Очевидно, для продакшена такой подход не годится.


        1. comerc
          18.02.2017 12:42

          А helmet правильно стили добавляет, но делает это динамически, во время рендеринга. Очевидно, для продакшена такой подход не годится.

          пробовал бороться с ним вот так, локально помогало, а в продакшене опять беда:


            componentWillMount() {
              document.body.style.display = 'none'
            }
          
            componentDidMount() {
              // HACK стили подключаются в Helmet после рендеринга страницы
              setTimeout(
                () => document.body.style.display = 'block'
              , 100)
            }


          1. VolCh
            18.02.2017 13:14

            react-helmet, по-моему, слабо заточен на работу с ресурсами, требующими загрузки. Для них нужно маунтить основной компонент, когда ресурс уже загружен (чего может вообще никогда не произойти, например из-за 404). Он хорошо работает, когда нужно не внешний стиль/скрипт подключить, а прямо в тегах style/script писать css/js. А чем вам что-то вроде


            import React from 'react';
            
            import styles from './styles.css';
            
            export default class HabrPage extends ReactComponent {...};

            не нравится?


            1. comerc
              18.02.2017 13:26

              Правильная постановка вопроса — половина решения. Нужно отловить момент загрузки скриптов в Helmet!


              А чем вам что-то вроде не нравится?

              Всё дело в том, что для 404 на Хабре подключаются другие стили (смотри /components/NotFound.js). Т.е. нужно было как-то разблюдовать. Импорт же подключает стили в проект намертво. Есть мысли подгружать саму страницу динамически, используя require.


              1. VolCh
                18.02.2017 13:44
                +1

                А как-то так:


                import React, { Component } from 'react'
                import Helmet from 'react-helmet'
                
                import styles from './../../public/styles/access_deny.css'
                
                class NotFound extends Component {
                  render() {
                    return (
                      <div id="layout">
                        <Helmet
                          defaultTitle="Хабрахабр"
                        />
                        <div className={styles.main}>
                          <div className={styles.logo}>
                            <a href="/#/" title="На главную страницу"><img alt="" src="https://habrahabr.ru/images/logo.svg"/></a>
                          </div>
                
                          <h1>Страница не найдена</h1>
                          <p>Страница устарела, была удалена или не существовала вовсе</p>
                
                          <div className={styles.buttons}>
                            <a href="/#/" className={styles.button}>Вернуться на главную</a>
                          </div>
                        </div>
                      </div>
                    )
                  }
                }
                

                Вообще говоря, компонентный подход предполагает, что и js-код, и разметка, и стили хранятся если не в одном файле (есть любители CSS в JS непосредственно писать, но меня они в удобстве подхода не убедили), то очень близко друг от друга, как-то так:
                src/components/NotFound/index.js
                src/components/NotFound/styles.css


                При переделке существующего приложения на реакт, я просто в каталог каждого компонента копировал все стили, импортировал их в JS, а уж потом в каждом отдельном компоненте вычищал лишнее.


                1. comerc
                  18.02.2017 13:56

                  Спасибо, до меня дошло! За лесом не видно деревьев. Так можно тупо переопределить стили для каждого HTML-тега в компоненте NotFound.


                  1. VolCh
                    18.02.2017 14:01

                    Так можно определить стили вообще для каждого компонента и забыть про них в других местах :)


                    1. comerc
                      18.02.2017 14:09

                      Так и было сначала, использовал другую утилиту для извлечения компонентов. Но она не понимает русские буквы и для каждого компонента добавляет id, а если id были определены в первоначальной верстке, то их затирает. В морг.


                      1. VolCh
                        18.02.2017 14:20

                        Я ручками всё делал :)


                        1. comerc
                          18.02.2017 14:21

                          В режиме хакатона — нереально.


          1. shybovycha
            18.02.2017 13:37
            +2

            Судя по комментариям в этом треде, напрашивается мысль "I had 99 problems. Then I used React. Now I have 101 problem."


            В чем суть статьи? Показать, как худо-бедно сделать драфт? Или как использовать все вышеперечисленные библиотеки (react-helmet, redux-act, redux-thunk)? Но ведь ничего из этого нету в статье...


            1. comerc
              18.02.2017 13:49
              -2

              Пока не хватает примера только для redux-thunk. Остальное все есть в исходниках, в статье указано, куда смотреть.


              1. shybovycha
                18.02.2017 13:54

                Ну так почему бы не не уместить это все в статью?


                1. comerc
                  18.02.2017 14:04

                  Первые пять минут фильма "Быстрее пули" со Скалой — шедевр. Потом всё скатилось, как обычно.


                  Краткость — сестра сами знаете чего.


                  1. shybovycha
                    18.02.2017 14:08
                    +4

                    По-моему вы не поняли, что я пытаюсь донести. Высказывание "краткость — сестра таланта" хорошо работает для Твиттера. На блогах вроде Хабра или Медиума, как мне кажется, пользователи хотят видеть статьи, раскрывающие какую-либо тему. Ссылку на репозиторий гитхаба можно уместить и в 140 символов.


                    1. comerc
                      18.02.2017 14:11
                      -1

                      Все дело в том, что суть статьи осталась за горизонтом. :)


  1. Garrett
    18.02.2017 13:41

    восстановил работоспособность плашки "#scroll_to_top"

    Самое главное на сделано! xD


    1. comerc
      18.02.2017 13:43

      Не понял, я что-то упустил? :)


      1. Garrett
        18.02.2017 13:51

        Как раз наоборот! Уже не знаю сколько долго оно на хабре в хроме не работает, но я уже даже и не пытаюсь пользоваться этим =)


        1. comerc
          18.02.2017 13:58

          Тестировал исключительно в Хроме — вроде всё пучком. Хочется немного подробнее, ведь интересно же!


  1. herr_kaizer
    18.02.2017 15:49
    +12

    А о чем статья?


    1. comerc
      18.02.2017 16:35

      О вискасе!


  1. andreylat
    18.02.2017 17:42
    +1

    Я правильно понял, что это все только фронтэнд без серверной части и сохранения?


    1. comerc
      18.02.2017 18:46

      Именно, и в этом вся прелесть. Есть конечно SSR, благодаря которому сможешь работать, как в привычном PHP. Но в данном примере все выполняется на клиенте. Если собрать под Electron-ом, то получим кросс-платформенное десктоп-приложение. Если заменить React на ReactNative, то получим мобильное приложение. Благодаря Redux-у, определена архитектура круговорота данных в приложении. Дальше нужно подключиться к внешнему REST-API или Websocket-серверу. И можно купить backend, как услугу, засматриваюсь на scorocode.ru


  1. novoselov
    18.02.2017 18:17
    +1

    Ох, я уже и забыл как выглядит «нативный» хабр :)
    StyleBot уже давно скрывает все мусорные блоки, объявления, кросс-ссылки.
    Жаль родительский сайт для сохранения скриптов лежит, кто-нибудь знает достойные альтернативы StyleBot?


    1. comerc
      18.02.2017 18:53

      Спасибо за лестный эпитет. Но до нативного Хабра ещё ой как далеко.


      1. comerc
        18.02.2017 20:13
        -1

        Понял, что затупил. Но все равно спасибо, "ваш отзыв очень важен для нас". :)


    1. riot26
      18.02.2017 19:24

    1. wakh
      18.02.2017 19:29

      Внезапно, а ведь ещё недавно «всё было». Впрочем, не первый раз.


  1. ProgramerNikita
    19.02.2017 09:55

    небольшая ошибочка, не щастье, а счастье


    1. comerc
      19.02.2017 12:33

      В данном случае именно щастье — это высшая форма банального счастья :)


  1. Alex_T666
    19.02.2017 12:22
    +1

    Мне кажется, что «слямзить», это значит — «украсть».


    1. comerc
      19.02.2017 12:34

      Только если оставить в кавычках.