Firebase Hosting has a feature called rewrites, which allows you to configure your firebase.json
file to achieve things like:
- Redirecting all paths to
/index.html
(useful for SPAs) - Redirecting requests to
/items/1234
to/items/id.html
- Redirecting requests to
/api/get_item
to the HTTP trigger of the Cloud Functionsget_item
function
Additionally, by using the cleanUrls attribute, you can remove the .html
extension from URLs. Accessing /page
will retrieve the file /page.html
uploaded to Hosting, while accessing /page.html
will redirect to /page
with a 301 redirect.
These behaviors are very convenient for creating sleek web applications and are often used, but they only work in applications deployed to the Firebase production environment. In the production environment, /items/1234
returns /item/id.html
, but in the development environment, /item/1234
results in a 404 error, which can be frustrating.
rewriteproxy#
To address this, I created a proxy that replicates the behavior of rewrites and cleanUrls in the development environment. It reads your local firebase.json
and operates accordingly.
You can find the repository here.
It is a simple reverse proxy written using the httputil.ReverseProxy
from Go's standard library. Here's how to use it:
$ rewriteproxy \
--port=3000 \
--firebase-json=/path/to/firebase.json \
--web-app-url=http://localhost:1234 \
--cloud-function-base-url=http://localhost:5001/your-project-id/us-central1
The --web-app-url
is the URL of the web application you started locally. For example, if you are using webpack-dev-server, it might be http://localhost:8080
, or if you are using parcel, it might be http://localhost:1234
. The --cloud-function-base-url
specifies the URL of the locally running Cloud Functions Emulator. This is what runs when you execute yarn run serve
in the functions/
directory of your Firebase project.
Examples#
Path Rewriting#
For example, if you write the configuration to redirect requests to /items/1234
to /items/id.html
in your firebase.json
, and then start the proxy with the command above, accessing http://localhost:3000/items/1234
will return the file hosted at http://localhost:1234/items/id.html
in your web application.
Cloud Functions#
If you write the configuration to redirect requests to /api/get_item
to the HTTP trigger of the Cloud Functions get_item
function in your firebase.json
, accessing http://localhost:3000/api/get_item
will execute the local Cloud Functions emulator at http://localhost:5001/your-project-id/us-central1/get_item
.
cleanUrls#
When cleanUrls: true
is set, it will proxy URLs without .html
to the web application with .html
appended.
Conversely, if you access with .html
appended, it will redirect to the URL without .html
with a 301 redirect and behave the same as mentioned above.
Root Path#
Additionally, accessing /
will be proxied to the web application's /index.html
.
How to Integrate with Your Firebase Project#
In your project directory, you should have functions
and public
directories. Create a dev
directory (you can name it anything) at the same level and run yarn add -D concurrently
inside it.
PROJECT_ROOT
├── firebase.json
├── functions # Implementation of Cloud Functions
├── public # Implementation of Hosting
└── dev
├── package.json
├── setup
├── start
└── yarn.lock
Prepare the start
script and set its contents like this. Feel free to modify the URLs and port numbers to your liking. I often run the parcel dev server on port 1235
and receive the rewriteproxy on 1234
. This way, when developing, you can run dev/start
to start the web app dev server, Cloud Functions emulator, and rewriteproxy together.
#!/bin/sh -eux
cd "$(dirname "$0")"
./node_modules/.bin/concurrently --kill-others \
-n public,functions,proxy \
-c cyan,yellow,blue \
"cd ../public && yarn run dev" \
"cd ../functions && yarn run serve" \
"$(go env GOPATH)/bin/rewriteproxy --firebase-json=../firebase.json --port=1234 --web-app-url=http://localhost:1235 --cloud-function-base-url=http://localhost:5001/YOUR-FIREBASE-PROJECT-ID/us-central1"
By the way, I think it would be convenient to set up setup
like this.
#!/bin/sh -eu
cd "$(dirname "$0")"
# dev
cd ../dev
yarn install
go get github.com/morishin/rewriteproxy
cd -
# public
cd ../public
yarn install
# functions
cd ../functions
yarn install
Feel Free to Use It#
If you are developing a web application using Firebase Hosting rewrites or cleanUrls, I think this will be useful, so feel free to use it.
The implementation of this rewriteproxy is minimal and only includes the features I often use from Firebase Hosting rewrites: "path rewriting," "proxying to Cloud Functions," and "removing .html." If you would like to use other features locally, I would appreciate it if you could open an issue or implement it and submit a PR.