Содержание этой статьи началось с комментария к проблеме от awerlang, так что спасибо ему.

AngularInDepth уходит от Medium. Более свежие статьи размещаются на новой платформе inDepth.dev. Спасибо за то, что участвуете в глубоком движении!

Если вы хотите подготовить свою библиотеку angular 2 к компиляции AoT, ознакомьтесь с обзором этой статьи. Если вам не удается скомпилировать библиотеку с помощью ngc, но она хорошо компилируется с помощью tsc, существует несколько возможных причин.

Вот исходный список awerlang того, что вам нужно сделать, чтобы убедиться, что ваша библиотека NgModules статически анализируется.

  1. const lambda = ›функция экспорта
  2. экспорт по умолчанию = ›именованный экспорт
  3. частные, защищенные методы доступа должны быть изменены на общедоступные для всех членов, к которым осуществляется доступ из шаблона
  4. шаблон динамического компонента = ›статический шаблон
  5. moduleId должен быть установлен для компонентов с templateUrl

Я разделю с 1 по 3 примеры и сообщения об ошибках, которые вы получите, если не сделаете их. № 4 и № 5 я не встречал, поэтому просто передаю их как вещи, с которыми вы можете столкнуться.

1. const lambda = ›функция экспорта

Ошибка:

Ошибка. Произошла ошибка при статическом разрешении значений символов. Вызов функции «объявления», вызовы функций не поддерживаются. Рассмотрите возможность замены функции или лямбды ссылкой на экспортированную функцию.

До:

const declarations = () => [
  SomeComponent
];
@NgModule({
  declarations: declarations(),
})
export class SomeModule {}

После:

export function declarations() {
  return [
    SomeComponent
  ];
}
@NgModule({
  declarations: declarations(),
})
export class SomeModule {}

2. экспорт по умолчанию = ›именованный экспорт

Ошибка:

can't resolve module ./some.component from /path/to/some.module.ts
Error: can't find symbol undefined exported from module /path/to/some.component.ts

До:

// some.component.ts
@Component({...})
class SomeComponent{}
export default SomeComponent;
// some.module.ts
import SomeComponent from './some.component.ts';
@NgModule({
  declarations: [ SomeComponent]
})
export class SomeModule {};

После:

// some.component.ts
@Component({...})
export class SomeComponent{}
// some.module.ts
import { SomeComponent } from './some.component.ts';
@NgModule({
  declarations: [ SomeComponent]
})
export class SomeModule {};

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

Ошибка:

Error: Error at /path/to/some.component.ngfactory.ts:134:40: Property 'context' is private and only accessible within class 'SomeComponent'.

До:

@Component({
  template: `<div> {{ context }} </div>`
})
export class SomeComponent {
  private context: any;
}

После:

@Component({
  template: `<div> {{ context }} </div>`
})
export class SomeComponent {
  public context: any;
}

4. шаблон динамического компонента = ›статический шаблон

Спасибо @karlsson

Ошибка:

Error: Error encountered resolving symbol values statically. Expression form not supported

До:

const enum SomeType = {Green, Red}
@component({
 template: `
 <template [ngIf]=”color === ${SomeType.Green}”>Green</template>
`
export class MyClass {
color = SomeType.Green;
}

После:

@component({
 template: `
 <template [ngIf]=”color === someType.green}”>Green</template>
`
export class MyClass {
 someType = {green: 0, red: 1};
 color = this.someType.green;
}

5. Невоспроизведенные

6. Явный экспорт компонентов.

(Спасибо Жюльену Боуле)

Ошибка: (при компиляции AoT приложения, использующего библиотеку)

Uncaught Error: Unexpected value 'undefined' imported by the module 'AppModule'

До:

export * from 'some-component';

После:

export { SomeComponent } from 'some-component';

7. Используйте интерфейсы вместо value as type

(Спасибо Krille)

Ошибка:

Error encountered resolving symbol values statically. Expression form not supported, resolving symbol RoleNames.

До:

//person.routing.ts
const routes: Routes = [
{
  path: 'person',
  component: PersonComponent,
  canActivate: [ HasAllRolesGuard ],
  data: {
    roles: [ RoleNames.PERSON_READ ]
  }
}];
export const SearchRouting: ModuleWithProviders = RouterModule.forChild(routes);
//person.module.ts
@NgModule({
  imports: [ PersonRouting ],
})
export class SearchModule {}
//global.ts
export type RoleName = "person_read" | "person_write";
export const RoleNames = {
  PERSON_READ: "person_read" as RoleName,
  PERSON_WRITE: "person_write" as RoleName
};

После:

// other files unchanged...
//global.ts
export type RoleName = "person_read" | "person_write";
export interface IRoleNames {
  PERSON_READ: RoleName;
  PERSON_WRITE: RoleName;
};
export const RoleNames: IRoleNames = {
  PERSON_READ: "person_read",
  PERSON_WRITE: "person_write"
};

8. Angular как равноправная зависимость

Ошибка:

ERROR in Error encountered resolving symbol values statically. Calling function ‘makeDecorator’, function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol NgModule

Примечание. Эта ошибка появляется только при использовании библиотеки в приложении, скомпилированном с помощью angular cli. (Не при использовании ngc напрямую.) Кроме того, ошибка появляется только при первой сборке приложения (или при использовании --aot) - сохранение файла для принудительной перекомпиляции обойдёт ошибку.

До:

// package.json
...
dependencies: {
  "@angular/common": "^2.4.10",
  ...
}

После:

// package.json
...
peerDependencies: {
  "@angular/common": "^2.4.10",
  ...
}

9. Статические селекторы.

(Спасибо Mateusz (mat3e))

Ошибка:

Произошла ошибка при статическом разрешении значений символов. Можно ссылаться только на инициализированные переменные и константы, потому что значение этой переменной необходимо компилятору шаблона.

До:

// definition
const SELECTOR_1 = 'lib-component-a';
const SELECTOR_2 = 'lib-component-b';
export class LibSelectors {
  static get SELECTOR_1() { return SELECTOR_1; }
  static get SELECTOR_2() { return SELECTOR_2; }
  
  /* other things */
}
// usage
@Component({
  moduleId: `${module.id}`,
  selector: LibSelectors.SELECTOR_1,
  templateUrl: './component.html'
})
export class LibComponent1 {/* ... */}

После:

// definition
export const SELECTOR_1 = 'lib-component-a';
export const SELECTOR_2 = 'lib-component-b';
export class LibSelectors {
  /* other things */
}
// usage
@Component({
  moduleId: `${module.id}`,
  selector: SELECTOR_1,
  templateUrl: './component.html'
})
export class LibComponent1 {/* ... */}

Outro

Надеюсь, это поможет людям подготовить свои библиотеки. Если у вас есть примеры ошибки №5 или какой-либо другой ошибки, с которой вы столкнулись, дайте мне знать, и я включу решение здесь.