- PVSM.RU - https://www.pvsm.ru -
В предыдущей серии (Как слямзить Хабр по-быстрому [1]) получил MVP [2] на базе Create React App [3] (CRA). Но это SPA [4], что не очень подходит, когда требуется индексация в поисковиках. Хорошо, нужен Server Side Rendering [5] (SSR). И желательно из коробки, а не на коленке. Крайне расточительно тратить ресурсы на самостоятельную разработку базовых технологий. Как выбирать платформу с поддержкой SSR? На практике, конечно, POC [6]. Попробую реализовать CRUD [7] с формой ввода на Material-UI [8], рассматривая кандидатов: React Starter Kit [9] (RSK), NEXT.js [10] и Electrode [11] (не путать с Electron [12]).
Исходники на GitHub [13].
RSK имеет собственный велосипед — universal-router
. Загружать внешние данные в Redux при серверном рендеринге предлагается через конфигурацию express [14] (или koa, или hapi).
NEXT.js подошёл к вопросу роутинга оригинальнее других, предложив использовать имена файлов в папке pages. Внутри обычные React-компоненты с новым статическим методом getInitialProps
, в котором можно выполнять загрузку внешних данных при серверном рендеринге. Если же нужно кастомизировать обработку запросов, то это делается самым естественным способом — через конфигурацию express [15] (или koa, или hapi).
Electrode, в отличии от других рассмотренных платформ, не заставляет отказываться от redux-router
. А это значит, что на время реализации фронтенда, можно вернуться к разработке на CRA. Вся магия серверного рендеринга внутри electrode-redux-router-engine
.
Очень интересно наблюдать, как загружается сайт zeit.co [16], который работает на NEXT.js. Когда открываешь страничку списка постов, приходит 15 MB траффика, но дальше переходы на страницы постов происходят мгновенно — всё кешируется в браузере. Однако это безобразие можно отключить через свойство prefetch
компонента Link
. Offline-first обещан в NEXT.js (с оговорками [17]), но в Electron уже реализован. Кеширование SSR: в NEXT.js есть пример [18], но в Electron решение в продакшене [19].
В RSK замечено не менее интересное поведение. Когда переключаю пункты списка истории строки ввода URL в Хроме, то наблюдаю выполнение роутов на сервере, хотя ещё не подтвердил свой выбор. А в результате готовая страница выдается с сервера быстрее.
NEXT.js и Electrode скрывают свою реализацию, но позволяют конфигурировать сборку. CRA запрещает конфигурировать сборку, только через eject (народ бился полгода за право прикручивать SCSS), но выход есть [20]. В RSK только форк, нужно следить за обновлениями проекта и мержить их руками — плата за полный доступ к исходному коду платформы.
RSK (как и CRA) убивает загрузкой новой страницы браузера при начальной сборке, NEXT.js и Electrode не имеют этого недостатка.
Electrode очень медленно выполняет начальную сборку.
NEXT.js имеет замечательный сервис для деплоя now [21], и он не привязан к конкретной платформе.
В RSK ужасный вывод ошибок, кроме того неправильно работает дебаг по Source Maps, курсор смещается на пару строк ниже. В Electrode просто невозможно понять, что пошло не так, если ошибка на стороне сервера. В NEXT.js ситуация значительно лучше, и обещают доработать ещё в ближайшем будущем. CRA тут эталон, и хочется сказать отдельное спасибо за вывод в консоль сообщений ESLint в процессе работы над проектом. Кстати, RSK превратил проверки ESLint в форменную пытку, я выпилил pre-commit.
NEXT.js подкупает разнообразием рецептов, хотя некоторые важные вопросы пока без ответа, но динамика развития проекта обнадёживает. RSK и Electrode хорошо дополняют общий набор. На примере CSRF [22]: вообще пока ничего в NEXT.js, в Electron праздник [23], в RSK нашёл отсылку на csurf [24].
Вчера вышел NEXT.js 2.0, спустя полгода после старта. Движуха вокруг NEXT.js намного больше, в сравнении с RSK и Electrode. Если судить по звездочкам на GitHub, то NEXT.js догоняет CRA, учитывая разницу в возрасте.
За технологиями стоят конкретные персоны. Это тоже важный момент выбора. NEXT.js развивает ZEIT — основатель Guillermo Rauch был техническим директором и соучредителем LearnBoost, помните TJ Holowaychuk?
По пути выяснил:
А хотелось просто валидацию полей формы. Но 462 открытых issues как бы намекают. Я не смог себя заставить. Кода для обслуживания получается больше, чем без redux-form. И нужно думать не только о поведении формы, но как ее заставить работать с помощью этой прекрасной обертки. В морг. Невозможно угодить всем и вся. Это нужно предложить решение на каждый случай применения. Был у меня подобный печальный опыт с Meteor-овскими велосипедом AutoForm. На первый взгляд — замечательно. Описываешь конфиг и оно само тебе формы выдает! Для двух полей это работает. Но когда формы большие, да со связанными полями. Божечки. Тормозит жутко. Глючит. И опять же вынуждает тебя лезть под капот с кувалдометром. Автор забил на пулл-реквесты. Остаётся форк — вешаешь на саппорт большую кучу "универсального" кода. Оно надо?
Многие проекты руководствуются рекомендациями Presentational and Container Components [25], но уважаемый автор признаётся в сносках, что концепция разделения спорная, и компоненты можно смешивать. А если это так, то зачем тащить чемодан без ручки? Все компоненты проекта удобнее хранить в одной общей папке. Какие плюсы:
Когда проект вырастит, следует дробить его на приватные npm-пакеты, инкапсулируя реализацию. Но не выращивать дерево подпапок внутри папки компонентов — развивать и поддерживать такое ощутимо сложнее. Проверено.
Дальше-больше. Попробовал CSS-Modules — отказался от BEM, но после styled-jsx [26] не могу больше смотреть на CSS-Modules. Зачем связывать каждый рутовый элемент компонента через className, ради чего переключать контекст внимания между файлами — непонятно.
Достигнув просветления с общей папкой компонентов, применил ducks-pattern [27]. "Но и это ещё не всё, позвонив прямо сейчас, вы получите второй комплект совершенно бесплатно". Можно отказаться от констант для связывания actions-reducers, используя пакет redux-actions [28]:
const increment = createAction('INCREMENT')
const reducer = handleActions({
[increment]: (state, action) => ({
counter: state.counter + action.payload
})
}, { counter: 0 })
Добавить плагин js-hyperclick [29].
Добавить пакет в проект:
$ yarn add babel-plugin-module-resolver -D
.babelrc
{
"presets": [
"next/babel"
],
"plugins": [
["module-resolver", {
"root": [""]
}]
]
}
package.json
{
"moduleRoots": [
""
}
пример:
import MyComponent from 'components/MyComponent'
import MyPage from 'pages/MyPage'
Кстати, NEXT.js избавляет от бессмысленной папки src в проекте. Просто не обращал внимания раньше, но как же без неё хорошо!
Это давний спор с техлидом маленькой но гордой веб-студии, что никакие UI-фреймворки нам не заменят ручной труд. Понятно, что разработка интерфейсов — это хлеб с маслом. Но я убеждённый сторонник применения готовых решений. Хорошо себе представляю, какая может быть проработка деталей, имея опыт реализации проекта с чистого листа по взрослому ТЗ от гуру UI/UX-дизайна. Гайдлайн Material Design — вторая космическая скорость. Но где же его реализация? Что видел — шлак. Кроме Material-UI [30]. Повертел-прикрутил, доработал напильником. Ну да, есть несколько недочётов. Точнее 647 открытых issues. Но пациент скорее жив чем мёртв. Демо [31] — форма добавления/редактирования поста блога.
Автор: comerc
Источник [32]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/251156
Ссылки в тексте:
[1] Как слямзить Хабр по-быстрому: https://habrahabr.ru/post/322084/
[2] MVP: https://en.wikipedia.org/wiki/Minimum_viable_product
[3] Create React App: https://facebook.github.io/react/blog/2016/07/22/create-apps-with-no-configuration.html
[4] SPA: https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5
[5] Server Side Rendering: https://rajdee.gitbooks.io/redux-in-russian/content/docs/recipes/ServerRendering.html
[6] POC: https://en.wikipedia.org/wiki/Proof_of_concept
[7] CRUD: https://ru.wikipedia.org/wiki/CRUD
[8] Material-UI: http://www.material-ui.com/#/
[9] React Starter Kit: https://reactstarter.com/
[10] NEXT.js: https://zeit.co/blog/next
[11] Electrode: https://habrahabr.ru/post/316818/
[12] Electron: https://electron.atom.io/
[13] Исходники на GitHub: https://github.com/comerc/yobrRSK
[14] через конфигурацию express: https://github.com/kriasoft/react-starter-kit/blob/feature/redux/src/server.js#L92-L94
[15] через конфигурацию express: https://github.com/zeit/next.js/blob/master/examples/parameterized-routing/server.js#L22
[16] zeit.co: https://zeit.co/
[17] с оговорками: https://github.com/zeit/next.js/issues/861
[18] есть пример: https://github.com/zeit/next.js/tree/master/examples/ssr-caching
[19] решение в продакшене: https://github.com/electrode-io/electrode-react-ssr-caching
[20] выход есть: https://www.npmjs.com/package/custom-react-scripts
[21] now: https://zeit.co/now
[22] CSRF: https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D0%B0%D1%8F_%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D0%BB%D0%BA%D0%B0_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0
[23] праздник: https://github.com/electrode-io/electrode/blob/master/samples/universal-react-node/src/server/plugins/csrf.js
[24] csurf: https://www.npmjs.com/package/csurf
[25] Presentational and Container Components: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.mq2t11t3r
[26] styled-jsx: https://github.com/zeit/styled-jsx
[27] ducks-pattern: https://github.com/erikras/ducks-modular-redux
[28] redux-actions: https://github.com/acdlite/redux-actions
[29] js-hyperclick: https://atom.io/packages/js-hyperclick
[30] Material-UI: http://www.material-ui.com/
[31] Демо: https://yobr-aimknojfwg.now.sh/post/add
[32] Источник: https://habrahabr.ru/post/325088/
Нажмите здесь для печати.