typescript - کامپایل AOT هنگامی که تابع کارخانهای وارد شده از کتابخانه در DI در Angular استفاده میشود، شکست میخورد
من یک برنامه Angular 6.1 دارم که برخی ماژولهای خارجی را وارد میکند.
وقتی که برنامه را در حالت AOT کامپایل میکنم:
$ ng build --aotمن این خطا را دریافت میکنم:
ERROR in ./src/app.component.ngfactory.js
Module not found: Error: Can't resolve '/home/user/project/node_modules/@acme/library/src/library/library' in '/home/user/project/src/app'
resolve '/home/user/project/node_modules/@acme/library/src/library/library' in '/home/user/project/src/app'
using description file: /home/user/project/package.json (relative path: ./src/app)
Field 'browser' doesn't contain a valid alias configuration
using description file: /home/user/project/node_modules/@acme/library/package.json (relative path: ./src/library/library)
no extension
Field 'browser' doesn't contain a valid alias configuration
/home/user/project/node_modules/@acme/library/src/library/library doesn't exist
.ts
Field 'browser' doesn't contain a valid alias configuration
/home/user/project/node_modules/@acme/library/src/library/library.ts doesn't exist
.tsx
Field 'browser' doesn't contain a valid alias configuration
/home/user/project/node_modules/@acme/library/src/library/library.tsx doesn't exist
.mjs
Field 'browser' doesn't contain a valid alias configuration
/home/user/project/node_modules/@acme/library/src/library/library.mjs doesn't exist
.js
Field 'browser' doesn't contain a valid alias configuration
/home/user/project/node_modules/@acme/library/src/library/library.js doesn't exist
as directory
/home/user/project/node_modules/@acme/library/src/library/library doesn't exist
[/home/user/project/node_modules/@acme/library/src/library/library]
[/home/user/project/node_modules/@acme/library/src/library/library.ts]
[/home/user/project/node_modules/@acme/library/src/library/library.tsx]
[/home/user/project/node_modules/@acme/library/src/library/library.mjs]
[/home/user/project/node_modules/@acme/library/src/library/library.js]
@ ./src/app.component.ngfactory.js 12:0-92 30:102-122 30:186-206 33:204-224 33:289-309 36:204-224 36:289-309 45:102-122 45:187-207 51:102-122 51:187-207 120:102-122 120:187-207
@ ./src/app/app.module.ngfactory.js
@ ./src/main.ts
@ multi ./src/main.ts
مسیر node_modules/@acme/library/src/library/library به یک فایل library.d.ts منتهی میشود، که در دایرکتوری ماژول موجود است.
اگر اطلاعات تایپ را به طور کامل از بسته خارجی حذف کنم، برنامه کامپایل شده و درست کار میکند. همچنین، اگر همه تایپها را به صورت دستی در یک فایل index.d.ts ادغام کنم، کامپایل به خوبی انجام میشود.
فکر میکنم چیزی در نحوهای که کامپایلر فایلهای تعریف نوع را حل میکند اشتباه است، به نظر میرسد که به دلایلی به دنبال فایلهایی با پسوند .d.ts نمیگردد.
بهروزرسانی ۱
ماژول خارجی @acme/library نیز توسط من توسعه یافته و پیشکامپایل شده است. این یک کتابخانه ساده تایپاسکریپت با برخی کلاسها و توابع صادر شده است. این از هیچ چیز پیچیدهای از انگولار مثل دکوراتورها و این چیزها استفاده نمیکند.
فایل package.json آن دارای فیلدهای زیر است:
"es2015": "index.es2015.js",
"main": "index.min.js",
"module": "index.es5.js",
"typings": "index.d.ts",
تمام فایلهای ذکر شده در دایرکتوری ریشه بسته موجود هستند.
بهروزرسانی ۲
پس از بررسی بیشتر، به نظر میرسد که مشکل ناشی از تزریق وابستگی است. لطفاً مثال زیر را ببینید.
من از یک ارائهدهندهی کارخانهی سفارشی استفاده میکنم تا نمونهای از Library را به سازندهی کامپوننت تزریق کنم.
تابع libraryFactory از ماژول خارجی وارد شده و به این شکل است:
export function libraryFactory(): Library {
const dep1 = new Dep1();
const dep2 = new Dep2();
return new Library(dep1, dep2);
}
نمونه ناموفق
import {Component} from '@angular/core';
import {Library, libraryFactory} from '@acme/library';
@Component({
selector: 'app-foo',
templateUrl: './foo.component.html',
providers: [
{
provide: Library,
useFactory: libraryFactory
}
]
})
export class FooComponent {
constructor(public library: Library) {
}
}
نمونه عملی
با این حال، اگر DI را از بین ببرم، کامپایل میشود و به درستی کار میکند:
import {Component} from '@angular/core';
import {Library, libraryFactory} from '@acme/library';
@Component({
selector: 'app-foo',
templateUrl: './foo.component.html'
})
export class FooComponent {
public library: Library;
constructor() {
this.library = libraryFactory();
}
}
چه چیزی میتواند باعث این مشکل باشد؟
من خوشحال خواهم شد که در صورت نیاز، در اولین درخواست اطلاعات دقیقتری ارائه دهم.
پاسخ شماره ۱
انگولار نمیداند چه چیزی را به کلاس کتابخانه شما تزریق کند زیرا Dep1 و Dep2 قبلاً هنگام استفاده از useFactory تزریق نشدهاند. بنابراین شما میتوانید به سادگی useFactory را در مثال ناموفق خود به useValue تغییر دهید، سپس باید درست باشد.
یا
اگر میخواهید از کارخانه برای نمونهٔ Library استفاده کنید، باید Dep1 و Dep2 را قبل از Library به ارائهدهندهها تزریق کنید. اگر Dep1 و Dep2 خودشان وابستگی نداشته باشند، باید کار کند. اگر آنها هم وابستگی داشته باشند، باید آنها را نیز تزریق کنید.
import {Component} from '@angular/core';
import {Library, Dep1, Dep2} from '@acme/library';
const dep1instance = new Dep1();
const dep2instance = new Dep2();
@Component({
selector: 'app-foo',
templateUrl: './foo.component.html',
providers: [
{
provide: Dep1,
useValue: dep1instance
},
{
provide: Dep2,
useValue: dep2instance
},
{
provide: Library,
useFactory: (dep1: Dep1, dep2: Dep2) => new Library(dep1, dep2),
deps:[Dep1,Dep2]
}
]
})
export class FooComponent {
constructor(public library: Library) {
}
}
یا
شما میتوانید به سادگی کتابخانه خود را با دکوراتورهای Injectible برای سازگاری با DI انگولار شاخهبندی کنید. به نظر من، انتخابی آسان، قابل نگهداری و مفید است.
