Firebase Hosting Staging and Production
Terminal
Syntax
firebase target:apply hosting <targetName> <resourceName>
Sample
firebase target:apply hosting staging firebase-project-id-staging
How to get the "Resource" name
Make sure to set up the Hosting configuration inside the Firebase console first and use the domain name (remove the "web.app")
How to add the "Target" in firebase target:apply hosting staging firebase-project-id-staging
- This might cause this error is not set up properly: Must supply either "site" or "target" in each "hosting" config.
Add target object inside hosting array. Make sure to have different public folder for production (app) and staging(staging)
firebase.json
{
"hosting": [
{
"public": "www",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
},
{
"target": "production",
"public": "www",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
{
"target": "staging",
"public": "www-dev",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
],
}
Execute command firebase target:apply hosting staging firebase-project-id-staging
.firebaserc (Before the target command)
{
"targets": {
"firebase-project-id": {
"hosting": {
"app": [
"firebase-project-id"
]
}
}
},
"projects": {
"default": "firebase-project-id",
}
}
.firebaserc (After the target command)
{
"targets": {
"firebase-project-id": {
"hosting": {
"app": [
"firebase-project-id"
]
}
},
"firebase-project-id-staging": {
"hosting": {
"staging": [
"firebase-project-id-staging"
]
}
}
},
"projects": {
"default": "firebase-project-id-pwa",
"staging": "firebase-project-id-staging"
}
}
Transition to different development
Syntax
firebase use <projectName>
Where to find the
.firebaserc
{
"targets": {
"firebase-project-id": {
"hosting": {
"app": [
"firebase-project-id"
]
}
},
"firebase-project-id-staging": {
"hosting": {
"staging": [
"firebase-project-id-staging"
]
}
}
},
// Use the projects property as <projectName>
"projects": {
"default": "firebase-project-id-pwa",
"staging": "firebase-project-id-staging"
}
}
Implementation
firebase use default // Production
firebase use staging // Staging
Project build
ionic build --prod // Production
ionic build -c=staging // Staging
Alternative
ng build --configuration=production // Production
ng build --configuration=staging // Staging
Note: You can use the alternative command when you set up this properly in angular.json file. Add *staging object under the configurations
angular.json
{
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"serviceWorker": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "50kb"
}
],
"ngswConfigPath": "ngsw-config.json"
},
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.prod.ts",
"with": "src/environments/environment.ts"
}
],
"outputPath": "www-dev"
},
}
}
Firebase deploy to Hosting
firebase deploy --only hosting:default // Production
firebase deploy --only hosting:staging // Staging
or Short method
firebase deploy -P default // Production
firebase deploy -P staging // Staging
Alternative
// Production
firebase use default
firebase deploy --only hosting
// Staging
firebase use staging
firebase deploy--only hosting
Note: You can also use firebase deploy after firebase use
Firebase Function Staging and Production
First go the environment you need to set up
Terminal
firebase use default // Production
firebase use staging // Staging
Set up the dynamic credentials.
Use case: Different Firebase hosting or API connections for staging and production environment that shares one firebase function
Terminal
firebase functions:config:set creds.api="5b3323d" creds.storagebucket="firebase-staging.appspot.com"
Firebase function sample (index.js)
Add functions.config() to use the credential configuration
exports.getAPI = functions.https.onRequest((req, res) => {
const headers = {
'API-Id': functions.config().creds.api,
'content-type': 'application/json'
};
console.log(headers)
})
To check the credential that have been set up for the current environment
Terminal
firebase functions:config:get
Output
{
creds: {
api: '5b3323d',
storageBucket: 'firebase-staging.appspot.com'
}
}
Update the configuration
firebase functions:config:set creds.api="10101" creds.newkey="12345" keypath.url="./firebase-staging.json"
Output (Previous set up)
{
creds: {
api: '5b3323d',
storageBucket: 'firebase-staging.appspot.com'
}
}
Output (New)
{
creds: {
api: '10101',
storageBucket: 'firebase-staging.appspot.com',
newkey: '12345'
},
keypath: {
url: './firebase-staging.json'
}
}
How to have dynamic Firebase admin credential key
- Download first the credential json file from Firebase console Settings > Service Accounts and click Generate new private key button located at the button of the page
- Add the downloaded file inside the function folder (firebase function directory in the local)
- Update the require command inside the firebase function index.js to const key = require('' + functions.config().creds.keypath); . Make use to concat the functions.config to blank string.
index.js
const functions = require('firebase-functions');
const key = require('' + functions.config().creds.keypath);
const fbAdmin = require('firebase-admin')
fbAdmin.initializeApp({
credential: fbAdmin.credential.cert(key),
});
After firebase functions:config:set, deploy it using
firebase deploy --only functions
Ionic Staging and Production
Set up the production and staging inside the angular.json. Make sure to add fileReplacements and outputPath property
{
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputPath": "www"
},
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.prod.ts",
"with": "src/environments/environment.ts"
}
],
"outputPath": "www-dev"
},
}
}
Note: This works well when you try to deploy this to different Firebase hosting for production and staging but it won't work well in the localhost.
Serve based on environments in Ionic localhost
If you use ionic serve for local development. It doesn't implement the fileReplacements for environment.ts.
Solution:
ng serve --configuration=production // Production
ng serve --configuration=staging // Staging
References:
https://firebase.google.com/docs/hosting/multisites https://firebase.google.com/docs/cli/targets https://github.com/firebase/firebase-tools/issues/902 https://jsmobiledev.com/article/multiple-firebase-projects