Angular / Typescript class.name 在生产构建中不起作用
Angular / Typescript class.name does not work in production build
使用 Angular 5. class.name 属性 遇到一个奇怪的问题。我们在打字稿中有以下功能:
export class ApiService
{
public list<T>(c: new(values: Object)=> T)
{
var cname = c.name;
....
}
}
现在,如果我在 Angular (ng-build) 的开发构建中使用此函数,如下所示:
export class Employee()
{
public id:string;
public name: string;
constructor(values: Object = {}) {
Object.assign(this, values);
}
}
在某处的代码中:
var list = api.list(Employee);
以上有效,在列表函数中我得到 cname = 'Employee'
但是,如果我们使用 ng build --env=prod 构建此解决方案,代码将失败并且我们得到 cname = undefined。
为什么会出现这种情况,如何解决?在开发构建中编译和工作的东西不应该在生产中工作吗?
您可能 运行 遇到缩小问题,该问题仅在 prod
构建期间发生。缩小将重命名您的 类 以获得最小的输出文件大小。
有关相关讨论,请参阅此问答:
如上面的答案所述,为了配置此选项,您需要 ng eject
您的应用程序,这将允许您自定义 UglifyJS 选项(负责缩小的库),但这也会阻止您使用 Angular CLI 的一些不错的功能(例如 ng build
和 ng serve
)。
请参阅此 GitHub 评论以了解 ng eject
的描述:https://github.com/angular/angular-cli/issues/6302#issuecomment-301220770
生产代码也有同样的问题,其中 'constructor.name' 返回空字符串。我的解决方案是装饰我需要的 classes,装饰器将在 运行 时间用任意 class-name 或作为参数传递的名称重新分配 'name':here是装饰者:
import "reflect-metadata";
var __global__ClassName__id__ = 0;
export function ClassName(useThisName: string = null) {
return function (target: any) {
if (target.name.length === 0 || useThisName !== null) {
Object.defineProperty(target, "name", {
value: useThisName !== null ? useThisName : `__ClassName__${++__global__ClassName__id__}`,
enumerable: false,
writable: false,
configurable: true
});
}
}
}
代码如下所示:
// generate a dynamic class name
@Decorator.ClassName()
export class PopupMessage{ }
// uses the argument as class name
@Decorator.ClassName("PopupMessage")
export class PopupMessage{ }
// and code will work as usual
var something = new Message.PopupMessage(1);
var samething = (<any>something).constructor.name == Message.PopupMessage.name;
使用 Angular 5. class.name 属性 遇到一个奇怪的问题。我们在打字稿中有以下功能:
export class ApiService
{
public list<T>(c: new(values: Object)=> T)
{
var cname = c.name;
....
}
}
现在,如果我在 Angular (ng-build) 的开发构建中使用此函数,如下所示:
export class Employee()
{
public id:string;
public name: string;
constructor(values: Object = {}) {
Object.assign(this, values);
}
}
在某处的代码中:
var list = api.list(Employee);
以上有效,在列表函数中我得到 cname = 'Employee'
但是,如果我们使用 ng build --env=prod 构建此解决方案,代码将失败并且我们得到 cname = undefined。
为什么会出现这种情况,如何解决?在开发构建中编译和工作的东西不应该在生产中工作吗?
您可能 运行 遇到缩小问题,该问题仅在 prod
构建期间发生。缩小将重命名您的 类 以获得最小的输出文件大小。
有关相关讨论,请参阅此问答:
如上面的答案所述,为了配置此选项,您需要 ng eject
您的应用程序,这将允许您自定义 UglifyJS 选项(负责缩小的库),但这也会阻止您使用 Angular CLI 的一些不错的功能(例如 ng build
和 ng serve
)。
请参阅此 GitHub 评论以了解 ng eject
的描述:https://github.com/angular/angular-cli/issues/6302#issuecomment-301220770
生产代码也有同样的问题,其中 'constructor.name' 返回空字符串。我的解决方案是装饰我需要的 classes,装饰器将在 运行 时间用任意 class-name 或作为参数传递的名称重新分配 'name':here是装饰者:
import "reflect-metadata";
var __global__ClassName__id__ = 0;
export function ClassName(useThisName: string = null) {
return function (target: any) {
if (target.name.length === 0 || useThisName !== null) {
Object.defineProperty(target, "name", {
value: useThisName !== null ? useThisName : `__ClassName__${++__global__ClassName__id__}`,
enumerable: false,
writable: false,
configurable: true
});
}
}
}
代码如下所示:
// generate a dynamic class name
@Decorator.ClassName()
export class PopupMessage{ }
// uses the argument as class name
@Decorator.ClassName("PopupMessage")
export class PopupMessage{ }
// and code will work as usual
var something = new Message.PopupMessage(1);
var samething = (<any>something).constructor.name == Message.PopupMessage.name;