相同的Angular代码在生产环境中停止工作

huangapple go评论61阅读模式
英文:

The same Angular code stops working in production

问题

我在Angular应用中有一个导航服务,在开发模式下工作得很好,但一旦生成生产版本,它就停止工作。

这个服务很简单;它返回当前活动的组件,但在生产环境中,它只返回'a'。

以下是服务代码:

@Injectable({
  providedIn: 'root'
})
export class NavigationService {
  private activeComponentSubject: BehaviorSubject<string> = new BehaviorSubject<string>('');

  constructor(private router: Router, private route: ActivatedRoute) {
    this.subscribeToNavigationEnd(this.route);
  }

  private subscribeToNavigationEnd(route: ActivatedRoute): void {
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) => {
      const activeComponent = this.getActiveComponent(route);
      this.activeComponentSubject.next(activeComponent);
    });
  }

  private getActiveComponent(route: ActivatedRoute): string {
    const childRoute = route.firstChild;

    if (childRoute) {
      return this.getActiveComponent(childRoute);
    } else {
      const componentName = route.outlet === PRIMARY_OUTLET ? route.component?.['name'] : '';
      return componentName || '';
    }
  }

  getComponent(): BehaviorSubject<string> {
    return this.activeComponentSubject;
  }
}

在组件中,它像这样调用:

ngOnInit(): void {
  this.navigationSubscription = this.navigation.getComponent().subscribe(component => {
    this.setPath(component);
    console.log(component);
  });
}

如果我在开发中打开组件,我会得到像ShopComponent、CheckoutComponent等值。

而在生产中,我只得到'a'。

以下是angular.json的配置:

"configurations": {
  "production": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ],
    "optimization": true,
    "outputHashing": "all",
    "sourceMap": false,
    "namedChunks": false,
    "extractLicenses": true,
    "vendorChunk": false,
    "buildOptimizer": true,
    "budgets": [
      {
        "type": "initial",
        "maximumWarning": "2mb",
        "maximumError": "5mb"
      },
      {
        "type": "anyComponentStyle",
        "maximumWarning": "6kb",
        "maximumError": "10kb"
      }
    ],
    "serviceWorker": true,
    "ngswConfigPath": "ngsw-config.json"
  },
  "development": {
    "buildOptimizer": false,
    "optimization": false,
    "vendorChunk": true,
    "extractLicenses": false,
    "sourceMap": true,
    "namedChunks": true
  }
}

希望这对你有所帮助。如果有其他问题,请告诉我。

英文:

I have a navigation service in my Angular application that works perfectly in development mode, but once the production build is made, it stops working.

The service is straightforward; it returns the currently active component, but in production, it returns just 'a'.

Here is the service code:

@Injectable({
  providedIn: &#39;root&#39;
})
export class NavigationService {
  private activeComponentSubject: BehaviorSubject&lt;string&gt; = new BehaviorSubject&lt;string&gt;(&#39;&#39;);

  constructor(private router: Router, private route: ActivatedRoute) {
    this.subscribeToNavigationEnd(this.route);
  }

  private subscribeToNavigationEnd(route: ActivatedRoute): void {
    this.router.events.pipe(
      filter(event =&gt; event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) =&gt; {
      const activeComponent = this.getActiveComponent(route);
      this.activeComponentSubject.next(activeComponent);
    });
  }

  private getActiveComponent(route: ActivatedRoute): string {
    const childRoute = route.firstChild;

    if (childRoute) {
      return this.getActiveComponent(childRoute);
    } else {
      const componentName = route.outlet === PRIMARY_OUTLET ? route.component?.[&#39;name&#39;] : &#39;&#39;;
      return componentName || &#39;&#39;;
    }
  }

  getComponent(): BehaviorSubject&lt;string&gt; {
    return this.activeComponentSubject;
  }
}

And in the component, it's called like this:

ngOnInit(): void {
  this.navigationSubscription = this.navigation.getComponent().subscribe(component =&gt; {
    this.setPath(component);
    console.log(component);
  });
}

If I open the component in the development I get values like ShopComponent, CheckoutComponent, etc.

While in the production I just get 'a'.

Here is angular.json configuration:

  &quot;configurations&quot;: {
    &quot;production&quot;: {
      &quot;fileReplacements&quot;: [
        {
          &quot;replace&quot;: &quot;src/environments/environment.ts&quot;,
          &quot;with&quot;: &quot;src/environments/environment.prod.ts&quot;
        }
      ],
      &quot;optimization&quot;: true,
      &quot;outputHashing&quot;: &quot;all&quot;,
      &quot;sourceMap&quot;: false,
      &quot;namedChunks&quot;: false,
      &quot;extractLicenses&quot;: true,
      &quot;vendorChunk&quot;: false,
      &quot;buildOptimizer&quot;: true,
      &quot;budgets&quot;: [
        {
          &quot;type&quot;: &quot;initial&quot;,
          &quot;maximumWarning&quot;: &quot;2mb&quot;,
          &quot;maximumError&quot;: &quot;5mb&quot;
        },
        {
          &quot;type&quot;: &quot;anyComponentStyle&quot;,
          &quot;maximumWarning&quot;: &quot;6kb&quot;,
          &quot;maximumError&quot;: &quot;10kb&quot;
        }
      ],
      &quot;serviceWorker&quot;: true,
      &quot;ngswConfigPath&quot;: &quot;ngsw-config.json&quot;
    },
    &quot;development&quot;: {
      &quot;buildOptimizer&quot;: false,
      &quot;optimization&quot;: false,
      &quot;vendorChunk&quot;: true,
      &quot;extractLicenses&quot;: false,
      &quot;sourceMap&quot;: true,
      &quot;namedChunks&quot;: true
    }
  }

答案1

得分: 2

这是预期的。所有的类都被重命名为简短的文本片段。这个过程被称为缩小,是为了使捆绑包(JavaScript文件大小)更小。您可以正确获取您的组件;只是它们的类名不再是长而可读的,而是简短的。

英文:

It is expected. All of the classes are renamed to short pieces of text. This process is named minification and is done to make the bundle (JavaScript file size) smaller. You are getting your components correctly; just their class names are no longer the long readable ones, but short ones.

答案2

得分: 1

感谢@Andrei的解释。

简单解决方案:

使用组件选择器作为唯一标识符。为此,您可以使用函数reflectComponentType的帮助来检索组件元数据作为对象,并读取组件选择器。

const mirror = reflectComponentType(route.component);
return mirror?.selector;

解决方案2

在您的组件上定义一个公共属性来保存组件名称。

export class MyComponent {

    public componentName = 'MyComponent';
}

return route?.component.componentName;

这仅适用于少量路由组件。

英文:

Thanks to @Andrei's explanation.

Simple solution:

Use component selector as a unique identifier instead. To do so, you could use the help of the function reflectComponentType to retrieve the component metadata as an object and read the component selector.

const mirror = reflectComponentType(route.component);
return mirror?.selector;

Solution 2

Define a public property on your component to hold the component name.

export class MyComponent {

    public componentName = &#39;MyComponent&#39;;
}

return route?.component.componentName;

It works only for small amount of route components.

huangapple
  • 本文由 发表于 2023年6月5日 16:44:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76404770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定