Thanks for getting back to me on that @mattbartel, that is what I have ended up doing on my end as well,
I was using create-react-app and wanted to avoid ejecting so we could continue to receive vendor updates, I ended up storing my SPA frontend in it's own subdirectory as part of my main repository.
An early step in the vapor build process generated a .env file in my SPA frontend which populated create-react-app's PUBLIC_URL with the automatically generated ASSET_URL variable generated by vapor deploy. This ensured create-react-app was able to do code-splitting and all other such niceties without too much fuss.
A later step in the build process actually stripped out all of the and tags from my generated create-react-app production build and saved them in an spa.blade.php file which was included alongside my usual initial main app layout, including the initial page state loading and CSRF token you mentioned.
The solution works and I'm comfortable with it because in the end it was easier to just wrangle the generated create-react-app HTML and build steps than eject and lose those upstream fixes and CRA scripts.
I also have not gotten to the stage where I have had to worry about the Service Worker and I don't envisage I'll look into that anytime soon either.
I think a vendor-supported vapor-esque solution for serving up static files with appropriate cache headers etc from the root domain would mitigate a lot of these issues and others (authentication domains with google analytics etc etc) but for now I'm happy with what I came up with.
If anyone needs a hand getting a create-react-app project integrated with a Vapor deployment process please don't hesitate to get in touch.
Thanks for your help again @mattbartel,
Cheers,
Michael