The purpose of this post is to show a worked example of updating an existing Angular 6 solution to use the new
HttpClientModule
available with version 6 of Angular. This new module provides a higher level
abstraction for developers to deal with when making HTTP requests when compared to the Http
module
available in Angular <6.0.0
.
There are no actual package changes strictly necessary in order to make use of the HttpClientModule
– it
is included as part of the @angular/common
module. However to ensure all references to the legacy
HttpModule
have been completely eradicated it is best to remove the module from package.json
so the
solution will not compile successfully until they are all removed.
The old Http
service provided by HttpModule
only dealt with simple HTTP requests &
responses, leaving the parsing of request bodies and subsequent responses to consumers. Almost all the HTTP requests to
my solution’s
ASP.NET Core 2 backend are JSON based and require a common set of headers (XSRF token, Content-Type
), so I had
previosuly authored my own HttpService
to hide some of the complexity around making such requests, leveraging
the Angular Http
service plus third party library TypedJSON
, along with other custom abstractions
around obtaining request headers (RequestHeadersService
) and obtaining and managing XSRF tokens
(XSRFTokenService
).
Much of this bespoke code's functionality is now either provided OOTB by the new
HttpClient
or alternatively can be wired in via various extensibility points.
Since my solution is fairly loosely coupled, there are only a small number of references to my bespoke HttpService
I made the decision to simply remove it rather than update it to be just a thin wrapper around Angular's HttpClient
– obviously on complex and/or larger projects it may be appropriate to retain the wrapper and delay tackling that
technical debt to another day. The change to HttpClient
markedly simplifies consumer code, for example:
The functionality formerly provided by XSRFTokenService
to HttpService
also needed to be replicated
in the HttpClient
world. One way to achieve this to create a HttpInteceptor
implementation
which can transform requests before they are sent:
Note how the code simply passes through requests for the token endpoint without modification – this is necessary
otherwise a recursive loop gets entered until a stack overflow occurs, as the HttpInteceptor
is registered
to intercept all HTTP requests thusly (note the use of the ClassProvider
provider interface):
With my code now building successfully using the Typescript compiler, it became time to try testing it in the browser.
As those of you who read the previous installment of this series
will know, this solution use the SystemJS
ES Module Loader as it has its origins in the Angular 2 RC Quickstart repo. And because of this things don't
work automagically like they would if using ng serve
. And so it again proved with these changes.
After many failed attempts to get HttpClientModule
to load correctly in the browser with the SystemJS ES
Module Loader I resorted to the sledgehammer apporach of simply adding an explicit mapping from its module name to
its corresponding UMD JS bundle location under the node_modules
directory tree, also taking the
opportunity to remove other unneeded cruft:
It seems that the HttpClientModule
UMD JS bundle does not follower earlier naming conventions and consequently
the ngPackage
convention based loading is broken, at least for this module. If someone has a more eloquent way to get this to work
please shoot me a message via LinkedIn.
HttpModule
to HttpClientModule
↗