{"id":2370,"date":"2019-04-03T14:57:27","date_gmt":"2019-04-03T12:57:27","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=2370"},"modified":"2019-04-03T14:57:27","modified_gmt":"2019-04-03T12:57:27","slug":"the-new-treeshakable-providers-api-in-angular","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/","title":{"rendered":"The new Treeshakable Providers API in Angular"},"content":{"rendered":"<div class=\"article\">\n<p><strong>Source code:<\/strong> <a href=\"https:\/\/github.com\/manfredsteyer\/treeshakable-providers-demo\">https:\/\/github.com\/manfredsteyer\/treeshakable-providers-demo<\/a><\/p>\n<blockquote><p>\nBig thanks to <a href=\"https:\/\/github.com\/alxhub\">Alex Rickabaugh<\/a> from the Angular team for discussing this topic with me and for giving me some valueable hints.\n<\/p><\/blockquote>\n<p><\/p>\n<p>Treeshakable providers come with a new <strong>optional<\/strong> API that helps tools like webpack or rollup to get rid of unused services during the build process. \"Optional\" means that you can still go with the existing API you are used to. Besides smaller bundles, this innovation also allows a more direct and easier way for declaring services. Also, it might be a first foretaste of a future where modules are optional.<\/p>\n<p>In this post, I'm showing several options for using this new API and also point to some pitfalls one might run into. The <a href=\"https:\/\/github.com\/manfredsteyer\/treeshakable-providers-demo\/tree\/provideIn-module\">source code<\/a> I'm using here can be found in my <a href=\"https:\/\/github.com\/manfredsteyer\/treeshakable-providers-demo\/tree\/provideIn-module\">GitHub repository<\/a>. Please note that each branch represents one of the below mentioned scenarios.<\/p>\n<h2 id=\"why-and-a-first-how\">Why and (a first) How?<\/h2>\n<p>First of all, let me explain why we need treeshakable providers. For this, let's have a look at the following example that uses the traditional API:<\/p>\n<pre class=\"hljs\"><code><div>@NgModule({\n    [...]\n    providers: [\n        { provide: FlightService, useClass: FlightService }\n        <span class=\"hljs-comment\">\/\/ Alternative: FlightService<\/span>\n    ]\n    [...]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> FlightBookingModule {\n}\n<\/div><\/code><\/pre>\n<p>Let assume, our <code>AppModule<\/code> imports the displayed <code>FlightBookingModule<\/code>. In this case we have the following dependencies:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/v0M19XZ.png\" alt=\"Traditional API\"><\/p>\n<p>Here you can see, that the <code>AppModule<\/code> always indirectly references our service, regardless if it uses it or not. Hence, tree shaking tool decide against removing it from the bundle, even if it is not used at all.<\/p>\n<p>To mitigate this issue, the core team found a solution that follows a simple idea: Turning around one of the arrows:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/8I7XNTm.png\" alt=\"Traditional API\"><\/p>\n<p>In this case, the <code>AppModule<\/code> just has a dependency to the service, when it uses it (directly or indirectly).<\/p>\n<p>To express this in your code, just make use of the <code>provideIn<\/code> property within the <code>Injectable<\/code> decorator:<\/p>\n<pre class=\"hljs\"><code><div>@Injectable({ \n    providedIn: <span class=\"hljs-string\">'root'<\/span> \n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> FlightService {\n    <span class=\"hljs-keyword\">constructor<\/span>(private http: HttpClient) {}\n    [...]\n}\n<\/div><\/code><\/pre>\n<p>This property points to a module and the service will be put into this module's injection scope. The value <code>'root'<\/code> is just a shortcut for the root injector's scope. Please note, that this scope is used by all other eagerly loaded (=not lazy-loaded) modules. Only lazy loaded modules as well as components get their own scope which inherits from the root scope. For this reason, you will very likely use <code>'root'<\/code> in most cases.<\/p>\n<p>One nice thing about this API is that we don't have to modify the module anymore for registering the service. This means that we can inject the service immediately after writing it.<\/p>\n<h2 id=\"why-providers-and-not-components\">Why Providers and not Components?<\/h2>\n<p>Now you might wonder, why the very same situation doesn't prevent treeshaking for components or other declarations. The answer is: It also prevents this. Therefore, the Angular team wrote the <a href=\"https:\/\/www.angulararchitects.io\/post\/2017\/07\/26\/shrinking-angular-bundles-with-the-angular-build-optimizer.aspx\">build optimizer<\/a> which is used by the CLI when creating a production build. One of it's tasks is removing the component decorator with its meta data as it is not needed after AOT compiling and prevents for tree shaking as shown.<\/p>\n<p>However, providers are a bit special: They are registered with a specific injection scope and provide a mapping between a token and a service. All this meta data is needed at runtime. Hence, the Angular team needed to go one step further and this led to the API for treeshakbles providers we are looking at here.<\/p>\n<h2 id=\"indirections\">Indirections<\/h2>\n<p>The reason we are using dependency injection is that it allows for configuring indirections between a requested token and a provided service.<\/p>\n<p>For this, you can use known properties like <code>useClass<\/code> within the <code>Injectable<\/code> decorator to point to the service to inject:<\/p>\n<pre class=\"hljs\"><code><div>@Injectable({ \n    providedIn: <span class=\"hljs-string\">'root'<\/span>,\n    useClass: AdvancedFlightService,\n    deps: [HttpClient]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> FlightService {\n    <span class=\"hljs-keyword\">constructor<\/span>(private http: HttpClient) {}\n    [...]\n}\n<\/div><\/code><\/pre>\n<p>This means that every component and service requesting a <code>FlightService<\/code> gets an <code>AdvancedFlightService<\/code>.<\/p>\n<p>When I wrote this using version 6.0.0, I've noticed that we have to mention the dependencies of the service <code>useClass<\/code> points to in the <code>deps<\/code> array. Otherwise Angular uses the tokens from the current constructor. In the displayed example both expect an <code>HttpClient<\/code>, hence the <code>deps<\/code> array would not be needed. I think that further versions will solve this issue so that we don't need the <code>deps<\/code> array for <code>useClass<\/code>.<\/p>\n<p>In addition to <code>useClass<\/code>, you can also use the other known options: <code>useValue<\/code>, <code>useFactory<\/code> and <code>useExisting<\/code>. Multi Providers seem to be not supported by treeshakable providers which makes sense because when it comes to this variety, the token should not know the individual services in advance.<\/p>\n<p>This means, we have to use the traditional API for this. As an alternative, we could build our own Multi Providers implementation by leveraging factories. I've included such an <a href=\"https:\/\/github.com\/manfredsteyer\/treeshakable-providers-demo\/blob\/multi\/src\/app\/flight-api\/multi.token.ts\">implementation in my examples<\/a>; you can look it up <a href=\"https:\/\/github.com\/manfredsteyer\/treeshakable-providers-demo\/blob\/multi\/src\/app\/flight-api\/multi.token.ts\">here<\/a>.<\/p>\n<h2 id=\"abstract-classes-as-tokens\">Abstract Classes as Tokens<\/h2>\n<p>In the last example, we needed to make sure that the <code>AdvancedFlightService<\/code> can replace the <code>FlightService<\/code>. A super type like an abstract class or an interface would at least assure compatible method signatures.<\/p>\n<p>If we go with an abstract class, we can also use it as a token. This is a common practice for dependency injection: We are requesting an abstraction and get one of the possible implementations.<\/p>\n<p>Please note, that we cannot use an interface as a token, even though this is usual in lot's of other environments. The reason for this is TypeScript that is removing interfaces during the compilation as JavaScript doesn't has such a concept. However, we need tokens at runtime to request a service and so we cannot go with interfaces.<\/p>\n<p>For this solution, we just need to move our <code>Injectable<\/code> decorator containing the DI configuration to our abstract class:<\/p>\n<pre class=\"hljs\"><code><div>@Injectable({ \n    providedIn: <span class=\"hljs-string\">'root'<\/span>,\n    useClass: AdvancedFlightService,\n    deps: [HttpClient]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">abstract<\/span> <span class=\"hljs-keyword\">class<\/span> AbstractFlightService  {\n    [...]\n}\n<\/div><\/code><\/pre>\n<p>Then, the services can implement this abstract class:<\/p>\n<pre class=\"hljs\"><code><div>@Injectable()\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> AdvancedFlightService <span class=\"hljs-keyword\">implements<\/span> AbstractFlightService {\n    [...]\n}\n<\/div><\/code><\/pre>\n<p>Now, the consumers are capable of requesting the abstraction to get the configured implementation:<\/p>\n<pre class=\"hljs\"><code><div>@Component({ [...] })\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> FlightSearchComponent <span class=\"hljs-keyword\">implements<\/span> OnInit {\n\n  <span class=\"hljs-keyword\">constructor<\/span>(private flightService: AbstractFlightService) { \n  }\n\n  [...]\n}\n<\/div><\/code><\/pre>\n<p>This looks easy, but here is a pitfall. If you closely look at this example, you will notice a cycle:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/gVQXXYY.png\" alt=\"Cycle caused by abstract class that points to service that is implementing it\"><\/p>\n<p>However, in this very case we are lucky, because we are <code>implementing<\/code> and not <code>extending<\/code> the abstract class. This lesser known feature allows us to treat the abstract class like an interface: TypeScript just uses it to check the methods and the signatures. After this, it removes the reference to it and this resolves the cycle.<\/p>\n<p>But if we used <code>extends<\/code> here, the cycle would stay and this would result in an hen\/egg-problem causing issues at runtime. To make a long story short: Always <code>implements<\/code> in such cases.<\/p>\n<h2 id=\"registering-services-with-lazy-modules\">Registering Services with Lazy Modules<\/h2>\n<p>In very seldom cases, you want to register a service with the scope of an lazy module. This leads to an own service instance (an \"own singleton\") for the lazy module that can override an service of an parent's scope.<\/p>\n<p>For this, <code>provideIn<\/code> can point to the module in question:<\/p>\n<pre class=\"hljs\"><code><div>@Injectable({ \n    providedIn: FlightBookingModule,\n    useClass: AdvancedFlightService,\n    deps: [HttpClient]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">abstract<\/span> <span class=\"hljs-keyword\">class<\/span> AbstractFlightService  {\n}\n<\/div><\/code><\/pre>\n<p>This seems to be easy but it also causes a cycle:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/7Bal6HJ.png\" alt=\"Cycle caused by pointing to a module with provideId\"><\/p>\n<p>In a good discussion with <a href=\"https:\/\/github.com\/alxhub\">Alex Rickabaugh<\/a> from the Angular team, I've found out that we can resolve this cycle be putting services in an own service module. I've called this module just containing services for the feature in question <code>FlightApiModule<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/kVblKQw.png\" alt=\"Resolving cycle by introducing service module\"><\/p>\n<p>This means we just have to change <code>providedIn<\/code> to point to the new <code>FlightApiModule<\/code>:<\/p>\n<pre class=\"hljs\"><code><div>@Injectable({ \n    providedIn: FlightApiModule,\n    useClass: AdvancedFlightService,\n    deps: [HttpClient]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">abstract<\/span> <span class=\"hljs-keyword\">class<\/span> AbstractFlightService  {\n}\n<\/div><\/code><\/pre>\n<p>In addition, the lazy module also needs to import the new service module:<\/p>\n<pre class=\"hljs\"><code><div>@NgModule({\n    imports: [\n        [...]\n        FlightApiModule\n    ],\n    [...]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> FlightBookingModule {\n}\n<\/div><\/code><\/pre>\n<h2 id=\"using-injectiontokens\">Using InjectionTokens<\/h2>\n<p>In Angular, we can also use <code>InjectionTokens<\/code> objects to represent tokens. This allows us to create tokens for situations a class is not suitable for. To make this variety treeshakable too, the <code>InjectionToken<\/code> now takes a service provider:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> FLIGHT_SERVICE = <span class=\"hljs-keyword\">new<\/span> InjectionToken&lt;FlightService&gt;(<span class=\"hljs-string\">'FLIGHT_SERVICE'<\/span>,\n    { \n        providedIn: FlightApiModule, \n        factory: () =&gt; <span class=\"hljs-keyword\">new<\/span> FlightService(inject(HttpClient))\n    }\n);\n<\/div><\/code><\/pre>\n<p>For technical reasons, we have to specify a <code>factory<\/code> here. As there is no way to infer tokens from a function's signature, we have to use the shown <code>inject<\/code> method to get services by providing a token. Those services can be passed to the service the factory creates.<\/p>\n<p>Unfortunately, we cannot use <code>inject<\/code> with tokens represented by abstract classes. Even though Angular supports this, <code>inject<\/code>'s signature does currently (version 6.0.0) not allow for it. The reason might be that TypeScript doesn't have a nice way to express types that point to abstract classes. Hopefully this will be resolved in the future. For instance, Angular could use a workaround or just allow <code>any<\/code> for tokens. In the time being, we can cast the abstract class to <code>any<\/code> as it is compatible with every type.<\/p>\n<p>With this trick, we can create an injection token pointing to a service that uses our <code>AbstractFlightService<\/code> as a token.<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> BOOKING_SERVICE = <span class=\"hljs-keyword\">new<\/span> InjectionToken&lt;BookingService&gt;(<span class=\"hljs-string\">'BOOKING_SERVICE'<\/span>,\n    { \n        providedIn: FlightApiModule, \n        factory: () =&gt; <span class=\"hljs-keyword\">new<\/span> BookingService(inject(&lt;<span class=\"hljs-built_in\">any<\/span>&gt;AbstractFlightService))\n    }\n);\n<\/div><\/code><\/pre>\n<h2 id=\"using-modules-to-configure-a-module\">Using Modules to Configure a Module<\/h2>\n<p>Even though treeshakable providers come with a nicer API and help us to shrink our bundles, in some situations we have to go with the traditional API. One such situation was already outlined above: Multi-Providers. Another case where we stick with the traditional API is when providing services to configure a module. An example for this is the <code>RouterModule<\/code> with its static <code>forRoot<\/code> and <code>forChild<\/code> that take a router configuration.<\/p>\n<p>For this scenario we still need such static methods returning a <code>ModuleWithProviders<\/code> instance:<\/p>\n<pre class=\"hljs\"><code><div>@NgModule({\n   imports: [ CommonModule ],\n   declarations: [ DemoComponent ],\n   providers: [ <span class=\"hljs-comment\">\/* no services *\/<\/span> ],\n   exports: [ DemoComponent ]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> DemoModule { \n    <span class=\"hljs-keyword\">static<\/span> forRoot(config: ConfigService): ModuleWithProviders {\n        <span class=\"hljs-keyword\">return<\/span> {\n            ngModule: DemoModule,\n            providers: [\n               { provide: ConfigService, useValue: config }\n            ]\n        }\n    }\n}\n<\/div><\/code><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>why, how and cycles<\/p>\n","protected":false},"author":9,"featured_media":3018,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2370","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-unkategorisiert"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>The new Treeshakable Providers API in Angular - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The new Treeshakable Providers API in Angular - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"why, how and cycles\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2019-04-03T12:57:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"640\" \/>\n\t<meta property=\"og:image:height\" content=\"426\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"The new Treeshakable Providers API in Angular\",\"datePublished\":\"2019-04-03T12:57:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\"},\"wordCount\":1411,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg\",\"articleSection\":[\"Unkategorisiert\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\",\"name\":\"The new Treeshakable Providers API in Angular - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg\",\"datePublished\":\"2019-04-03T12:57:27+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg\",\"width\":640,\"height\":426},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"The new Treeshakable Providers API in Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The new Treeshakable Providers API in Angular - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/","og_locale":"en_US","og_type":"article","og_title":"The new Treeshakable Providers API in Angular - ANGULARarchitects","og_description":"why, how and cycles","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/","og_site_name":"ANGULARarchitects","article_published_time":"2019-04-03T12:57:27+00:00","og_image":[{"width":640,"height":426,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg","type":"image\/jpeg"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"The new Treeshakable Providers API in Angular","datePublished":"2019-04-03T12:57:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/"},"wordCount":1411,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg","articleSection":["Unkategorisiert"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/","name":"The new Treeshakable Providers API in Angular - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg","datePublished":"2019-04-03T12:57:27+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/the-new-treeshakable-providers-api-in-angular-why-how-and-cycles.jpg","width":640,"height":426},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/the-new-treeshakable-providers-api-in-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"The new Treeshakable Providers API in Angular"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2370","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=2370"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2370\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/3018"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=2370"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=2370"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=2370"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}