История самурая

Путь, который проходит Dart-код от IDE до браузера

Дерево проекта

.
├── lib
│   ├── app_component.css
│   ├── app_component.dart
│   └── app_component.html
└── web
    ├── index.html
    └── main.dart
          

Каким образом?

Dartium

Браузер


Loading source assets...
Loading angular, sass_builder, dart_to_js_script_rewriter and test/pub_serve transformers...
Building demo3... (43.1s)
[Info from Dart2JS]:
Compiling demo3|web/main.dart...
[Info from Dart2JS]:
Took 0:00:09.032240 to compile demo3|web/main.dart.
Built 894 files to "build".
          

Loading source assets...
Loading angular, sass_builder, dart_to_js_script_rewriter and test/pub_serve transformers...
Building demo3... (43.1s)
[Info from Dart2JS]:
Compiling demo3|web/main.dart...
[Info from Dart2JS]:
Took 0:00:09.032240 to compile demo3|web/main.dart.
Built 894 files to "build".
          

Откуда столько файлов?

Из чего состоит Dart-код?

  • Код проекта
    5 + 2 или 5 - 2 + 4
  • Сторонние библиотеки
    267 - 7 = 260
  • Стандартная библиотека
    894 - 267 = 627

Из чего состоит Dart-код?

  • Код проекта
    5 + 2 или 5 - 2 + 4
  • Сторонние библиотеки
    267 - 7 = 260
  • Стандартная библиотека
    894 - 267 = 627

Стандартная библиотека

  • dart:core — числа, даты, коллекции, урлы — Lodash, Momentjs
  • dart:async — async/await, промисы, стримы — RxJS
  • dart:math — Математика
  • dart:html — Все что в браузере
  • другие

Код проекта


5 + 2 или 5 - 2 + 4

Dart → Dart2JS → JS

Разве этого не достаточно!?

Есть еще pub

Пакетный менеджер, иногда выполняет функцию сборщика

Dart → Pub transformers → Dart2JS → JS

Это как лоадеры в вебпаке

Было

  • app_component.css
  • app_component.dart
  • app_component.html
  • main.dart
  • index.html

Было

  • app_component.css
  • app_component.dart
  • app_component.html
  • main.dart

Стало

  • app_component.css → app_component.css.shim.dart
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

app_component.dart


@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html'
)
class AppComponent {
}
          

app_component.dart


@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html'
)
class AppComponent {
}
          

app_component.css


:host {
    color: red;
}
          

app_components.css.shim.dart


const styles = const ['._nghost-%COMP% { color:red; }'];
            

app_component.css


:host {
    color: red;
}
          

app_components.css.shim.dart


const styles = const ['._nghost-%COMP% { color:red; }'];
          

          Hello world
          

В браузере


<style>._nghost-kpm-1 { color:red; }</style>
<my-app class="_nghost-kpm-1" id="">
  Hello world
</my-app>
          

          Hello world
          

В браузере


<style>._nghost-kpm-1 { color:red; }</style>
<my-app class="_nghost-kpm-1" id="">
  Hello world
</my-app>
          

app_components.css.shim.dart


const styles = const ['._nghost-%COMP% { color:red; }'];
            

Стало

  • app_component.css → app_component.css.shim.dart
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

          Hello world
          

app_component.template.dart


...
ComponentRef build() {
    final HtmlElement parentRenderNode = initViewRoot(rootEl);
    Text text = new Text('Hello world');
    parentRenderNode.append(text);
  }
...
        

AOT-компиляция

JIT-компиляция

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html → app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html 👍→ app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html 👍→ app_component.template.dart
  • main.dart другой main.dart

app_component.dart


@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html'
)
class AppComponent {}
          

Кто делает new AppComponent()?

app_component.template.dart


import 'package:angular/angular.template.dart' as angular_template;
import 'package:angular/di.template.dart' as di;

void initReflector() {
  angular_template.initReflector();
  di.initReflector();

  _ngRef.registerFactory(AppComponent, () => new AppComponent());
}
          

