Содержание этой статьи началось с комментария к проблеме от awerlang, так что спасибо ему.
AngularInDepth уходит от Medium. Более свежие статьи размещаются на новой платформе inDepth.dev. Спасибо за то, что участвуете в глубоком движении!
Если вы хотите подготовить свою библиотеку angular 2 к компиляции AoT, ознакомьтесь с обзором этой статьи. Если вам не удается скомпилировать библиотеку с помощью ngc, но она хорошо компилируется с помощью tsc, существует несколько возможных причин.
Вот исходный список awerlang того, что вам нужно сделать, чтобы убедиться, что ваша библиотека NgModules статически анализируется.
- const lambda = ›функция экспорта
- экспорт по умолчанию = ›именованный экспорт
- частные, защищенные методы доступа должны быть изменены на общедоступные для всех членов, к которым осуществляется доступ из шаблона
- шаблон динамического компонента = ›статический шаблон
- 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 или какой-либо другой ошибки, с которой вы столкнулись, дайте мне знать, и я включу решение здесь.