A web app designed with highly modular, small components (in this case using AngularJS directives but could just as easily be WebComponents, ReactJS components, or any other technology). Components often have asynchronous REST API calls, upon initialization or upon user interaction. This design is causing many API calls per page (sometimes 20+). Is there any problem with this design? Some are suggesting we condense the API calls into larger client-side services that act as singletons. So 10 API calls may be reduced to 1, even though a page may only use a portion of that data. Are there any red flags, or problems with this design? Which should be preferred?
This design is causing many API calls per page (sometimes 20+). Is there any problem with this design?
There shouldn't be. The fact that each request is small and async means you can greatly speed up your web app, rather than having to wait for a single large request to complete which blocks everything.
Browsers limit the total number of concurrent requests
So yes, there is a problem with this design. However I think the accepted response is to move to a web-sockets implementation where you use a single connection, but with many message types to communicate with the server
Don't forget the size of each network request. Generally, if each request only returns like 2 KB of data, then the network request is to expensive for that small amount of data.
If the network request goes up to 400KB, then break it into two. But generally, not enough data for a single network request is more often the issue.
Some considerations here:
If you are seeing acceptable performance, you shouldn't worry too much about it. If you can manage to run HTTP2 you should see an increase in performance.  .
As with any design, there are no hard fast rules as to whether you should do many small requests or few large requests. Some things to consider:
Are many of the calls interdependent? If you have a complex dependency relationship between different calls it can make maintenance harder.If this is the case batching related response data would make sense.
Do different components share much of the same data? If this is the case you could have a central point that does the shared calls and allows components access to the shared data.
Keep an eye on the maintenance burden of the small components doing separate calls. You will know when it becomes hard to manage and then a change may be necessary. Changing a design based on hypothetical future needs can cause design mistakes, because you have to accurately anticipate what problems you will have in the future. If it's working well now, changing it would also be unnecessary.
1: "HTTP/2 is fully multiplexed allowing multiple files and requests to be transferred at the same time, as opposed to HTTP1.x which only accepted one single request / connection at a time. HTTP/2 uses the same connection for transferring different files and requests, avoiding the heavy operation of opening a new connection for every file which needs to be transferred between a client and a server." - https://css-tricks.com/http2-real-world-performance-test-analysis/