Squashing Mixed Content in Development with lcl.host
Tags: webdev, https, javascript, beginners
Published: 2024-03-22 17:24:13

[Mixed content](https://web.dev/articles/what-is-mixed-content) occurs when a webpage served over HTTPS loads a resource over HTTP. Browsers block these mixed content resources to protect your security, but blocked resources can break your pages. These bugs often slip through to production because browsers specifically allow mixed content on `http://localhost` pages. Switching to HTTPS in local development will make our browser block mixed content and behave the same for the local and deployed version.

Getting HTTPS setup and working with an app in local development is tricky. There were two options: acquire a publicly-trusted certificate from a CA, or make your own self-signed certificate from the command line. Neither of these options are simple, that's why most developers skip HTTPS in their development environment. But [lcl.host](https://lcl.host/) now makes this quick and easy.

[lcl.host](https://lcl.host/) is a free developer tool from [Anchor.dev](https://anchor.dev/) to setup a local HTTPS development environment in minutes. It combines the best parts of both public CA certificates and self-signed certificates, and it's built for novice and expert web developers alike. [Read more about how lcl.host works on the Anchor blog.](https://anchor.dev/blog/introducing-lcl-host)

Now we will look at mixed content issues in practice with an example app which attempts to load a script asset over HTTP. Our browser will allow the script to load via `http://localhost` but will block the script over HTTPS, just as it does with deployed apps. **Using HTTPS in local development let's us catch mixed content warnings and errors before we deploy and cause issues for users.**

### Mixed Content Example App

[`anchordotdev/mixed-content-example`](https://github.com/anchordotdev/mixed-content-example) is a nodejs app that triggers a mixed content error when served over HTTPS. We'll start by setting up the app and running it with just HTTP, which won't trigger any errors at all.

```
$ git clone https://github.com/anchordotdev/mixed-content-example
$ cd mixed-content-example
$ npm install
$ node ./index.js
mixed-content-example app over HTTP: http://localhost:3000
```

Browse to http://localhost:3000/ and you'll see "INSECURE SCRIPT LOADED AND RUN!!!", demonstrating that the insecure script loaded without any errors.

![insecure mixed content allowed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0x2pc6eyc9f1zryye7g.png)

This script will always be insecure because it's always served over HTTP, yet our browser allowed it through! Next let's setup and use lcl.host to serve the page over HTTPS and secure our page.

### lcl.host

Setting up local HTTPS used to be a pain, but lcl.host makes it easy: install the CLI, run `anchor lcl`, and work through the guided steps:


```
$ brew install anchordotdev/tap/anchor
$ anchor lcl
```

**For the example, we use the suggested values for all the prompts.** Once you are done, restart the app, and you'll see it is now listening on both **HTTP and HTTPS**:

```
$ node ./index.js
mixed-content-example app over HTTP: http://localhost:3000
mixed-content-example app over HTTPS: https://mixed-content-example.lcl.host:44375
```

Now open the HTTPS version in your browser, and **be sure to use the port number returned when you run the app, which may differ from what we depict here.** Notice this time the "INSECURE" message doesn't appear, because your browser blocked the script for you.

![secure mixed content blocked](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fns55lxe94rolaq4pw6c.png)

If we look in the devtools console, we also can see there is now a "Mixed Content" error for the insecure `simple-example.js` script.

![devtool console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d06t3qj4iifnyjo8j7aa.png)

Working through this example helped us reproduce mixed content errors and catch them in our dev tools console. You can use lcl.host to catch mixed content bugs in all your web applications too.

### Real World Apps

Using lcl.host with real development apps works the same as the example: run `anchor lcl` in the project directory and follow the guide. [Check out the lcl.host docs to learn more about other issues that local HTTPS helps mitigate.](https://anchor.dev/docs/lcl-host/why-lcl#when-do-i-need-https-locally)