N причин, чтобы использовать Create React App



    Create React App — отличный инструмент для быстрого старта React-приложений. Вы не тратите время на настройку Webpack, Babel и других привычных инструментов. Они заранее настроены и спрятаны, так что разработчики могут сфокусироваться на коде и бизнес-логике приложения.


    До выхода Create React App мне приходилось каждый раз при старте нового приложения копировать Webpack-конфиг и другие *rc-файлы из предыдущих приложений или же настраивать всё вручную. Это не занимало много времени, скорее, было скучно. Иногда приходилось понервничать, когда что-то не так сделал, и начинается: «Почему в том приложении работает, а здесь нет?». Особенно когда у тебя несколько приложений с более-менее одинаковыми конфигами. И тем более с релизом Webpack2 нужно будет опять всё перенастраивать и тратить время. (Спойлер: с Create React App нужно будет просто обновить версию react-scripts в package.json).

    Create React App предоставляет CLI-интерфейс для создания приложений с базовой структурой, устанавливает все нужные зависимости и добавляет в package.json скрипты для запуска, тестов и сборки приложения.

    npm install -g create-react-app
    create-react-app my-app
    cd my-app/
    npm start # yarn start

    Zero configuration! Разработчики не могут настраивать Webpack или Babel, пока не сделают eject.

    Если вы опытный пользователь и вас не устраивает стандартная конфигурация, можете сделать eject. В таком случае Create React App используется как генератор шаблонного кода.

    Команда npm run eject копирует все конфиги и транзитивные зависимости (Webpack, Babel, ESLint и т. д.) в ваш проект, чтобы вы могли их контролировать. Команды вроде npm start и npm run build не перестанут работать, но будут указывать на скопированные скрипты, чтобы их можно было модифицировать. После этого вы сами по себе.

    Почему я хочу не делать eject


    Во-первых, потому что эту операцию нельзя отменить. Но дело не только в этом. Вот еще несколько причин.

    Я хочу получать обновления Create React App

    Представьте, что команда Create React App решает перейти на Webpack 2 (а они это уже сделали), чтобы поддерживать tree-shaking и другие крутые фичи. В таком случае мне достаточно будет обновить версию react-scripts вместо того, чтобы обновлять конфиги во всех приложениях.

    Или, предположим, команда Create React App релизит Plugin System #670. Я бы с радостью использовал такую систему и даже создавал бы собственные плагины. Но, если eject был сделан, ничего не выйдет.

    Не люблю, когда в package.json много зависимостей

    Возможно, это мелочь, но я не хочу видеть в package.json кучу зависимостей babel*, eslint* и webpack*, которые я не использую напрямую в коде.

    Лишние конфиги и лишний код

    Я всегда поддерживаю чистоту в приложениях. После eject создаются директории scripts и config. А с ними — около десяти новых файлов по 50–200 строчек кода в каждом. Причем в большинстве случаев eject делают, чтобы поменять всего около пяти строк кода (добавить один новый Webpack Loader).

    Опять 25

    После того как я сделаю eject и отредактирую конфиги, нужно будет скопировать их в другие приложения, потому что чаще всего конфиги приложений (пресеты Babel, Webpack loaders и плагины) одинаковые.

    Почему мне нравится Create React App


    Это инструмент от разработчиков React

    Разработчики Create React App — это разработчики React. Я им доверяю и уверен, что они знают, как правильно разрабатывать React-приложения, реализуя все фичи с правильной связкой технологий в рамках проекта Create React App.

    В структуре приложения нет конфигурации и лишних файлов

    Поскольку я люблю порядок в приложениях, мне определенно нравится, что отсутствуют webpack.config, нет кучи *rc-файлов и зависимостей в package.json.

    Весь стек обновляется одной строкой



    Стек разработки фиксированный и стабильный

    В релизах Create React App присутствуют только stage-3 функции (release candidate). Иногда интересно поиграться с новыми фичами из секции draft, например, с do-expressions или null-propagation. Можно даже посмотреть на orthogonal-classes proposal, но использовать в продакшне — совсем не лучшая идея.

    Но если всё-таки использовать фичи draft и proposal, результат можно было бы описать примерно так:



    Функциональность этого инструмента быстро расширяется

    Я уверен, что количество фич инструмента будет быстро расти. Сообщество уже достаточно большое, и поступает много интересных идей и предложений. Вот некоторые из них:


    Некоторые треды закрыты или уже ушли в релиз. Но суть в том, что идей много. Даже появились сторонние инструменты для Create React App, вроде CRA generate: Scaffold a React component или CRAFT.

    Мой опыт работы с Create React App


    Благодаря Create React App наша команда отказалась от CSS Modules, React Toolbox и еще кое-каких библиотек, для которых нужна была дополнительная конфигурация Webpack.

    Кстати, react-toolbox-themr обеспечивает легкую интеграцию с React Toolbox с Create React App… Но описывать тему приложения в package.json не лучшая, как по мне, идея.

    И я по-прежнему не хочу делать eject!

    Работа с CSS

    В официальной документации, в секции Adding a CSS Preprocessor (Sass, Less etc.), подробно описано, как настроить работу с sass или less.

    Единственно ограничение — css modules.

    Вместо CSS Modules мы начали смотреть в сторону Glamor, Aphrodite, styled-components, Fela и JSS.

    Есть еще Radium, но мне не нравится использовать style для стилизации компонентов.

    В итоге мы используем свой, еще совсем новый подход — rockey.

    Описываем стили компонентов, используя Template Literals и отталкиваясь от реальных имен компонентов, вместо привычных CSS классов.

    На первый взгляд подход похож на styled-components, но на самом деле совсем другой.

    Загрузка из глобальных папок

    Достаточно сложно работать с кодом, которому требуются модули из родительских директорий:

    const dateUtils = require('../../../utils/date');

    Обычно в Webpack это решается с помощью конфигурации resolve.modulesDirectories. Как я уже писал, в CRA-приложении нет доступа к Webpack, но возможны два решения.

    Официальное — создать node_modules в директории src (Document src/node_modules as official solution for absolute imports #1065).

    Другой, более «красивый» способ — использовать переменную окружения NODE_PATH. Больше информации — в официальной документации Node.js Loading from the global folders.

    Советую использовать cross-env, чтобы кроссплатформенно устанавливать переменные окружения.

    "scripts": {
       "start": "cross-env NODE_PATH=src/scripts react-scripts start"
    }

    Если вы используете .env-конфиг, просто добавьте переменную NODE_PATH:

    NODE_PATH=src/scripts

    Переменные окружения

    Create React App по умолчанию поддерживает .env (используя dotenv-пакет). Просто создайте в корневой папке .env и запустите приложение. Не забудьте добавить каждой переменной префикс REACT_APP_. Больше информации — в официальной документации, в разделах Adding Custom Environment Variables и Adding Development Environment Variables In .env.

    Поддержка нескольких .env-конфигов

    Иногда полезно разделить конфиги по типу окружения (dev/test/prod). Например, вот .env.development:

    REACT_APP_GOOGLE_CLIENT_ID = XXX-YYY-ZZZ.apps.googleusercontent.com
    REACT_APP_API_PROTOCOL = http:
    REACT_APP_API_HOST = localhost:3000
    NODE_PATH = src/scripts
    PORT = 9001

    А вот .env.production:

    REACT_APP_GOOGLE_CLIENT_ID = ZZZ-YYY-XXX.apps.googleusercontent.com
    REACT_APP_API_PROTOCOL = https:
    REACT_APP_API_HOST = api.my-applicaton.com
    NODE_PATH = src/scripts

    Сейчас это можно сделать, установив dotenv и обновив npm scripts:

    "scripts": {
     "start": "node -r dotenv/config ./node_modules/.bin/react-scripts start dotenv_config_path=.env.development",
     "build": "node -r dotenv/config ./node_modules/.bin/react-scripts build dotenv_config_path=.env.production"
    }

    Но, скорее всего, в релиз попадет мой Pull Request — Support different env configs #1343.

    Какие .env*-конфиги можно будет использовать?

    • .env — стандартный (общий) конфиг;
    • .env.development, .env.test, .env.production — в зависимости от окружения;
    • .env.local — локальный конфиг для переопределения любых переменных в зависимости от окружения разработчика. Игнорируется системой контроля версий;
    • .env.development.local, .env.test.local, .env.production.local — локальный конфиг в зависимости от окружения. Игнорируется системой контроля версия.

    Приоритет конфигов (шаг пропускается, если файл конфига не существует):

    • npm test — .env.test.local, env.test, .env.local, .env;
    • npm run build — .env.production.local, env.production, .env.local, .env;
    • npm start — .env.development.local, env.development, .env.local, .env.

    Изменить порт dev-сервера

    Мы, например, не можем запускать приложение на 3000 порту, потому что работаем с Google Auth, который несколько лет назад был настроен на localhost порты 9001–9005. Конечно, мы можем изменить настройки Google Auth, но уже привычнее использовать именно эти порты.

    Добавьте переменную окружения PORT с помощью cross-env:

    "scripts": {
     "start": "cross-env PORT=9001 react-scripts start"
    }

    или .env-конфига:

    PORT=9001

    Дополнительная конфигурация

    Вот список возможных настроек с помощью переменных окружения:
    Variable Development Production Usage
    BROWSER + - Create React App открывает браузер, настроенный по умолчанию, но можно задать определенный браузер или установить none, чтобы отключить эту фичу. Также можно указать на Node.JS скрипт, который будет выполняться каждый раз при старте dev-сервера.
    HOST + - По умолчанию — localhost.
    PORT + - По умолчанию — 3000. Если он занят, Creat React App предложит запустить приложение на следующем доступном порте. Или можно задать определенный порт.
    HTTPS + - Если установлено в true — локальный dev-сервер будет запущен в https-режиме.
    PUBLIC_URL - + Обычно Create React App ожидает, что приложение расположено в корне веб-сервера или путь определен в package.json (homepage). Можно переопределить ссылку для всех ассетов. Это полезно, если вы используете CDN для хостинга приложения.
    CI + + Если установлено в true, Create React App будет обрабатывать warnings как ошибки. Запускает тесты без — watch параметра.

    Изменить конфиг Webpack: добавить плагины и поменять точку входа

    В качестве примера приведу две ситуации, когда мне это понадобилось:

    1. Добавить Webpack Offline Plugin.
    2. Сделать сборку только с одним компонентом из приложения.

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

    Добавьте в npm-scripts build:custom:

    "scripts": {
     "build:custom": "node scripts/customBuild.js"
    }

    Затем создайте scripts/customBuild.js:

    const webpack = require('react-scripts/node_modules/webpack');
    const craWebpackConfig = require('react-scripts/config/webpack.config.prod');
    const OfflinePlugin = require('offline-plugin');
    
    const config = {
      ...craWebpackConfig,
      plugins: [
         ...craWebpackConfig.plugins,
         new OfflinePlugin()
      ]
    };
    
    webpack(config).run(function(err, stats) {
      if (err !== null) {
        console.log('done');
      } else {
        console.log(err);
      }
    });

    В этом случае расширится только конфиг Webpack, а не react-scripts build. Не будет красивых логов, сравнения размеров текущего и предыдущего билда и других фич.

    Помните, что использование нестандартных загрузчиков (вроде yaml, markdown, dsv loaders и т. д.) и дополнительных плагинов делает ваше приложение сложнее и сложнее. И в некоторых случаях даже невозможно перейти на новый релиз Webpack.

    Вот почему я не люблю даже обычные css-loaders для Webpack. Всегда стараюсь подключать только js- или json-модули. CSS-файлы вполне подходят для конфигурации Webpack поля entry. Стараюсь никогда не подключать их с помощью функции require. Это делает приложение максимально зависимым от текущего сборщика.

    Babel presets and plugins

    Create React App пока не поддерживает расширение babel-конфига. Соответственно декораторы также не поддерживаются.

    Я даже делал Pull Request: Adding support for custom babel configuration #1357. Но его уже закрыли, и я полностью согласен с командой Create React App: не стоит засорять приложение кучей настроек.

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



    React scripts

    Фича, о которой почти никто не знает. Чуть больше информации можно найти в официальном треде на github — Document maintaining a fork of react-scripts as an alternative to ejecting. #682.

    React scripts — пакет, в котором реализованы все используемые скрипты (start/test/build) и конфигурирование всех используемых инструментов.

    То есть вы можете сделать форк, синхронизировать его с текущей версией и добавить нужный вам функционал.

    create-react-app my-app --scripts-version my-super-react-scripts,

    где my-super-react-scripts — ваша версия react-scripts.

    Например, есть custom-react-scripts с поддержкой декораторов, babel-preset-stage-0, LESS / SASS, CSS Modules (более подробно описано в статье Configure create-react-app without ejecting).

    Awesome Create React App

    Awesome Create React App — подборка интересных материалов, ожидаемых фич и FAQ. Также представлен список существующих react-scripts версий.

    Список ожидаемых фич в версии 0.10.0

    Runtime error overlay #1101

    При необработанных исключениях показывается диалог с ошибкой, очень похожий на ранее добавленную фичу, — Syntax error overlay. Отображается сообщение об ошибке, стек вызова и строка кода, где произошла ошибка. Диалог может быть скрыт по нажатию на Escape. Ошибка, как и ранее, дублируется в консоли.



    Upgrade to webpack v2 #1291

    Теперь всем пользователям Create React App нужно просто обновить версию react-scripts (twitter.com/…​status/819634786734112768) вместо того, чтобы читать гайды по миграции с Webpack 1 на Webpack 2. Подробнее о Webpack 2 можно почитать в статье Webpack 2 and beyond или What’s new in webpack 2.

    Dynamic import support #1538

    Очень клевая фича для асинхронной подгрузки модулей. Ранее для этого использовался require.ensure.

    import('./path/to/module).then(module => {
      // module.default
    });

    Add lint-staged + husky for prettier auto-formatting on commit #1759

    Автоматически запускает eslint для файлов в индексе и форматирует их с помощью prettier перед каждым коммитом.

    Пока реализована только как внутренняя фича для самого Create React App, но я очень надеюсь, что добавят в генерируемое приложение.



    И много других крутых фич:


    Конец

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

    Делая eject (либо при самостоятельной конфигурации), вы жертвуете всеми текущими фичами CRA (и фичами из новых релизов) ради того, чтобы добавить декораторы или еще какую-то мелочь.

    Конфигурирование Webpack, Babel или любого другого инструмента в рамках Create React App сделало бы Create React App более хрупким. И команда Create React App не смогла бы гарантировать идеальную работу и стабильность инструмента. Также это спровоцировало бы появление Create React App Issues, не связанных с Create React App.
    Plarium
    115,00
    Разработчик мобильных и браузерных игр
    Поделиться публикацией

    Комментарии 33

      0

      Недостаток конфигурации легко обойти, react-app-rewired прекрасен.

        0
        да, отличная штука, я как общался с Тимом, когда он занимался её разработкой. Но это все таки отдельный инструмент.

        Есть еще — custom-react-scripts — это кастомная версия react-scripts.

        create-react-app my-app --scripts-version custom-react-scripts
        


        Здесь подробнее про custom-react-scirpts — Configure create-react-app without ejecting
        Здесь можно почитать офф. инфу Document maintaining a fork of react-scripts as an alternative to ejecting #682
          0

          Не-не-не: custom-react-scripts — это форк, а react-app-rewired — врапер. Почувствуйте разницу.

            0
            да, форк react-scripts (не create-react-app), и этот подход официально поддерживается, я кидал ссылку на тред.
            И это как только будут новые фичи в react-scripts — они так же будут и тут.
        –1
        А чем вам css-модули не угодили?
          0
          ничем. CSS modules отличный инструмент, но в паре с CRA не работает
            0
            посмотреть что?
              0
              как прикрутить Styled-JSX и настроить абсолютные пути для импорта
                0

                так там нету ничего про CRA кроме ссылки на RAW

                  0
                  Абсолютные пути в импорте

                  Работают относительно папки src, пример:


                  import MyComponent from 'components/MyComponent'

                  Конфигурация babel-plugin-module-resolver
                  ['module-resolver', { 'root': ['src'] }]

                  Настройка WebStorm

                  Для папки src в контекстом меню выполнить: Mark Directory as > Resource Root.


                  Настройка Atom
                  • Установить плагин js-hyperclick.
                  • Для доменных компонентов прописывать в package.json путь до src:
                    "moduleRoots": ["../.."]
                    0

                    Собственно, я больше хотел обратить внимание на Styled-JSX.

              +3

              Интересно почитать про велосипедостроение на тему SSR для CRA. :)

                0
                Поддерживаю :) Ну, на самом деле велосипедов там нет, поскольку поддержка нулевая.
                  0

                  Не видишь суслика? А он там есть.

                  0
                  пока не поддерживается, но уже давно есть PR Export render function #1292 и теоретически он попадет в релиз 0.10.0
                    0
                    cra побоку как ты делаешь ssr в случае с redux. Все банально при любом раскладе — определить экшены, выполнить, отрендерить, влить стор в html и распарсить на фронте
                      +1

                      Покажите код :)

                        +2
                        Да вообще как здрасьте. Как вывести космический корабль на орбиту? Да все банально при любом раскладе — определить траекторию, спроектировать корабль (незначительная мелочь), построить его, запустить двигатели и произвести взлет.

                        Конечно, Redux — не «rocket science», но за этим вот «выполнить экшены» — куча тех еще компромиссов и ухищрений.
                          –1

                          Ну разве что немного подумать, как посадить первую ступень на плавучую платформу :)

                      +3
                      "start": "cross-env NODE_PATH=src/scripts react-scripts start"
                      

                      И как такие костылищи прикажете поддерживать IDE?
                      Красивым кодом они это еще называют.
                        +1

                        Развешивание ярлыков. У меня есть ответы для Atom и WebStorm, например.

                          +3
                          И вы их тут не напишите? Тайное знание?
                            0

                            Написал ранее, см. выше.

                        +2

                        В конце концов всё свелось к такому:


                        Это так классно! Из коробки можно делать почти всё! Но если вы хотите чего-то большего, то делайте eject, но если сделаете, то перестаёте обновляться, так что лучше не eject'ить. Но если всё же хотите что-то новенькое, то можете костыльнуть так и вот так и у вас будет почти то же самое, что и с CRA, но это будет работать немного не так.

                        Лично для меня не является аргументом


                        Лишние конфиги и лишний код

                        отсутствуют webpack.config, нет кучи *rc-файлов и зависимостей в package.json.

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

                          0
                          React-create-app безусловно крутая штука что бы быстро стартануть новый проект.

                          Вот еще одна, но с одним приятным отличием — сразу получаете sandbox и возможность документирования компонентов в маркдауне https://github.com/OpusCapitaBES/js-react-showroom-client

                          image

                            0
                            А как этим пользоваться — держать отдельным приложением куда выносятся все компоненты из других проектов, или прикручивать к каждому проекту?
                              0

                              Сейчас удобнее к каждому. Отдельным приложением тоже можно, но это требует особого оформления пакетов — что бы файлы доки попадали в npm пакет + компоненты по своим именам торчали из main файла (бандла) пакета. Ведутся работы над оптимизацией этого варианта.

                            +2
                            Не понимаю, почему многие кто делают какие-то boilerplate с webpack делают webpack.dev.config и webpack.prod.config, хотя реально 80% файла одинаковые, более того, нужно думать о том, что ты поддерживаешь 2 файла, вместо 1, а если это еще деплоить в Docker и на разные environment (local, test-*, stage, prod) это получается 2 файла костылей.

                            п.с. в своих проектах это всегда 1 файл.
                              0
                              Чтобы не городить ветки ифов, очевидно. У нас 5 конфигов — общий, вайтлейблинг и расширяющие их: дев, прод и сторибук. Различия везде есть, и вместо ветвей условий мы используем композицию маленьких кусочков.
                                0
                                А можно подробней, что выносится в отдельные dev/prod конфиги? Я использую общий конфиг на все энвайрменты, возможно ваши примеры позволят мне переосмыслить подход.
                                  0
                                  В основном для prod это всякие DefinePlugin'ы, минифаеры, оптимизаторы, экстракторы. Для dev — HMR, другие дефайны, настройки проксей и т.п.
                                0
                                Использую модуль webpack-config
                                Позволяет вынести общую часть в базовый конфиг, а в конкретных конфигах его расширять
                                У меня это расширение большей частью сводится к редактированию DefinePlugin

                                Кроме того можно настройки редко используемых(либо опциональных) плагинов вынести в отдельные файлы, и подключать/отключать одной строчкой
                                Например unused-files-webpack-plugin, webpack-bundle-analyzer для локальной работы/анализа
                                Настроенный UglifyJsPlugin только для серверных сборок

                                Как итог, в файле под каждое окружение находится его более конкретное описание, отличающее его от других конфигов, и при этом без if-ов в неожиданных местах

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

                              Самое читаемое