31
Июл
2019

Angular Ivy

Ivy представляет собой новую версию компилятора и визуализатора Angular, благодаря которому компиляция осуществляется быстрее, а конечные файлы имеют меньший размер.

Разработка Angular Ivy началась задолго до его официального релиза, и начиная с версии 8.x.x он стал доступен в тестовом режиме. Полная поддержка ожидается в Angular 9, а пока настоятельно не рекомендуется использовать его в режиме production.

Особенности Angular Ivy:

  • Меньший размер скомпилированного приложения и более быстрая компиляция;
  • Улучшенный отладчик (debugger);
  • Динамическая загрузка.

Установка

При создании нового проекта с использованием команды ng new, поддержка Angular Ivy задается с помощью параметра –enable-ivy.

ng new my-ivy-project --enable-ivy

Для активации Angular Ivy в уже имеющемся проекте задайте в файле tsconfig.app.json параметр enableIvy в блоке angularCompilerOptions.tsconfig.app.json


    {
     ...
     "angularCompilerOptions": {
       "enableIvy": true
     }
    }
    

Чтобы отключить использование Ivy просто установите параметр enableIvy в false.

Компиляция и размер файлов

Благодаря Angular Ivy процесс компиляции стал быстрее благодаря тому, что зависимые компоненты и директивы теперь не включаются в зависящий компонент. Вместо этого в зависящем компоненте указываются ссылки на зависимости. Таким образом, при изменении одной из зависимостей нужно перекомпилировать только ее, а не весь использующий ее код.

Что касается оптимизации конечных файлов, то одно и то же приложение, скомпилированное с поддержкой Ivy и без, будет иметь разный размер, причем первое значительно меньший. Такая оптимизация достигается за счет:

  • преобразования всех декораторов в статические методы класса, что избавляет от необходимости в “файлах-фабриках”;
  • большей подверженности файлов процессу под названием tree shaking из-за изменения.

Чтобы самостоятельно убедиться в вышесказанном, сравните транспилированный код двух компиляторов.

Команда для View-Engine.

node_modules/.bin/ngc

Команда для Ivy.

node_modules/.bin/ngc -p tsconfig.app.json

Debugger

Также изменения коснулись формата вывода ошибок. Теперь в консоли можно увидеть более информативное сообщение.

Рассмотрим пример.app.component.ts


    import {Component} from '@angular/core';

    @Component({
     selector: 'app-root',
     templateUrl: './app.component.html'
    })
    export class AppComponent{
     title = 'Angular ivy';
    }
    

app.component.html


    <h1>{{title}}</h1>

    <select (change)="selectValueChanged($event)">
     <option value="1">Faster compilation</option>
     <option value="2">Small bundle size</option>
     <option value="3">Informative debugging</option>
    </select>
    

Здесь на событие изменения значения поля вызывается несуществующий метод selectValueChanged(), что инициирует возникновение ошибки.

Вывод ошибки без использования Ivy.

Вывод ошибки c использованием Ivy.

Динамическая загрузка

Вместе с Ivy в Angular появилась поддержка динамического импорта ES6. Раньше все асинхронно подгружаемые модули загружались следующим образом.untitled.ts


    const routes: Routes = [
     {
       path: ':lang',
       children: [
         {path: 'auth', loadChildren: './auth/auth.module#AuthModule'}
       ]
     }
    ];
    

Теперь с Ivy это можно сделать так.untitled.ts


    const routes: Routes = [
     {
       path: ':lang',
       children: [
         {
           path: 'auth',
           loadChildren: () => import('./auth/auth.module').then(({AuthModule}) => AuthModule)
         }
       ]
     }
    ];
    

Динамический импорт ES6 также дает возможность подгружать отдельные компоненты без его объявления в модуле.app.module.ts


    @NgModule({
     declarations: [AppComponent],
     imports: [BrowserModule],
     providers: [],
     bootstrap: [AppComponent]
    })
    export class AppModule{}
    

app.component.ts


    import {Component, ɵrenderComponent, Injector} from '@angular/core';
    import {ChildComponent} from './child.component';
    
    @Component({
     selector: 'app-root',
     template: `
       <h1>Root component</h1>
      
       <button (click)="loadChild()">Load ChildComponent</button>
     `
    })
    export class AppComponent{
    
     constructor(private injector: Injector){}
    
     loadChild(){
       import ('./child.component').then(({ChildComponent}) => {
         ɵrenderComponent(ChildComponent, {
           host: 'app-root',
           injector: this.injector
         })
       });
     }
    }
    

child.component.ts


    @Component({
     selector: 'app-child',
     template: `
       <h1>Dynamically loaded "ChildComponent"</h1>
     `,
    })
    export class ChildComponent{}
    

Для отображения загружаемого компонента используется функция ɵrenderComponent, которая первым параметром принимает тип компонента, а вторым – объект конфигурации со следующими свойствами:

  • host – селектор компонента, в который будет загружен подгруженный компонент;
  • injector – экземпляр текущего injector-а, указывается только если подгружаемый компонент имеет зависимости.
Share

Тебе может это понравится...