We are using firebase to host our react js application.
Also, we have a WordPress blog, hosted on Siteground.
We need to access the blog from [Domain]/blog
Firebase offers hosting configuration object and you can use rewrite rules to define source and destination.
But unfortunately, it just lets you add a local path in Destination, not external IP or Domain.
We need something like this in firebase hosting config object:
"hosting": {
// ...
// Serves index.html for requests to files or directories that do not exist
"rewrites": [ {
"source": "/blog",
"destination": "[SERVER IP / CUSTOM"
} ]
}
Is it possible?
Related
I checked the docs here: https://firebase.google.com/docs/hosting/multisites and here: https://firebase.google.com/docs/cli/targets but I don't think I understand them well enough and I am unable to host different content on different subdomains within the same domain using Firebase. E.G (page.website.com and website.com) My Firebase.json file looks like this:
{
"hosting": [{
"target": "mainSite",
"public": "public"
},
{
"target": "authentication",
"public": "authentication"
}
]
}
I don't really understand where to direct the folder to the subdomain using:
firebase target:apply hosting TARGET_NAME RESOURCE_IDENTIFIER
Is that RESOURCE_IDENTIFIER? E.G is website.com or whatever site what I should put into RESOURCE_IDENTIFIER? I am lost.
I don't really understand where to direct the folder to the subdomain
using:
firebase target:apply hosting TARGET_NAME RESOURCE_IDENTIFIER Is that
RESOURCE_IDENTIFIER? E.G is website.com or whatever site what I should
put into RESOURCE_IDENTIFIER? I am lost.
RESOURCE_IDENTIFIER refers to the SITE_ID values that you used to construct the Firebase-provisioned default subdomains for the site, see this section of the doc.
You defined them when executing the following command in the the Firebase CLI:
firebase hosting:sites:create SITE_ID
In parallel (and independently of the previous settings) you can associate a custom domain (e.g. page.website.com and website.com) to each of your site.
I have a monorepo with two projects - web and docs. Each of these is their own Vercel project with the web project mounted at https://example.com and docs mounted at https://docs.example.com. All of this works as expected.
I now want to have the docs project be available at https://example.com/docs. In the web project, I setup the following rewrites in my vercel.json file.
{
"rewrites": [
{
"source": "/docs/:match*",
"destination": "https://docs.example.com/:match*"
},
{ "source": "/(.*)", "destination": "/" }
]
}
This works for the main index file, but all of the corresponding css and js files result in 404's. The browser is looking for those files at https://example.com/_next which isn't correct, it should be looking at https://docs.example.com/_next.
How do I make this work?
rewrite vs. redirect
Let's first understand this difference.
A rewrite is something that happens on the server only. The server will rewrite the URL that has been requested and search for content of that rewritten URL. The client will not know anything about that. E.g. if /a.html is rewritten to /b.html, the client will receive the same content on both URLs. Client won't know, if there is the same file two times or if one (or both) requests have been rewritten to some other resource.
A redirect on the other hand side involves the client (i.e. browser). If the server is asked for an URL that should be redirected, it will reply back to the client/browser with the destination URL of the rewrite. The client will then send another request for the new URL and make this visible to the end user by changing the address in the navigation bar. If /a.html is redirected to /b.html, the client will not receive the actual content of b.html when requesting a.html, but the browser will update the address to b.html and send a new request.
What's the issue with rewrites in your case?
The HTML contains references to other resources using absolute paths, e.g. something like:
<script src="/_next/static/..."></script>
If this file should be served as docs.example.com and example.com/docs (e.g. using rewrites), the actual HTML will not change. The browser will thus try to access docs.example.com/_next/static/... or example.com/_next/static/... respectively. That works for the first case (docs.example.com), but not for the second one. You've noticed that already.
You can change the basePath of next, e.g. to /docs. Then the HTML would contain <script src="/docs/_next/...">. That would make the browser request docs.example.com/docs/_next/... or example.com/docs/_next/... respectively. That would work for the second case, but not the first one. You could heal the first case with more rewrite rules, but I'd suggest a KISS solution.
Now what?
As mentioned in the comments, placing the exact same content at two different addresses is not good practice. And you can see, that is is causing subsequent difficulties as well. (Not to mention punishment by search engines for duplicate content.)
A good solution would be to decide where to store the content. That should be either docs.example.com or example.com/docs, not both.
Using docs.example.com, forwarding example.com/docs/ to docs.example.com
I'd suggest (and assume in this section) to take docs.example.com to have a clear separation of concerns.
So in Vercel you would set up two projects. One for your "main" next instance, another one for the "docs" next instance. (Both can come from the same repo, that doesn't matter.)
You then assign domains to both projects, e.g. www.example.com to the "main" project, docs.example.com to the "docs" project.
example.com as well as docs.example.com should be working right now.
example.com/docs/ should yield a 404 error.
Then you add redirects (not rewrites!) for your "main" project by adding a vercel.json like this:
{
"redirects": [
{ "source": "/docs/:path*", "destination": "https://docs.example.com/:path*" }
]
}
Now, if you enter example.com/docs/foo in your browser, you should be redirected to docs.example.com/foo and the page should load properly.
Using only example.com/docs/
If you decide to have the docs content only at example.com/docs/, the solution would be as follows:
Add basePath: '/docs' to next.config.js of the docs next project. Do not add a domain to this vercel project.
In the "main" next project add a vercel.json with a rewrite like this:
{
"rewrites": [
{ "source": "/docs", "destination": "https://$domain-of-docs-project.vercel.app/docs" },
{ "source": "/docs/:path*", "destination": "https://$domain-of-docs-project.vercel.app/docs/:path*" }
]
}
Please comment, if you have additional questions or this doesn't fix the issue.
I think you can use the vercel.json like this:
{
"rewrites": [
{
"source": "/:path*",
"has": [
{
"type": "host",
"value": "docs.example.com"
}
],
"destination": "/docs/:path*"
}
]
}
Next offers a specific example for this.
Your "web" project should handle rewrites, as seen here.
next.config.js:
const { DOCS_URL } = process.env //this should be the vercel URL NOT docs.example.com
/** #type {import('next').NextConfig} */
module.exports = {
async rewrites() {
return [
{
source: '/:path*',
destination: `/:path*`,
},
{
source: '/docs',
destination: `${DOCS_URL}/docs`,
},
{
source: '/blog/:path*',
destination: `${BLOG_URL}/docs/:path*`,
},
]
},
}
Your "docs" app needs to set a base path, as seen here. next.config.js:
module.exports = {
basePath: '/docs',
}
Then to ensure that docs.example.com no longer serves the docs as well, I'd just remove the DNS record. Instead you'll just have a vercel URL that you will use in the rewrites in "web". No need to point to that server from docs.example.com.
Nextjs documentation for multi-zone
Nextjs example with multi-zones
I deployed a new version of a web app that included some new Firebase functions. The new Firebase functions were inaccessible upon deployment.
I was able to find the root cause by familiarity with Firebase's configuration: the function requests were intended to route through the main app domain, and be redirected on the Firebase server to their final destination. (This should have been set up with Firebase's 'rewrites' section of firebase.json, but wasn't.)
A partial view of my rewrites section of firebase.json:
"rewrites": [
{
"source": "/getPlaces",
"function": "getPlaces"
},
...
{
"source": "**",
"destination": "/index.html"
}
]
In plain English, this says, "Firebase server: every time you get a request routing to https://my.app/getPlaces, I want you to not route to that address within my app; I want to invoke my Cloud function instead. Otherwise, route normally."
Yet when I look at the Functions tab of my Firebase console, all I see is this:
Under 'Request', it says https://us-central1-my-app.cloudfunctions.net/getPlaces. That gives me just one of the ways to access my function; the other is https://my.app/getPlaces, as defined in rewrites. I need to know all of the addresses that Firebase will respond to, not just the default one using cloudfunctions.net.
Is it possible to see the entire configuration for the deployed Firebase functions anywhere in the web UI, ie console.firebase.com or console.cloud.google.com, where redirects from rewrites like this can be seen?
I have a website that I'm already running on firebase hosting using a google domain. I would like to now show all calls to my firebase function being made through a url such as api.mydomain.com, instead of the default firebase domain. How is it that I may be able to do this?
I read the firebase tutorial on hosting cloud functions, and I also came across this article on creating multiple sites. So could someone please tell how is it that I can set up the workflow such that my site is still running at mydomain.com, but my APIs are now being called through api.mydomain.com? What would be the target name for
If possible, I Would like all requests to be shown as requests to api.mydomain.com, and not to api.mydomain.com/endpoint - so that what endpoint is being hit is also hidden from public
Sorry, I am new to this.
Let's say your main project has an ID of example-app. To serve requests as api.mydomain.com, you would have to use a Cloud Function that makes use of express (or some other similar route handler).
Create the secondary site for your project using the Firebase CLI, (with an id of example-app-api, example-api, etc.)
firebase hosting:sites:create example-app-api
Connect your hosting targets to your resources
firebase target:apply hosting app example-app
firebase target:apply hosting api example-app-api
Modify your firebase.json file to suit the targets above.
{
"hosting": [
{
// app is linked to example-app, served as mydomain.com
"target": "app",
// contents of this folder are deployed to the site "example-app"
"public": "public",
// ... other settings ...
},
{
// api is linked to example-app-api, served as api.mydomain.com
"target": "api",
// Contents of this folder are deployed to the site "example-app-api"
// Any file here will be returned instead of calling your Cloud Function.
// Recommended contents:
// - favicon.ico (website icon for bookmarks, links, etc)
// - robots.txt (instructions for bots and scrapers)
// Optional contents:
// - service-worker.js (empty file, used to prevent triggering cloud function)
// - humans.txt (details about who you/your company are & how to report bugs)
"public": "api-static-resources",
// ... other settings ...
"rewrites": [
{
// redirect all calls to the function called "api"
"source": "**",
"function": "api"
}
]
}
]
}
Deploy the api hosting config using the Firebase CLI
firebase deploy --only hosting:api
Open Hosting Settings for your project, click "View" for example-app-api then click "Custom Domain" following these instructions.
You should now be able to trigger your Cloud Function by calling it at api.mydomain.com.
api.mydomain.com/getPost?id=someId
api.mydomain.com/favicon.ico
api.mydomain.com/robots.txt
Can firebase hosting be used to deploy a node.js application that requires dynamic routing. Why do they call that hosting can be used to deploy single page app.
Firebase Hosting project structure
Something like this:
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var homeRouter = require('./routes/home');
And then have the routes in the routing folder
Firebase Cloud Functions do support Express.js routing.
You can read more in the docs or follow this medium post for more of a walkthrough.
Edit:
For more on using the express router with module imports take a look at this blog.
{
"hosting": {
// ...
// Add the "rewrites" attribute within "hosting"
"rewrites": [ {
"source": "**", // <<< Do this in your firebase.json
"function": "app"
} ]
}
}