Как собрать react приложение сделанное в react-create-app?
сделал приложение на react redux + mock данные на локолхосте все работает как теперь на хостинг залить , нужну webpack писать?
- Вопрос задан более трёх лет назад
- 6214 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 1
Full stack developer (Python/Django, React.js)
npm run build or yarn build
Ответ написан более трёх лет назад
Нравится 3 4 комментария
frolldoll @frolldoll Автор вопроса
Это не работает , сбилдил и открыл , в консоле ошибок нет но пустой экран может условия какие что бы билдить или что мне делать.

frolldoll, если вы сбилдите и попытаетесь открыть без использования веб сервера то вы ничего не увидите. Нужен любой web server.

кстат после команды build есть инструкция по запуску локального сервера (прям в косноли — советую внимательно читать что пишут вам инструменты, это актуально всегда но для экосистемы react вдвойне, команда react много важных вещей пишет в косноли, в ряде случаев сообщения ошибок содержат ссылки на обсуждения их решений)
Как создать React проект?
В официальной документации reactjs есть отдельный раздел в котором описываются способы создания нового React-приложения (Create React App, Next.js, Gatsby, другие наборы инструментов и даже создание с нуля).
Для создания и дальнейшей разработки приложения обычно используют Create React App.
Create React App — удобная среда для изучения React и лучший способ начать создание нового одностраничного приложения на React.
Инструмент настраивает среду для использования новейших возможностей JavaScript, оптимизирует приложение для продакшена и обеспечивает комфорт во время разработки.
Create React App не обрабатывает бэкенд логику или базы данных, он только предоставляет команды для сборки фронтенда, поэтому вы можете использовать его с любым бэкэндом. «Под капотом» используются Babel и webpack, но вам не нужно ничего знать о них.
Для создания проекта выполните команды:
npx create-react-app my-app cd my-app npm start
Когда ваше приложение готово к развёртыванию в продакшене, запуск команды npm run build создаст оптимизированную сборку вашего приложения в папке build.
Развертывание React-приложения
Когда мы имеем дело с большим проектом, в репозитории которого накопились десятки тысяч строк кода, иногда единственным здравым решением кажется все переписать с нуля, а не оптимизировать. С точки зрения бизнеса может возникнуть вопрос: а почему вообще нужно оптимизировать или даже переписывать приложение, если оно работает? Дело в том, что по мере роста кодовой базы есть вероятность увеличения дублирующихся компонентов/фрагментов кода, появления устаревших участков, которые тормозят сборку, но полезной нагрузки уже не несут. Это негативно влияет на скорость работы приложения и увеличивает срок разработки.
В этом кейсе мы покажем, как улучшить имеющееся решение с точки зрения архитектуры, а также рассмотрим библиотеки и их особенности, которые помогут сделать приложение быстрее.
В данном примере мы имеем дело с довольно объемной кодовой базой, UI которой обрабатывает большие массивы данных и выводит их на экран в виде списков, таблиц, графиков. Поэтому нам важно обеспечить гибкость нашего приложения как в плане сборки бандла, так и для развертывания в разных средах. И, конечно, иметь в рукаве самые последние фичи, позволяющие делать наш код красивым, понятным и читаемым.
Статья будет полезна тимлидам и техлидам проектов, а также разработчикам, которые столкнулись с развертыванием крупных неоптимизированных React-приложений.

