We faced exactly the same choices for our live service that deploys a laravel API and multiple react apps.
There is no generic correct answer to a question "what tool/provider is better?" as it depends on your circumstances. Cost is a particularly tricky question. Are we just talking about the cost of getting something live, or the cost of running an elastically scalable service, or the cost of running a highly available elastic service that spans data centre availability zones such that it isn't taken down by an outage in a single data centre zone?
Digital Ocean ("DO") is very highly promoted in the Laravel community so it was "the default" for the development team when I joined a startup about two months from go-live. When I asked "what about data centre availability zones" the answer at the time for Digital Ocean was that they didn't support it and we would have to set-up in two different DO data centres and work on our own mechanism (e.g. DNS) to switch between them if DO had a major outage in one place. Yet on AWS they have availability zones and also Elastic Load Balancer so its far easier to get a setup going that is "future ready" if you intend to be running a very successful large scale service a year after launch.
In the end we went live on openshift.com which is a shared kubernetes service running on AWS. So our live DNS points at the Elastic Load Balancer of a shared Kubernetes cluster were we rent space for our containers. The cluster we are on has containers by other companies and runs across many AWS EC2 virtual machines. Yet they are not dedicated to us so we only pay a small fraction of the costs. Yet if any one virtual machines crashes where our containers are running openshift kubernetes automatically starts a replacement container on another virtual machine. So we have automated high availability and crash recovery but only pay-as-we-go for the memory and CPU we currently use. We can scale up more containers anytime we want by using changing the replica count. Openshift has internal load balancing so that a single internal service IP with an internal DNS name automatically points at however many containers we want to run of a particular type. That solves discovery between our services. If you deploy a redis instance from the built-in catalog it is instantly available on a private IP with a DNS entry only viable in your project. That sort of ”discovery” feature is really important when you are running microservices at scale.
With our setup, we get a great low-cost price for a very professional, elastic, highly scalable, fully automated infrastructure-as-code setup, that has all the advantages of AWS ELB, and all the advanced features of kubernetes for microservices.
Edit: I wrote a tutorial for my experiences running laravel backend with a reactjs frontend on openshif.com that is over at https://gist.github.com/simbo1905/d27ba7218a2fd71fcb4f0fcede82fd6d