How to define Firebase? - angularjs

Im trying to learn Angular and the video tutorial I am doing is using Firebase, Ive got Firebase defined as
//Contacts controller
.controller('ContactsCtrl', ['$scope', '$firebaseArray', function($scope, $firebaseArray) {
//init firebase
var ref = new Firebase('https://myappurl-048596.firebaseio.com/');
but when viewing the console, I keep getting errors saying Firebase not defined and it breaks the whole project. So, how do I properly define Firebase so that I can get rid of this error?

Follow this link: https://firebase.google.com/docs/web/setup
Add this in your config function:
var firebaseConfig = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(firebaseConfig);

Related

How to use process.env in a React service worker

I am trying to set-up a Firebase-messaging-sw.js file (for web push notifications). I am wondering if there is a way to avoid exposing my Firebase config data to the public as much as possible - though it might be revealed anyways? (I'm not too sure about the nuances)
I've tried following: How can I customize my Service Worker based on environment variables? But the answer's swEnvbuild doesn't seem to be running, as the swenv.js file is not found. I suspect it might need to be set-up differently in React?
(first question, please feel free to provide constructive criticisms of my question)
I recently had to do this with a CRA app, it's not easy to find information on it so I figured I should share my solution. Assuming you've already changed serviceWorker.unregister() to serviceWorker.register() in ./src/index.js, and have a .env file with your variables set in the root of your project, then you can update ./src/serviceWorker.js to include your process.env variables as a query string.
In the register function in serviceWorker.js, update const swUrl as shown below, notice the const firebaseConfig w/process.env, declared before swUrl..
./src/serviceWorker.js:
// Convert environment variables to URL `search` parameters
const firebaseConfig = new URLSearchParams({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
}).toString();
// Service worker URL w/config variables
const swUrl = `${process.env.PUBLIC_URL}/firebase-messaging-sw.js?${firebaseConfig}`;
then in ./public/firebase-messaging-sw.js (create it if it doesn't exist), you can do something like the following..
./public/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/8.0.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.2/firebase-messaging.js');
// Set Firebase configuration, once available
self.addEventListener('fetch', () => {
const urlParams = new URLSearchParams(location.search);
self.firebaseConfig = Object.fromEntries(urlParams);
});
// "Default" Firebase configuration (prevents errors)
const defaultConfig = {
apiKey: true,
projectId: true,
messagingSenderId: true,
appId: true,
};
// Initialize Firebase app
firebase.initializeApp(self.firebaseConfig || defaultConfig);
const messaging = firebase.messaging();
// Configure message handler (assumes backend is set up)
messaging.onBackgroundMessage((payload) => {
const { icon, body, title } = payload.data;
self.registration.showNotification(title, { body, icon });
});
If there's a more ideal solution, would love to hear about it, but this configuration worked for me.
I found this article which uses cra-append-sw to append the env vars. Then I created two pre scripts in my package.json. When I run npm start the prestart script runs creating a [root folder]/public/firebase-messaging-sw.js file that contains the env vars (after being processed by webpack).
Implementation
I created a [root folder]/firebase-messaging-sw.js. This file will be processed by webpack replacing the values of the env vars.
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.1.1/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/logo.png'
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
then I have [root folder]/.env.dev and [root folder]/.env.prod
REACT_APP_FIREBASE_API_KEY=A...
REACT_APP_FIREBASE_AUTH_DOMAIN=d...
REACT_APP_FIREBASE_DATABASE_URL=h...
REACT_APP_FIREBASE_PROJECT_ID=d...
REACT_APP_FIREBASE_STORAGE_BUCKET=d...
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=7...
REACT_APP_FIREBASE_APP_ID=1...
REACT_APP_FIREBASE_MEASUREMENT_ID=G...
And finally, i added 2 pre scripts in my package.json
...
"scripts": {
"prestart": "cra-append-sw --mode dev --env ./.env.dev ./firebase-messaging-sw.js",
"prebuild": "cra-append-sw --mode build --env ./.env.prod ./firebase-messaging-sw.js",
...
I had real troubles with this one myself. The service worker gets involved in the stack way before your environment gets bootstrapped so it makes sense that it doesn't have access to your .Env variables.
My Solution
I built an npm module that on build, using webpack, extracts your "safe" versioning variables from your .env file and puts them into a stand-alone JS file. You can then go ahead and import this file and use it in your service worker.
https://www.npmjs.com/package/vue-enverywhere
Disclaimer:
I know this is for vue, but its webpack, and it's not vue specific. Also, You might be better to just copy the code, and not use the module. This was more of a fun exercise for myself :)
In index.js file (or wherever you want to register service worker) :
if ("serviceWorker" in navigator) {
console.log("Registration started");
const firebaseConfig = encodeURIComponent(
JSON.stringify({
apiKey: process.env.FCM_API_KEY,
projectId: process.env.FCM_PROJECT_ID,
messagingSenderId: process.env.FCM_SENDER_ID,
appId: process.env.FCM_APP_ID,
})
);
navigator.serviceWorker
.register(
`../../../firebase-messaging-sw.js?firebaseConfig=${firebaseConfig}`
)
.then(function (registration) {
console.log("Registration successful, scope is:", registration.scope);
})
.catch(function (err) {
console.log("Service worker registration failed, error:", err);
});
In Service Worker, firebase-messaging-sw.js :
importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js");
importScripts(
"https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"
);
firebase.initializeApp(
JSON.parse(new URL(location).searchParams.get("firebaseConfig"))
);
firebase.messaging();
This is enough for receiving Background Push Notifications on sending notification-type message.
this solution will work,
Just remember to edit the path to your Service-worer file (while registering in index.js or so), according to your project,
Or It will give "Mime Error".

The script resource is behind a redirect, which is disallowed. firebase cloud messaging

Hi from past one month our firebase app started giving this error.
"The script resource is behind a redirect, which is disallowed."
We've registered the firebase-messaging-sw.js at the root of the server , and it opens in the browser as well. The same code works great in localhost but gives this error on a public domain (cloudflare dNS)
https://prnt.sc/orot3j
Already tried solutions mentioned here : Firebase: change the location of the service worker
Our current code :
messaging = firebase.messaging();
$this.setState({messaging});
messaging.useServiceWorker(registration);
messaging.requestPermission().then(function() {
$this.setState({permission:true});
messaging.getToken().then(function(currentToken) {
$this.setState({fcmtoken:currentToken});
resolve(currentToken);
});
});
});
firebase-messaging-sw.js contents :
importScripts("https://www.gstatic.com/firebasejs/5.3.0/firebase-messaging.js");
var config = {
apiKey: "AIzxxxxxxxxxxxxxx0",
authDomain: "noxxxxions-7xxxd.firebaseapp.com",
databaseURL: "https://notifications-76xxxxd.firebaseio.com",
projectId: "nxxxxxxxxxxd",
storageBucket: "notifixxxxxx.appspot.com",
messagingSenderId: "90000000000"
};
firebase.initializeApp(config);
var messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
var notificationTitle = "Background Message Title";
var notificationOptions = {
body: "Background Message body.",
icon: "/firebase-logo.png"
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});```
Clicking on that link causes a redirection.
What if you try with the redirected url eg: https://prnt.sc/orot3j instead of http://prntscr.com/orot3j

Best way to separate test/prod environments for project React+Firebase [duplicate]

This question already has answers here:
Firebase configuration for multiple projects/environments
(3 answers)
Closed 3 years ago.
I've been doing a React+Firebase project without any CI/CD, and the manual effort has become unpleasant, so I'm looking to automate deployment to 2 environments, but not sure how to it with Firebase.
I have 2 environments - test and prod, each pointing to a separate Firebase project and database. Currently depending on where I deploy, I just alternate between config and configTest:
const configTest = {
apiKey: "XXX",
authDomain: "domaintest.firebaseapp.com",
databaseURL: "https://domaintest.firebaseio.com",
projectId: "domain-test",
storageBucket: "domaintest.appspot.com",
messagingSenderId: "000"
};
const config = {
apiKey: "YYY",
authDomain: "domain.firebaseapp.com",
databaseURL: "https://domain.firebaseio.com",
projectId: "domain",
storageBucket: "domain.appspot.com",
messagingSenderId: "111"
};
firebase.initializeApp(config);
//firebase.initializeApp(configTest);
I am assuming there should be a better way, but I couldn't find any instruction on the topic.
Usually you have the config object filled with environment variables accessed via process.env global variable.
const config = {
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
...
};
You can use modules like env-cmd or dotenv to load environment variables from .env file.

How to configure AngularFire for Multiple Firebase Projects

I am attempting to configure my AngularFire (2.3.0) - (This uses Angular 1.x) app to handle multiple firebase projects. Firebase has a reference in their docs for this possibility. Here is a snippet of how to initialize a single database.
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
Here is how you would add another database.
var secondaryAppConfig = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
};
// Initialize another app with a different config
var secondary = firebase.initializeApp(secondaryAppConfig, "secondary");
// Retrieve the database.
var secondaryDatabase = secondary.database();
Can AngularFire recognize and distinguish between multiple projects?
Yes angularFire can do it => tested with : "angular": "~1.5.3", "angularfire": "^2.0.1"
Secondary DB from another project (different auth !) :
constructor(Firebase, $firebaseArray){
'ngInject';
this.firebase = Firebase;
this.app = Firebase.initializeApp(secondaryConfig, 'secondary');
this.$firebaseArray = $firebaseArray;
}
getListDb1 () {
const refList = this.firebase.database().ref(`items`);
return this.$firebaseArray(refList);
}
getListDb2 () {
const refList = this.app.database().ref('items');
return this.$firebaseArray(refList);
}
I couldn't achieve to access 2 DBs from the same project with the same Auth in AngularFire but I have the solution for AF2 if someone needs it, just ask.

How to receive push notification in angularJs web Application with FCM.?

I want to show push notification on angular web app when Server sends a message via FCM.
What would be the best way to approach this, is there an Angular plugin for this (which I must admit I cannot find myself).
You should check the Firebase Cloud Messaging Quickstart example. Be careful to include the file firebase-messaging-sw.js in your /dist folder during deployment.
Following Firebase Javascript Web Setup which requires you to do the following all you will have left to do is expose the obejcts and perform the initialization in your appropriate angular artifacts.
Updated 1/28/2019: Make sure you add script tags to get firebase-messaging bundle <script src="https://www.gstatic.com/firebasejs/4.9.0/firebase-messaging.js"></script>
but if you have browserify etc you can following their article and samples fully.
The raw JavaScript is as below:-
<script src="https://www.gstatic.com/firebasejs/4.9.0/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
</script>
You could do this initialization in your config block - something like below. Remember firebase is a global object.
app.config(function() {
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
});
You can also create background message handler in some service or same config block according to firebase-messaging-sample Here is the gits of it:-
const messaging = firebase.messaging();
// [END initialize_firebase_in_sw]
**/
// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
// [START background_handler]
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/firebase-logo.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});

Resources