Сборка приложения
Для начала выберем удобный механизм развертывания приложения, статика которого максимально оптимизирована.
Для сборки можно взять create-react-app или сборщики модулей, которых также немало.
Вариант с create-react-app подойдет, если мы готовы пожертвовать гибкостью, а иногда и безопасностью. Что это значит?
Во-первых, create-react-app использует под капотом webpack со всеми необходимыми плагинами. Если в репозитории подключен depend-bot, который следит за актуальностью пакетов, а также их зависимостей, он может выявить устаревший пакет или пакет с уязвимостью, обновление которого лежит на разработчиках CRA. Также минорные версии пакетов обновляют явно не в первую очередь.
Во-вторых, добавление разных плюшек в сборку потребует инжекта webpack конфига, а это практически то же самое, что писать конфиг с нуля самому и подписываться на его поддержку. Поэтому CRA в данном примере использовать не будем.
Если же рассматривать сборщики модулей, то самое гибкое решение на данный момент — webpack 5. Именно его и возьмем за основу, так как основное требование — гибкая и мощная настройка проекта.
Требования к сборке на webpack:
- Иметь возможность задавать node_env (development, production, test и т.д.) и влиять на конечный bundle через них.
- Иметь возможность задавать любые переменные окружения через конфиги и подключать нужные конфиги в зависимости от node_env.
- Настроить свои aliases для экспорта модулей.
- Подключить typescript, eslint, prettier.
- Подключить все необходимые транспайлеры.
- Добавить возможность динамического import react-компонентов.
- Оптимизировать все что можно и нужно.
- Настроить процессы коммитов по нашему git-flow через конфиг.
- Должно работать на всех платформах.
Сразу опишем основной стек приложения, так как его выбор будет оказывать сильное влияние на сборку проекта. Обратите внимание, что версии библиотек могут отличаться от актуальных — в данном случае мы описываем конкретный кейс с теми версиями, с которыми непосредственно велась работа.
Название
Версия
Описание
react, react-dom
Здесь без комментариев
react-router-dom
Нам нужен роутинг, для удобства и связки в эпиках будем использовать вместе с connected-react-router ^6.*.*
redux
Для нашего store
redux-observable
Для обработки запросов
rxjs
Для redux-observable и генерации событий
immer
Для иммутабельности store
reselect
Для мемоизации store
styled-components
Для генерации динамического css
react-virtualized
Для виртуализации данных
react-intl
Для поддержки нескольких локализаций
@loadable/component
Для динамического импорта
react-final-form
Для написания правильных пользовательских форм ввода
Константы webpack
Для поддержки конфигурации webpack нам понадобится большое количество констант. Обычно это названия директорий или пути к файлу. Предлагаем следующий список констант:
// Modules const path = require("path"); // Constants from path const APP_DIR = process.cwd(); const ASSETS_FOLDER = "assets"; const SOURCE_FOLDER = "src"; const PUBLIC = "public"; const BUILD_FOLDER = "build"; const CACHE_FOLDER = ".cache"; const PREFIX_PATH = "@" // Это наш alias для каталога src const PATH_TO_PROJECT = path.resolve(APP_DIR, SOURCE_FOLDER); const PATH_TO_PUBLIC = path.resolve(APP_DIR, PUBLIC); const PATH_TO_ASSETS = path.resolve(APP_DIR, ASSETS_FOLDER); const PATH_TO_BUILD = path.resolve(APP_DIR, BUILD_FOLDER); const PATH_TO_CACHE_FOLDER = path.resolve(APP_DIR, CACHE_FOLDER); // Mode const DEVELOPMENT = "development"; const PRODUCTION = "production"; const < NODE_ENV >= process.env; const ENV_LIST = [DEVELOPMENT, PRODUCTION]; const VALID_NODE_ENV = NODE_ENV && ENV_LIST.includes(NODE_ENV) ? NODE_ENV : PRODUCTION; // Если node_env не валиден, заменяем своим дефолтом. const IS_DEVELOPMENT = NODE_ENV === DEVELOPMENT; const IS_PRODUCTION = NODE_ENV === PRODUCTION; const IS_BUNDLE_ANALYZE = process.env.IS_BUNDLE_ANALYZE || false; // Это для режима анализа бандла, о нем немного позже. // OS const OS = < IS_WINDOWS: process.platform === "win32", >;
Отдельно стоит выделить объект OS. Он нам понадобится при написании eslint конфига, к нему мы еще вернемся.
Конфиги и переменные окружения
Будем иметь в виду, что для каждой среды в package.json своя команда, в которой пробрасывается нужный env_variable.
"scripts": < "start": "cross-env NODE_ENV=development webpack serve --config ./webpack.config.js", "build": "cross-env NODE_ENV=production webpack --config ./webpack.config.js", "analyze-dev": "cross-env NODE_ENV=development cross-env webpack serve --config ./webpack.config.js", >
Также создадим конфиг в корне проекта для каждой из сред со следующим форматом имени:
где node_env любая среда.
Если нужно создать шаблон, тогда добавляем еще нейминг, например:
Прописываем его в .gitignore, и любой разработчик копипастит и переименовывает его по своему усмотрению.
NODE_ENV = development HOST = localhost PORT = 3000 VERSION = 1.0.0 CLIENT_ID = xxxx-xxxx-xxxx-xxxx
В него можно сразу добавить полезные переменные, например, HOST и PORT — для среды develop, чтобы webpack четко знал, где поднимать свой webpack-dev-server, а также API, чтобы знать, на какой адрес отправлять запросы клиента.
Webpack необходимо разбить архитектурно так, чтобы не испытывать муки во время поддержки. Нам должно быть только приятно или, как минимум, не больно. =)
Поэтому в корне проекта создаем каталог webpack и заводим в нем следующие каталоги:
- loaders — наши loaders (babel, sass, less и т.д.) для загрузки в корень конфига.
const getBabelLoader = () => < const loader = < loader: "babel-loader", options: < configFile: path.join(APP_DIR, ".babelrc"), >, >; return loader; >; module.exports = < getBabelLoader >;
2. optimization — сюда будут входить модули оптимизации, которые не попадают под другие категории. Например, terser плагин указывает webpack, как сжимать код.
const TerserPlugin = require("terser-webpack-plugin"); const terser = () => < const plugin = new TerserPlugin(< terserOptions: < parse: < ecma: 10, >, compress: < ecma: 5, warnings: false, comparisons: false, booleans: true, collapse_vars: false, if_return: true, sequences: true, unused: true, conditionals: true, dead_code: true, evaluate: true >, mangle: < safari10: true, >, output: < beautify: false, ecma: 5, comments: false, ascii_only: true, >, >, parallel: true, >); return plugin; >; module.exports = < terser >;
Основные параметры конфига:
- ecma — стандарт JavaScript, по умолчанию 5 (ES5)
- booleans — оптимизация условных выражений: !!a ? b : c → a ? b : c
- comparisons — оптимизация логических выражений: a = !b && !c && !d && !e → a=!(b||c||d||e)
- collapse_vars — выборочное удаление переменных var и const, которые не переиспользуются
- if_return — оптимизация условий за счет return
- sequences — объединение операторов через запятую
- unused — удаление переменных и операторов, на которые отсутствуют ссылки (неиспользуемый код)
- conditionals — применение оптимизации к условным выражениям
- dead_code — удаление кода, который никогда не выполнится
- evaluate — замена константных выражений результатом вычисления (если возможно)
С более полным описанием всех параметров можно ознакомиться тут.
- optimization-presets — здесь храним готовые наборы пресетов, полученные из пункта 2.
const getOptimizationMainPreset = () => < const optimization = < minimize: IS_PRODUCTION, minimizer: [ terser(), cssAssets(), ], splitChunks: getSplitChunks(), runtimeChunk: 'single' >; return optimization; >; module.exports = < getOptimizationMainPreset >;
- plugins — наборы плагинов для webpack.
'use-strict'; // Modules const LoadablePlugin = require('@loadable/webpack-plugin'); // Constants const < IS_PRODUCTION, >= require('../utils/constants'); const getLoadableWebpackPlugin = () => < const plugin = new LoadablePlugin(< filename: 'stats-loadable.json', writeToDisk: IS_PRODUCTION, >); return plugin; >; module.exports = < getLoadableWebpackPlugin >;
- plugins-loader — лоадеры плагинов из пункта 4.
const getMainPluginsLoader = () => < return [ getProgressBarPlugin(), getRefreshPlugin(), IS_PRODUCTION && getCleanWebpackPlugin(), getForkTsCheckerWebpackPlugin(), getDefinePlugin(), ].filter(Boolean); >; module.exports = < getMainPluginsLoader >;
- presets — готовые пресеты.
// Loaders const < getStyleLoader >= require("../loaders/style-loader"); const < getCssLoader >= require("../loaders/css-loader"); const < getPostCssLoader >= require("../loaders/postcss-loader"); const getCssPreset = () => < const preset = < test: /\.css$/i, use: [ getStyleLoader(), getCssLoader(), getPostCssLoader(), ], >; return preset; >; module.exports =
- utils — константы, дополнительные фичи для webpack.
Имея такую архитектурную разбивку, получаем большое количество тонко настраиваемых модулей, которые легко комбинировать в готовые webpack конфиги.
Особое внимание уделяем aliases.
// Modules const fs = require("fs"); const path = require("path"); // Constants const < PATH_TO_PROJECT, PREFIX_PATH >= require("./constants"); const DEFAULT_ALIASES = < redux: "redux/src", [PREFIX_PATH]: path.join(PATH_TO_PROJECT), >; const getDirectories = () => fs .readdirSync(PATH_TO_PROJECT, < withFileTypes: true >) .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name); const reducer = (accumulator, currentValue) => < const key = `$$`; const pathDirectory = path.join(PATH_TO_PROJECT, currentValue); accumulator[key] = pathDirectory; return accumulator; >; const ALIASES_OBJECT = Object.assign(DEFAULT_ALIASES, getDirectories().reduce(reducer, <>)); module.exports = < ALIASES_OBJECT >;
Вся суть конфига выше в том, что его можно поместить куда угодно, и он будет динамически подхватывать любую вновь созданную директорию. Например, подключаем в webpack:
resolve: < alias: ALIASES_OBJECT, extensions: [".js", ".jsx", ".ts", ".tsx", ".json", ".mjs"], modules: [PATH_TO_PROJECT, "node_modules"], plugins: [PnpWebpackPlugin], >,
Или в eslint конфиг с расширением .js:
settings: < 'import/extensions': ['.js', '.jsx', '.ts', '.tsx', '.json'], 'import/resolver': < alias: < map: Object.entries(ALIASES_OBJECT), extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], >, >, react: < version: 'detect', >, >,
Далее стараемся привести наш проект внутри src к следующему виду:
// Redux
actions — каталог с redux-экшенами для импорта в react-компоненты и epics.
constants — каталог с redux-константами для импорта в actions, epics и reducers.
modeles — модели redux-store, это начальные состояния reducers, для импорта в reducers.
epics — эпики redux для обработки запросов и сохранения данных в store.
reducers — все reducers проекта, разбитые на каталоги в зависимости, например, от роутинга или раздела приложения.
selectors — каталоги selectors и structured-selectors для импорта в качестве state в react-компоненты.
api — rxjs.ajax объекты для импорта в epics с целью инициализации запросов.
redux — каталог для создания redux store, полного initial-store, root-reducer, и других middleware, например, root-epic.
// React
app — каталог инициализации корня приложения, сюда прописываем все react providers, роутинг и т.д.
components — каталог с react-компонентами, которые часто переиспользуются в других проектах.
enhancers — сюда пишем все декораторы, которые мы можем комбинировать, например, с помощью compose из redux. Декоратор локали, прав доступа к разделам сайта и т.д.
hooks — для кастомных хуков react.
i18n — здесь храним json локалей.
layouts — декораторы-react-компоненты для других react-компонентов. Например, мы хотим, чтобы определенные разделы сайта имели меню. Описываем эти компоненты там и оборачиваем в них разделы.
lib (иногда helpers или utils) — методы, которые часто переиспользуются внутри react-компонентов. Например, генерация градиентов, обрезка текста и т.д.
modules — это каталог react-компонентов, которые переиспользуются только в layouts. Например, сам компонент menu.
routes — здесь храним все разделы, которые прописываем в роутинге приложения. Чуть позже познакомимся с тем, как создавать для них конфиги с динамическим импортом.
// Other
theme — каталог тем для ui-kits или правил для styled-components (палитра, отступы, шрифты и т.д). Опишем его чуть позже.
utils — различные фичи, которые не нашли себе место в одном из каталогов.
Имея данную конфигурацию, можем обратиться, например, к каталогу redux:
При добавлении нового каталога в корень src просто перезапускаем webpack.
Получение данных из конфигов переменных окружения на этапе компиляции webpack
Выше мы уже создавали конфиги на примере .env.development. Проблема в том, что на этапе компиляции объект process.env из среды node о них ничего не знает. Он знает только те переменные, которые были переданы в качестве env в скрипты package.json. Например, здесь мы передаем NODE_ENV:
«start»: «cross-env NODE_ENV=development webpack serve —config ./webpack.config.js»,
Чтобы записать их в process.env, сначала считаем их из нужного нам конфига:
"use-strict"; // Utils const < VALID_NODE_ENV, IS_DEVELOPMENT, IS_PRODUCTION, >= require("./constants"); const < getConfig >= require("./get-config-file"); const DEFAULT_ENV = < NODE_ENV: VALID_NODE_ENV, IS_DEVELOPMENT: IS_DEVELOPMENT, IS_PRODUCTION: IS_PRODUCTION, >; const getConfigEnv = (objectEnv = <>) => < const conf = getConfig(); if (conf) < const resultConf = Object.keys(conf).reduce( (acc, key) =>< const value = JSON.stringify(conf[key]); acc[key] = value; return Object.assign(<>, acc); >, Object.assign(<>, objectEnv, DEFAULT_ENV), ); return resultConf; > return <>; >; module.exports = < getConfigEnv >;
Теперь метод getConfigEnv возвращает все переменные окружения development конфига.
NODE_ENV = development HOST = localhost PORT = 3000 VERSION = 1.0.0 CLIENT_ID = xxxx-xxxx-xxxx-xxxx
Теперь их нужно записать в process.env. Создадим в разделе plugins такой метод:
// Modules const webpack = require("webpack"); // Utils const < getConfigEnv >= require("../utils/get-config-env"); const getDefinePlugin = () => < const plugin = new webpack.DefinePlugin(< "process.env": getConfigEnv(), >); return plugin; >; module.exports = < getDefinePlugin >;
Теперь при сборке проекта будем автоматически получать все переменные из нужного конфига.
Дублирование пакетов:
При их установке наш пакетный менеджер добавит в проект не только сами пакеты, но и их зависимости. Часто бывает, что разные пакеты используют одни и те же зависимости различных версий. Чтобы знать о таких дублированиях, установим webpack-plugin:
// Modules const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin'); const getDuplicatePackageCheckerPlugin = () => < const plugin = new DuplicatePackageCheckerPlugin(< verbose: true, emitError: true, >); return plugin; >; module.exports = < getDuplicatePackageCheckerPlugin >;
Чтобы исправить конфликты, добавим нужный пакет и его версию в package.json в раздел resolutions, чтобы везде применялась одна и та же версия пакета.
"resolutions":
Для того чтобы узнать, сколько версий пакета используется в приложении вручную, есть команда в терминале (на примере react):
Она выдаст дерево зависимостей, если версий больше одной.
Если проект — это пакет, который будет задействован в других проектах, и в его зависимостях есть react, то его необходимо указать в peerDependencies. Это означает, что версия react будет подтягиваться из внешнего приложения.
"peerDependencies": < "react": ">=16.9.0", "react-dom": ">=16.9.0" >,
Это крайне важно для react, так как все пакеты проекта и сам проект должны использовать не только одну версию react, но и одну копию пакета. В противном случае будет ошибка.
В качестве сборщика вместо webpack можно использовать rollup. Например, на нем написано множество популярных пакетов, например, redux.
Конфиг babel.rc
< "presets": [ ["@babel/preset-env", < "modules": false >], "@babel/preset-react" ], "plugins": [ [ "babel-plugin-styled-components", < "ssr": false, "pure": true >], "@babel/plugin-syntax-dynamic-import", ["@babel/plugin-proposal-class-properties", < "loose": true >], "@babel/plugin-proposal-export-default-from", "@babel/plugin-proposal-optional-chaining", "@babel/plugin-proposal-unicode-property-regex", "@babel/plugin-transform-runtime" ], "env": < "development": < "plugins": [ "react-refresh/babel" ] >> >
Здесь перечислены все необходимые плагины для удобной работы с JavaScript.
Для обновления страницы при разработке мы применяем react-refresh.
Eslint конфиг
const path = require('path'); // Utils const CONSTANTS = require('./webpack/utils/constants'); const < ALIASES_OBJECT >= require('./webpack/utils/aliases'); const < APP_DIR, OS >= CONSTANTS; const < IS_WINDOWS >= OS; module.exports = < parser: '@typescript-eslint/parser', parserOptions: < tsconfigRootDir: path.resolve(APP_DIR, 'src'), project: path.resolve(APP_DIR, './tsconfig.json'), createDefaultProgram: true, ecmaVersion: 2018, sourceType: 'module', ecmaFeatures: < jsx: true, >, >, env: < browser: true, es2020: true, node: true, >, extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:react/recommended', 'plugin:react-hooks/recommended', 'airbnb-typescript', 'plugin:jsx-a11y/recommended', 'plugin:import/typescript', ], plugins: [ '@typescript-eslint', 'import', 'react', 'optimize-regex', 'prettier', 'promise', ], rules: < 'arrow-parens': 'off', 'no-alert': 'error', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/lines-between-class-members': 'off', 'linebreak-style': 0, 'eslint linebreak-style': [0, 'error', IS_WINDOWS ? 'windows' : 'unix'], 'import/prefer-default-export': 'off', 'import/no-extraneous-dependencies': 'off', 'no-console': 'off', 'react/prop-types': 'off', 'implicit-arrow-linebreak': ['error', 'below'], 'no-param-reassign': 'off', >, settings: < 'import/extensions': ['.ts', '.tsx', '.json'], 'import/resolver': < alias: < map: Object.entries(ALIASES_OBJECT), extensions: ['.ts', '.tsx', '.json'], >, >, >, globals: < document: true, window: true, parent: true, >, >;
Здесь мы подключили все необходимые плагины и расширения для нашей сборки, а также генерацию aliases, описанную ранее.
‘eslint linebreak-style’: [0, ‘error’, IS_WINDOWS ? ‘windows’ : ‘unix’],
отвечает за кроссплатформенные решения переноса строк.
HTTPS webpack-dev-server
Иногда для имитации рабочей среды нужно локально открывать https-соединение. Чтобы такое осуществить, создадим в корне проекта каталог cert. Внутрь него положим 2 файла:
Это самоподписанный сертификат и его публичный ключ.
Затем прописываем в webpack конфиге webpack-dev-server свойство https:
"use-strict"; // Modules const fs = require("fs"); const path = require("path"); const dotenv = require("dotenv"); // Utils const < APP_DIR, PATH_TO_ASSETS, >= require("./constants"); const devConstants = dotenv.config(< path: "./.env.development" >).parsed; const getDevServer = () => < const serverConf = < compress: true, static: [ PATH_TO_ASSETS, ], firewall: false, historyApiFallback: true, hot: true, https: < key: fs.readFileSync(path.join(APP_DIR, '/cert/localhost.key')), cert: fs.readFileSync(path.join(APP_DIR, '/cert/localhost.crt')), >, host: devConstants.HOST, open: true, port: devConstants.PORT, >; return serverConf; >; module.exports = < getDevServer >;
Коммиты, husky, конфиг
Наша задача автоматизировать коммиты. То есть привести их, например, к виду feature(my-project): [TASK-ID] my description, и чтобы это не занимало много времени у разработчиков.
Также все, что eslint и prettier могут автоматически исправить, мы перезапишем. Если исправить нельзя, выведем сообщение об ошибке и запретим делать коммит.
Для автоматизации процесса коммитов мы будем использовать:
husky: не ниже 6 версии
Создаем в корне .czrc и прописываем путь к конфигу:
Создаем каталог .commitizen в корне проекта и в нем наш конфиг cz-config.js:
'use-strict'; const < configLoader >= require('commitizen'); const longest = require('longest'); const map = require('lodash/map'); const config = configLoader.load() || <>; const regExpJiraTicket = /^(ux|devops)-[1-9][0-9]$/gi; const options = < scope: 'courier-admin', maxCommitWidth: 50, >; const choicesList = < feature: < title: 'feature', description: 'Новая задача', >, 'bug-fix': < title: 'bug-fix', description: 'Исправить баг', >, >; const length = longest(Object.keys(choicesList)).length + 1; const choices = map(choicesList, (type, key) => (< name: `$:`.padEnd(length)> $`, value: key, >)); module.exports = < prompter(cz, setCommit) < cz.prompt([ < type: 'list', name: 'type', message: 'Выберите тип коммита:', choices, default: config.defaultType, >, < type: 'input', name: 'jiraTicket', message: 'Введите тег задачи в JIRA (например UX-123):', validate: value => < const trimValue = value.trim(); if (!trimValue.length >0) < return 'Обязательное поле.'; >if (!regExpJiraTicket.test(trimValue)) < return 'Неверный формат.'; >return true; >, transformer: subject => subject.toUpperCase(), filter: subject => subject.trim().toUpperCase(), >, < type: 'input', name: 'commit', message: `Краткое наименование коммита (не более $):\n`, validate: value => < const trimValue = value.trim(); if (!trimValue.length >0) < return 'Обязательное поле.'; >if (trimValue.length > options.maxCommitWidth) < return 'Сократите коммит.'; >return true; >, filter: subject => subject.trim().toLowerCase(), >, ]) .then(answers => < const < type, jiraTicket, commit >= answers; const str = `$ ($): [$] $`; setCommit(str); >) .catch(error => < console.log(error); >); >, >;
Здесь все описываем согласно вашему gitflow. Пример выше демонстрирует основные возможности commitizen. Также мы можем брать уже готовые конфиги из npm.
Создаем каталог .husky в нем файл pre-commit
#!/bin/sh . "$(dirname "$0")/_/husky.sh" yarn lint-staged
В package.json в раздел scripts добавляем скрипт предустановки:
"prepare": "husky install", "commit": "cz"
После этого на unix системах возможна ошибка в работе husky. Для её исправления необходимо дать рекурсивно права каталогу .husky на перезапись.
chmod -R +w ./.husky
При вводе в терминал команды
нас ждет короткий опрос, после которого будет запущена проверка линтером, и в случае успеха — коммит.
Заключение
В этой статье мы разобрали пример разворачивания React-приложения. Таким способом мы помогли заказчику избежать переписывания проекта с нуля, улучшили архитектуру имеющегося решения и сделали приложение быстрее. Описанный технологический стек характерен для большинства проектов, поэтому с большей долей вероятности этот материал будет полезен в вашей работе.
Спасибо за внимание! Полезные материалы для разработчиков мы также публикуем в наших соцсетях – ВК и Telegram.
- Блог компании SimbirSoft
- Веб-разработка
- JavaScript
- Программирование
- ReactJS
Создаём новое React-приложение
These docs are old and won’t be updated. Go to react.dev for the new React docs.
See Start a New React Project for the recommended ways to create an app.
Используйте встроенный набор инструментов для лучшего взаимодействия пользователя и разработчика.
На этой странице описано несколько популярных наборов инструментов React, которые помогают в таких задачах как:
- Масштабирование до большого количества файлов и компонентов.
- Использование сторонних библиотек из npm.
- Раннее обнаружение распространённых ошибок.
- Отражение изменений CSS и JS на лету в процессе разработки.
- Оптимизация кода для продакшена.
Рекомендованные на этой странице инструменты не требуют дополнительной настройки для начала работы.
Возможно, вам не нужен дополнительный набор инструментов
Если у вас нет проблем, описанных выше, или пока не чувствуете себя уверенно, используя инструменты JavaScript, рассмотрите возможность добавления React в виде простого тега на HTML-странице, при необходимости с JSX.
Также это самый простой способ добавить React в существующий веб-сайт. Вы всегда можете расширить набор инструментов, если посчитаете это нужным.
Рекомендуемый набор инструментов
Команда React в первую очередь рекомендует следующие решения:
- Если вы изучаете React или создаёте новое одностраничное приложение, используйте Create React App.
- Если вы создаёте серверный сайт с Node.js, попробуйте Next.js.
- Если вы создаёте статический контент-ориентированный сайт, попробуйте Gatsby.
- Если вы создаёте библиотеку компонентов или интегрируетесь с существующей кодовой базой, попробуйте более гибкие наборы инструментов.
Create React App
Create React App — удобная среда для изучения React и лучший способ начать создание нового одностраничного приложения на React.
Инструмент настраивает среду для использования новейших возможностей JavaScript, оптимизирует приложение для продакшена и обеспечивает комфорт во время разработки. Вам понадобятся Node.js не ниже версии 14.0.0 и npm не ниже версии 5.6 на вашем компьютере. Для создания проекта выполните команды:
npx create-react-app my-app cd my-app npm start
Create React App не обрабатывает бэкенд логику или базы данных, он только предоставляет команды для сборки фронтенда, поэтому вы можете использовать его с любым бэкэндом. «Под капотом» используются Babel и webpack, но вам не нужно ничего знать о них.
Когда ваше приложение готово к развёртыванию в продакшене, запуск команды npm run build создаст оптимизированную сборку вашего приложения в папке build . Вы можете узнать больше о Create React App из его README и его пользовательского руководства.
Next.js — это популярный легковесный фреймворк для статических и серверных приложений, использующих React. Он включает в себя готовые решения для стилизации и маршрутизации и предполагает, что вы используете Node.js в качестве серверной среды.
Gatsby — лучший способ для создания статических сайтов с помощью React. Он позволяет использовать React-компоненты, но выводит предварительно отрендеренный HTML и CSS, чтобы гарантировать минимальное время загрузки.
Более гибкие наборы инструментов
Следующие наборы инструментов предлагают больше гибкости и выбора. Мы рекомендуем их более опытным разработчикам:
- Neutrino сочетает в себе возможности webpack и простоту пресетов. Инструмент включает в себя пресеты для React-приложений и React-компонентов.
- Nx — набор инструментов для ведения фулстэк разработки в монорепозиториях, который обладает встроенной поддержкой React, Next.js, Express и так далее.
- Parcel — быстрый упаковщик веб-приложений с нулевой конфигурацией, который работает с React.
- Razzle — это фреймворк для серверного рендеринга, более гибкий чем Next.js, но не требующий обязательной настройки.
Создание набора инструментов с нуля
В набор инструментов для сборки JavaScript обычно входят:
- Менеджер пакетов, такой как Yarn или npm. Он позволяет вам использовать обширную экосистему сторонних пакетов и легко устанавливать или обновлять их.
- Сборщик, такой как webpack или Parcel. Он позволяет писать модульный код и объединять его в небольшие пакеты, чтобы оптимизировать время загрузки.
- Компилятор, такой как Babel. Он позволяет писать современный код JavaScript, который будет работать даже в старых браузерах.
Если вы предпочтёте создать свой собственный набор JavaScript-инструментов с нуля, ознакомьтесь с этим руководством, в котором воссоздаются некоторые функции Create React App.
Не забудьте убедиться, что ваш набор инструментов правильно настроен для продакшена.