app_component.template.dart


import 'package:angular/angular.template.dart' as angular_template;
import 'package:angular/di.template.dart' as di;

void initReflector() {
  angular_template.initReflector();
  di.initReflector();

  _ngRef.registerFactory(AppComponent, () => new AppComponent());
}
          

app_component.template.dart


import 'package:angular/angular.template.dart' as angular_template;
import 'package:angular/di.template.dart' as di;

void initReflector() {
  angular_template.initReflector();
  di.initReflector();

  _ngRef.registerFactory(AppComponent, () => new AppComponent());
}
          

app_component.template.dart


void initReflector() {
  _ngRef.registerFactory(AppComponent, () => new AppComponent());
}
          

Инверсия зависимостей



  
    
  

          



  
    
  

          

app_component.dart


@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html'
)
class AppComponent {
  AppComponent(){ // init }
}
          

app_component.dart


@Component(
  selector: 'my-app',
  styleUrls: const ['app_component.css'],
  templateUrl: 'app_component.html'
)
class AppComponent {
  AppComponent(MyService service){ // init }
}
          

...
registerFactory( AppComponent, (MyService p0) => new AppComponent(p0));

registerDependencies( AppComponent, const [MyService]);

registerFactory( MyService, () => new MyService());
...
          

...
registerFactory( AppComponent, (MyService p0) => new AppComponent(p0));

registerDependencies( AppComponent, const [MyService]);

registerFactory( MyService, () => new MyService());
...
          

...
registerFactory( AppComponent, (MyService p0) => new AppComponent(p0));

registerDependencies( AppComponent, const [MyService]);

registerFactory( MyService, () => new MyService());
...
          

...
registerFactory( AppComponent, (MyService p0) => new AppComponent(p0));

registerDependencies( AppComponent, const [MyService]);

registerFactory( MyService, () => new MyService());
...
          

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart
  • app_component.html 👍→ app_component.template.dart
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart👍→
  • app_component.html 👍→ app_component.template.dart 👍
  • main.dart другой main.dart

А где начало?

main.dart до


void main() {
  bootstrap(AppComponent);
}
          

main.dart после


import 'main.template.dart' as main_template;

void main() {
  main_template.initReflector();
  bootstrapStatic(AppComponent);
}
            

main.dart до


void main() {
  bootstrap(AppComponent);
}
          

main.dart после


import 'main.template.dart' as main_template;

void main() {
  main_template.initReflector();
  bootstrapStatic(AppComponent);
}
            

main.template.dart


import 'main.template.dart' as main;
import 'package:angular/angular.template.dart' as angular_template;
import 'package:demo/app_component.template.dart' as app_component;

void initReflector() {
  main.initReflector();
  angular_template.initReflector();
  app_component.initReflector();
}
          

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart 👍
  • app_component.html 👍→ app_component.template.dart 👍
  • main.dart другой main.dart

Стало

  • app_component.css → app_component.css.shim.dart 👍
  • app_component.dart👍→
  • app_component.html 👍→ app_component.template.dart 👍
  • main.dart другой main.dart 👍
  • main.template.dart 👍

— Почему Dart2JS крутой?

— Потому что он поддерживает оптимизации на SSA!
(Static single assignment form)

Свертка констант

constant folding

До


int x = 14;
int y = 7 - x / 2;
print (y * (28 / x + 2));
          

После


          print('0');
          

UglifyJS


var x=14,y=7-x/2;console.log(y*(28/x+2));
          

void main(){
  var car = new Car(new Wheel());
  car.wheel.pump();
}

class Car {
  Wheel wheel;
  Car(this.wheel);
}

class Wheel {
  pump(){ document.body.appendText('test'); }
}
          

Результат


      var t1, t2;
      t1 = document;
      t2 = t1.body;
      t2.toString;
      t2.appendChild(t1.createTextNode("test"));
          

Спасибо!

сайт: zolotyh.com

twitter: @zolotyh