Dart, как возможность перенести нативное приложение в web
KeepSolid
Тимофей Лавренюк
План доклада
- Попытки перенести нативные приложения в web
- Почему мы выбрали Dart
- Что такое Dart?
- Особенности Dart
- Экосистема Dart
- Сложности перехода с C++ на веб-разработку
- Выводы
Кто я
Из Одессы
Более 8 лет в веб-разработке
Работаю в KeepSolid
Попытки перенести нативное приложение в web
1
Ядро
RPC Server
- Монолитное C++ ядро
- Отсутствие помощи
- Некомпилируемые библиотеки
WEB-Версия
Криптография
Offline
Работа с PDF
Общение с RPC-сервером
- Говнокод + утечки памяти
- Сложный дебаг
- CMake
Команда
Нужно писать на TypeScript
?
Research: на чем можно писать Front-End, кроме TypeScript
- Язык от JetBrains
- Много информации
- Сыроват для Web
- Нет UI-фреймворка
- Нет пакетного менеджера
- Синтаксис OCaml от Facebook
- Мало информации
- Есть UI-framework
- Есть пакетный манеджер
- Много функциональщины
- Язык от Mozilla
- Компилируется в WebAssembly, может общаться с JS кодом
- Нет стабильного UI-фреймворка
- Есть пакетный менеджер
- Язык от Google
- Не много, но и не мало информации
- Есть UI-фреймворк
- Есть пакетный менеджер
Почему мы выбрали Dart?
2
class SomeClass {
sayHello(value) {
alert(value);
}
static #privateField = 2;
callPrivate(obj) {
alert(obj.value)
}
}
interface ISomeClassMain {
sayHello: (value: string) => void;
}
interface ISomeObject {
value: 'one' | 'two' | null | undefined;
zalepon: any;
}
class SomeClass implements ISomeClassMain {
sayHello(value: string) {
alert(value);
}
private static privateField = 2;
private callPrivate(obj: ISomeObject): void {
alert(obj.value);
}
}
Вывод ошибок
Что такое Dart?
3
A client-optimized language for fast apps on any platform
Кто использует
2011
Появился
2011
2018
Появился
медленно развивался
С чего мы начали?
SDK
IDE
Java
JS
Победил
void main() {
print('Hello, World!');
}
Как мы смогли выучить язык?
Как учат JS?
МНОГО
Что предлагает Dart?
Круто, что еще нужно?
Особенности Dart
4
Строгая типизация
Типизация в Javascript (ее нет)
The Dart language is type safe: it uses a combination of static type checking and runtime checks to ensure that a variable’s value always matches the variable’s static type. Although types are mandatory, type annotations are optional because of type inference.
List numbers = [1,2,3];
print(numbers.first); // 1
print(numbers.last); // 3
print(numbers.isEmpty); // false
print(numbers.isNotEmpty); // true
Map<String, String> users =
{"1": "Foo", "2": "Bar"};
List<String> usernames = users.values;
class SomeClass {
double number;
callFunction() {}
}
SomeClass nullClass;
final value = nullClass ?? SomeClass();
final number ??= SomeClass().number;
print(nullClass?.callFunction());
class Foo {
Foo({
this.paramOneName = '1',
this.paramTwoName = '2' });
String paramOneName;
String paramTwoName;
}
var foo = Foo(paramOneName: '3');
class Bar {
Bar();
Foo f1;
Foo f2;
}
Bar bar = Bar()
..f1 = Foo(paramTwoName: '2')
..f2 = Foo(paramOneName: '10');
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
Вспомогательные классы
- DateTime
- Duration
- Uri
Core libraries
- dart:core
- dart:async
- dart:collection
- dart:html
- dart:io
- ...
dart:async
Dart - однопоточный язык, как и JS
Future<int> future = Future(asyncFunction);
future.then((int value) {
print(value);
}).catchError((e) {
print('Error');
});
someFunc () async {
try {
int value = await future;
} catch(e) {
print('Error');
}
}
Streams
controller = StreamController<int>(
onListen: startTimer,
onPause: stopTimer,
onResume: startTimer,
onCancel: stopTimer);
controller.stream.listen((timer) {
print(timer);
});
someStream
.map(...)
.reduce(...)
.skip(...)
.take(...)
.timeout(...)
.transform(...)
.listen((result) {
print(result);
})
stream_transform
rx_dart
Event Loop
"многопоточности" быть
Web Workers
Isolates
dart:collection
dart:convert
- Base64Encoder
- Base64decoder
- JsonDecoder
- JsonEncoder
- HtmlEscape
- ...
dart:html
Stream
Все из коробки
Сторонние библиотеки
json_serializer
{
"name": "Foo",
"email": "somemail@example.com"
}
JSON response
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
User(this.name, this.email);
String name;
String email;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
built_value
built_collection
abstract class User implements Built<User, UserBuilder> {
factory User([updates(UserBuilder b)]) = _$User;
User._();
@nullable
String get firstName;
@nullable
String get lastName;
}
User user = User((builder) =>
builder..firstName = 'One'
..lastName = 'Two'
);
User secondUser = user.rebuild((builder) =>
builder..lastName = 'Three'
);
// user != secondUser
intl
http
...
Экосистема Dart
5
UI
Веб-разработка
import 'package:angular/angular.dart';
@Component(
selector: 'user-info',
templateUrl: 'user_info.html')
class UserInfo implements OnInit {
User(this.dataController)
DataController dataController;
Stream<String> userName;
void ngOnInit() {
userName = dataController.info.userName;
}
}
<div>{{userName | async}}</div>
А что если нужна библиотека, которой нет на Dart?
Подключаем JS библиотеку
@JS('draw2d')
library draw2d;
@JS('Canvas')
class Canvas {
external factory Canvas(String name, [num x, num y]);
external Canvas add(Figure figure, [num x, num y]);
external Canvas addSelection(ArrayList /*Figure|List<Figure>*/ object);
external Canvas clear();
external void destroy();
external void fireEvent(String name, [dynamic attr]); /*Object*/
external Point fromCanvasToDocumentCoordinate(num x, num y);
external Point fromDocumentToCanvasCoordinate(num x, num y);
external num getAbsoluteX();
external num getAbsoluteY();
}
Кроссплатформенная разработка
2011
2018
Появился
2019
медленно развивался
Dart 2.0
Flutter-Хайп
Хайп Flutter-а двигает разработку Dart вперед
Форматирование кода
class User
{
String paramNumberOne = 1;
String paramNumbeTwo = 2;
String paramNumbeThree = 3;
num _age;
num get age => _age;
set age (num age)
{
_age = age;
}
}
class User {
String paramNumberOne = 1;
String paramNumbeTwo = 2;
String paramNumbeThree = 3;
num age;
}
Dart Formatter
dartfmt -w --fix lib
Dart 👍
Linter
analysis_options.yaml
+ pre-commit hook
dartanalyzer --fatal-warnings lib
= 🔥
Dart 👍👍👍
Документация
Dart documentation guide
dartdoc
F1
Dart 👍👍👍
Пакетный менеджер
name: project name
version: 0.0.1
environment:
sdk: '>=2.4.0 <3.0.0'
dependencies:
intl: ^0.15.7
pubspec.yaml
pub get
Когда либа импортится за 10 секунд
Dart 👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍
Debug
console.log("Best debug ever (No)");
Chrome Dev Tools
Build system
Сложности перехода с C++ на веб-разработку
6
Забить на потребление памяти
JS Garbage Collector
Сложности web-разработки на Dart
Бывает недостаточно информации
Велосипедо-строение
Выводы
7
Batteries included
Веб разработка быстрее нативной
Реализованные проекты
Roadmap Planner Web Viewer
KeepSolid Goals
Dart хорош, но не везде
2011
2018
Появился
2019
медленно развивался
Dart 2.0
Flutter-Хайп
2011
2018
Появился
2019
Будущее
медленно развивался
Dart 2.0
Flutter-Хайп
Dart 2.5
ML Autocomplete
Dart 2.6
Extensions
К плюсам возвращаться не хочется
Итого:
С++ разработчики
Dart C++
By Timofey Lavrenyuk
Dart C++
- 413