Comments 83
-ts компилятор быстрее babel и генерит чуть более оптимальный код (например нет лишних оберток для классов не имеющих родителя).
-ts отлично поддерживается в ide (vscode — из коробки, sublime — офф плагин от ms github.com/Microsoft/TypeScript-Sublime-Plugin, WebStorm — из коробки)
-npm @types
-c 3.0.0 расширены возможности типизации rest параметров
-keyof ( или в flow тоже есть аналог? )
-когда ставишь ts нет ощущения, что тебе в node_modules упало половина всего npm
-информацию о типах при желании можно вытянуть в runtime через декораторы (например на этой основе можно генерить валидаторы, gui, мета информацию для orm github.com/typeorm/typeorm)
В flow тоже так можно, но это несет доп издержки в рантайме codemix.github.io/flow-runtime/#
-У ts целостная экосистема, в отличии от babel где все перемотано изолентой.
Я так и не понял зачем нужны все эти пресеты в виде отдельных пакетов. Если уже используется транспилятор смысл использовать не все потенциальные фичи новых стандартов? В крайнем случае можно было бы сделать с конфиги одну настройку experimental включающую поддержку фич, попадание которых в стандарт находится под вопросом. Но в babel наворотили непонятно что. В итоге мануалы старше полугода уже становятся неактуальны и непонятно какой пресет нужно ставить для той или иной фичи.
-tsconfig поддерживает множественные псевдонимы путей ( пример
"@middlewares/*": [
"./src/middlewares/*",
"./src/core/middlewares/*"
],
), которые не ломают автокомплит в ide.
Никогда не сравнивал звезды, но не стал бы пытаться сравнивать язык и фреймворк.
Пока я готовил эту статью, я узнал кучу новых вещей о современном Javascript: flow, babel, async/await, шаблоны jsx. Интересно, насколько быстро эти знания устареют? И всё это не нужно, если использовать Kotlin. При этом знать о React нужно совсем немного, потому что большая часть проблем легко решается при помощи языка.
Заголовок намекает, а заключение утверждает, что Javasript + React забудется и устареет, а Kotlin + React это прогрессивно. Однако сравнение востребованности говорит об обратном. Те кто пишут на Яве не спешат переходить на Котлин, а Реакт довольно популярен.
Но опять же, каждому свои фломастеры.
Ну и надо подчеркнуть, что редакс он прежде всего для разделяемых между компонентами данных, а не просто «все данные в одном месте». Никто не запрещает вам в, например, реакт компонентах иметь локальные стейты и даже пробрасывать их детям через свойства.
Но когда возникает задача разделить какие-то данные между двумя компонентами в совсем разных ветвях дерева, то или поднимаем их к глобальному уровню, пробрасывая через компоненты, которым они не нужны, или используем механизмы синхронизации двух локальных стейтов, или используем механизмы управления глобальным состоянием. Часто третий способ самый простой.
И что такого плохого в лишнем слое абстракции?
То, что это новая библиотека, новые термины, новые ограничения, которые надо увязать со всем остальным. Чем меньше движущихся частей, тем легче поддерживать и писать новый код.
Redux вносит глобальное состояние, что просто зло ИМХО.
Мне прямо интересно какую альтернативу вы предлагаете. А то Ваш пример из статьи с хранением состояния в ближайшем State компонента получит проблемы при необходимости разделения состояния между двумя компонентами. Особенно когда у вас иерархия компонентов перестанет совпадать с иерархией данных. Например показывать текущую страницу из основного списка на странице в заголовке, определяемым в Layout'e.
Сразу отвечу на некоторые Ваши вопросы.
А почему глобальная точка входа должна быть одна? Зачем всю систему завязывать на один элемент?
Да можете хоть десять сделать, просто вы при этом никакой проблемы не решите, зато добавите проблему с синхронизацией точек входа в ваши данные. Собственно из-за наличия возможного разделяемого состояния, это никак не поможет с «Как потом разбираться какой код можно выбросить? Как оценить степень последствий при изменениях?»
Как потом разбираться какой код можно выбросить? Как оценить степень последствий при изменениях?
В случае Redux+JS, проверить селекторы и использующие их компоненты. Удалить и проверить тесты.
В случае Redux+(TS/Flow/Kotlin) — просто удаляйте пока компилируется.
Например показывать текущую страницу из основного списка на странице в заголовке, определяемым в Layout'e.
В своем проекте я это решил через наследование, что больше соответствовало моему случаю (header отличается для разных страниц). Вот пример
Про разделенные состояния я писал выше, что можно использовать синглетоны. Хотя, конечно, у меня были простые случаи. Если дадите реалистичный пример, когда это нужно, я подумаю более конкретно.
Удалить и проверить тесты… просто удаляйте пока компилируется
Я часто на работе сталкиваюсь с вопросом «а можем ли мы сделать то-то» и если я смогу получить ответ только изменяя код и тем более запуская тесты, то это будет слишком долго.
шаблонные строки в JS тоже есть, hello ${foo}
. И по-моему typescript лучше чем js+flow
{ «a»: «aaa» } — валидный? Или пустые поля всегда передаются?
{ «a»: 33 } — ?
{ «a»: «aaa», «d»: 33} — ?
Валидность второго — вопрос, конечно, спорный
{
"event": {
"id": 52413,
"name": "Событие",
"owner": "Мой любимый клуб",
"fromKu": "KU6",
"toKu": null
},
"timetables": [
{
"id": 52414,
"begin": 1524768960000,
"end": 1524765600000
},
{
"id": 52415,
"begin": 1524168840000,
"end": 1524169080000
}
],
"tariffs": [
{
"id": 52418,
"name": "один день",
"quantity": 1,
"timetablesIds": [
52414
],
"price": "1000.00"
},
{
"id": 52419,
"name": "два дня",
"quantity": 2,
"timetablesIds": [
52414,
52415
],
"price": "2000.00"
}
],
"demandsCount": 0,
"pretendersCount": 8,
"debit": {
"cashless": "0",
"cash": "5000.00",
"full": "5000.00"
},
"id": 52413
}
Внутренние объекты как есть передаются на отрисовку и где-то очень далеко после уже используются. И если проверки не было бы, то мне пришлось проверять весь код до того места, потому что я воплне мог накосячить в js части
Если бы была проверка на валидность json, то Вы бы не потратили несколько часов в такой ситуации.
Это не отрицает необходимость обратной совместимости api
Как вам показался котлиновский сериализатор на вкус? Я пытался его использовать, но он плохо поддерживается IDEA'ей (говорится что нужно ставить отдельный плагин для идеи, но он не помог), кроме того почему-то для моих случаев получались какие-то костыли
А так, пишешь data class простенький, помечаешь аннотаций и всё работает на ура.
function Question() {
писать кучу скобочек и стрелочек:
const Question = () => {
Это типичная болезнь яваскриптщиков, когда появляется какая-то фича, они ищут, где бы ее использовать, даже если это не нужно, а некоторые всерьез верят, что «в 2018» слово function устарело.
Стрелочные функции придуманы для удобной записи маленьких анонимных функций в таких ситуациях:
var names = array.map(users, u => u.name);
Не надо их везде пытаться использовать.
Мне нравится больше const Question = () => {
Когда дольше используешь стрелки полностью привыкаешь к такому стилю.
Минусов такого подхода я не вижу.
Стрелочные функции придуманы ...
Это вообще не аргумент. Какая разница для чего оно изначально делалось? Пирамиды тоже не для туристов строили.
async loadCars() {
const uri = `/api/cars?brand=${this.state.brand || ''}&color=${this.state.color || ''}`;
this.setState({
cars: await (await fetch(uri)).json(),
loaded: true,
});
}
JS — 3.5mb
Kotlin — 5.4mb
JS — 375kb
Kotlin — 752kb
Если вынести за скобки сборку и подобное, то для непосредственного написания кода с одной стороны остается Kotlin+React, а с другой Javascript+React+babel+Flow+ES5|ES6|ES7
Какая странная формулировка. Babel — это инструмент сборки, а ES5|ES6|ES7 — это часть языка Javascript. Корректнее будет написать Javascript+Flow+React, а если взять Typescript, как советуют комментаторы выше, то будет просто Typescript+React, что никак не сложнее Kotlin+React
он отвечает за то, чтобы ( ) превратился в React компонент
У вас в скобочках контент потерялся. Подозреваю что там было что-то типа <ComponentName />
.
В моем понимании это часть формулы Javascript+React. Просто такой специальный синтаксис для React. Не обязательно использовать Babel, есть и другие инструменты, Typescript его понимает из коробки, или можно взять buble, например. Это нюансы сборки, на процесс кодинга они не влияют.
специальный синтаксис для React
Которого нет в Kotlin варианте. А вместе с ним нет никаких ограничений что код, а что не код.
Я уже упоминал, что сторогость компиляции TypeScript зависит от конфигов, что означает, что и сам код зависит от этих конфигов (наверно, очень весело поддерживать одновренно два проекта на TypeScript с разными конфигами, у меня один, слава богу). Код зависит от того, какой ES подключен (набор разрешенных конструкций, насколько я понял). Т.е. чтобы понять что и как ты можешь писать сейчас, надо знать настройки конкретного проекта. В случае Kotlin у тебя всегда полная реализация языка без каких-либо допущений и подкручиваний.
нет никаких ограничений что код, а что не код
А какие могут быть ограничения? В любом случае специальные конструкции придётся учить, даже если это сахар языка. Все-таки билдеры встречаются не в каждом Kotlin-проекте
сторогость компиляции TypeScript зависит от конфигов
Странно ставить гибкость конфигурации в недостаток. Наоборот, за счёт этого можно мигрировать существующие проекты постепенно. Переименовали файлы JS -> TS и постепенно наращиваем строгость типизации.
В случае Kotlin придётся переписывать проект целиком в один присест, а это может растянуться надолго.
И никто не заставляет переписывать весь проект целиком. Я не пробовал серьезных сочетаний, но, кажется, это ничем не отличается от TypeScript и JS в одном проекте.
С Babel всё-равно придется иметь дело в любом случае
Зачем? TypeScript умеет работать с JSX.
Я как-то решил попробовать пару примеров, которые есть на GitHub-е на тему Kotlin + React. Предлагаемые решения очень сильно интегрированы в инфраструктуру JS с использованием его жуткого билд-стека, поверх которого еще стоят gradle-плагины.
Из неприятных эффектов — полная рекомпиляция бандла при любом малейшем изменении, которое может длиться от 30 сек. и больше взависимости от кодовой базы. Разрабатывать с таким темпом практически невозможно, из-за чего до сих пор юзаю GWT, который умеет инкрементальную компиляцию.
Для меня критично в 2018 году ждать 30 секунд на любое изменение. С увеличением кодовой базы и используемых сторонних модулей это время будет только расти. Тогда как на сам перезапуск сервера тратится 1.5 секунды (Embedded Jetty).
Проблема там не столько в самом компиляторе Котлина, сколько в бандлере. Чем больше библиотек — тем дольше приходится ждать. Простой хелло ворлд компилируется 10 секунд. Подключите React и время сразу увеличивается до 30.
Плюс ко всему отсутствие документации, нормальных примеров, гайдов и шаблонов для проекта. Вобщем, пока еще более чем зелено.
"dependencies": {
"react": "15.6.1",
"react-dom": "15.6.1",
"react-router-dom": "4.2.2",
"react-sticky": "6.0.1",
"primereact": "1.4.0",
"chart.js": "2.7.2",
"react-transition-group": "^2.2.1",
"font-awesome": "^4.7.0",
"classnames": "^2.2.5",
"bigdecimal": "^0.6",
"moment": "^2.20",
"file-saver": "1.3.3"
}
При этом перезапуск java сервера у меня с минуту идет (база, liqubase, spring...).
У вас 1.5 секунды с учетем перекомпиляции (хоть и инкрементной) запуска jvm и подобного?
Ну вот я пробовал официальные туториалы в т.ч. create react kotlin app и котлиновский tictactoe. Они все используют gradle kotlin frontend plugin, который в свою очередь пускает npm, webpack и babel. Когда я меняю строчку и делаю рефреш, все-равно компилится около 30 секунд — не важно, новый бандл или рефрешнутый. Пробовал поковыряться с настройками, но по ходу нет способа ускорить.
Компиляцию не учитываю. Запуск JVM и бутстрап приложения. Я всегда пользую Embedded Jetty, который сам по себе стартует меньше секунды. Архитектура, где нужно запускать сторонний сервер и туда что-то деплоить — это из эры динозавнов. Приложение обычно использует легкий фреймворк типа Javalin, пускает Flyway для базы, зачастую также использую Eclipselink (JPA), который пускается в 3-5 раз быстрее Hibernate. Иногда прикручиваю Google Guice для DI, но это лишних 0.5 — 0.7 секунд стартапа. Spring (Boot) принципиально не использую.
Как по мне, так основная проблема, которую необходимо решить любому языку, транспилирующемуся в js, — это размер коммьюнити и возможность использовать существующие библиотеки. Тот же Typescript имеет огромное коммьюнити и кучу типов для уже известных js библиотек. Как у этого с котлин?
Самому нравится шарить DTO и валидацию между фронтом и беком. Для этого все пишу на
Kotlin + React vs Javasript + React