Browsersync and Inertia.
Tired of those XMLHttpRequest CORS policy errors? Me too.
Here’s a quick one on using Browsersync with Inertia. If you’ve ever tried and you got hung up on those pesky CORS errors that prevent redirects, then maybe I have a workaround for you.
The bit about Browsersync
Browsersync is one of those tools that just sticks. It has fantastic staying power. When I started building stuff for the web, LiveReload was all the rage. I loved that I could put my browser on one screen, my editor on another and not need to manually refresh every time I needed to see a change. It would just update whenever I saved stuff.
LiveReload eventually fell out of favour (is it even still a thing? I don’t know) and I went off to find an alternative. It didn’t take me long to come across Browsersync. It kinda did the same thing LiveReload did, but without the need to install that UI app. It’s a node dependency in the actual project, and it worked nicely with Webpack (also a recent discovery at the time).
Browsersync works by proxying your dev environment URL. Instead of visiting your site at
whatever.test, you get a proxy url at
localhost:3000. Now browse around your site and the other browser will follow along. It really is just like magic.
It’s become an invaluable piece of my toolkit and not one I’m going to give up without a fight.
The bit about Inertia
Inertia is still pretty new, but I’ve used it in a bunch of places already and I find that I immediately miss it when I have to work on projects where Inertia wasn’t used.
So if Browsersync is fantastic, and Inertia is a little piece of Laravel developer heaven, what could possibly be the problem? Well, the problem isn’t really a problem at all. It’s actually a good thing. It’s a simple piece of security baked into all our browsers called CORS.
CORS (Cross Origin Request Sharing) is designed to help prevent cross-site request forgeries. It’s intention to either give or deny an application running at one domain access to the resources of an application running at a very different domain.
whatever.test ) and the proxy URI served by Browsersync (
localhost:3000 ). From the browsers point of view, that’s two distinct origins. The result is the following:
It’s frustrating, but it’s also kind of a good thing. You don’t really want to break this stuff because it’s actually going to make your life easier later on.
The quick solution
So there are two solutions to this. The first thing that you might come across is why not just set the CORS headers to allow the different origins access to each others resources? That’s not a bad idea, but if you don’t have any intention of making cross origin requests outside of your dev environment, then this feels a little like breaking the wheel, then re-inventing the wheel, and then changing the wheel again before going into production.
Setting up CORS correctly takes a bit of time and can be a little tricky. There are a few packages around that attempt to make the process easier, but you’ll need to go read up a bunch about CORS first. Note that I’m not advocating for ignoring CORS at all. You definitely should go and learn about what CORS is and why it’s causing these errors in the first place, but sometimes I just don’t think it’s necessary to change the browser defaults.
Instead, there is a really simple solution and is requires two tiny changes.
First, update your Browsersync config and add the
open option and set it to false. If you’re a Laravel Mix user, you can do this with:
If you’re not a mix user, I’m sure you can translate the above into whatever you’re using. The Browsersync options are the same regardless.
To be honest, this first change isn’t all that necessary, but it will stop the browser from opening automatically which gets a little annoying eventually. Especially when your default browser isn’t the one you use for development (yes, I’m weird like that).
Next, add this small addition to your
app.blade.php file that you created when you were setting up Inertia.
You’ll still get all that magical Browsersync goodness, and you can continue to use Inertia as before. There’s no need to go fiddling with CORS headers (which would have been a much bigger, and more time consuming change).
app()->isLocal() means you don’t need to worry about it being used in production so you can just leave it there. As long as you’re environment isset to
local and you have Browsersync watching your project, you can carry on as normal.