How to use firebase in front end as a module? - javascript

I am making a project in which I am using typescript and also using the module system(type="module"). I put the following inside my main.html file.
<script src="https://www.gstatic.com/firebasejs/7.6.1/firebase-app.js"></script>
I have another file firebase.ts which contains
// #ts-nocheck;
var firebaseConfig = {
apiKey: "AIzaSyAePVmVNzKbvbLnAGP1VVQwyEaE7pJ3a_M",
authDomain: "chess-3ea12.firebaseapp.com",
databaseURL: "https://chess-3ea12.firebaseio.com",
projectId: "chess-3ea12",
storageBucket: "chess-3ea12.appspot.com",
messagingSenderId: "454944098464",
appId: "1:454944098464:web:9d10fe0a1808233f5ca1c5"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default {
fs: firebase.database(),
db: firebase.database().ref(),
auth: firebase.auth()
}
Typescript will obviously show error
Cannot find name 'firebase'
How I can fix this means that I could get firebase a module so I could import it inside any file.

You can install Firebase as a dependency so that it appears in node_modules. You won't actually be using anything in it except for its definition file, though. With typeof import(...) syntax, you can import the type of a module, so import it and declare the Firebase type onto the window:
declare global {
interface Window {
firebase: typeof import('firebase');
}
}
Then, you'll be able to reference window.firebase and use its types:
const { firebase } = window;
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default {
fs: firebase.database(),
db: firebase.database().ref(),
auth: firebase.auth()
}

Related

expo constants not working on web anymore (empty manifest object)

i'm using firebase Auth in my expo app (Google Auth) and in order to do that, I need to set my firebase variables in a .env file (my API_KEYS, AuthDomain ...). I'm using expo constants to get those env variables and use them in my firebase.ts file, when implemented it worked on both mobile and web. Today I noticed that it's not working on web anymore because the constants.manifest object is empty and I don't understand why.
firebase.ts :
import { initializeApp } from "firebase/app";
import "firebase/auth";
import Constants from "expo-constants";
// Initialize Firebase
console.log("=======>", Constants);
const firebaseConfig = {
apiKey: Constants.manifest?.extra?.apiKey,
authDomain: Constants.manifest?.extra?.authDomain,
projectId: Constants.manifest?.extra?.projectId,
storageBucket: Constants.manifest?.extra?.storageBucket,
messagingSenderId: Constants.manifest?.extra?.messagingSenderId,
appId: Constants.manifest?.extra?.appId,
};
const Firebase = initializeApp(firebaseConfig);
export default Firebase;
app.config.js :
import "dotenv/config";
export default {
expo: {
entryPoint: "./src/App.tsx",
name: "Flooz",
slug: "flooz",
version: "1.0.0",
orientation: "portrait",
icon: "./src/assets/images/icon.png",
scheme: "flooz",
userInterfaceStyle: "automatic",
splash: {
image: "./src/assets/images/splash.png",
resizeMode: "contain",
backgroundColor: "#ffffff",
},
updates: {
fallbackToCacheTimeout: 0,
},
assetBundlePatterns: ["**/*"],
ios: {
supportsTablet: true,
},
android: {
adaptiveIcon: {
foregroundImage: "./src/assets/images/adaptive-icon.png",
backgroundColor: "#ffffff",
},
},
web: {
favicon: "./src/assets/images/favicon.png",
},
extra: {
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID,
},
},
};
Expo changed their manifest structure.
You can access your environment variables in Constants.expoConfig.extra (source)

Uncaught TypeError while importing from firebase/database

error that i'm getting:
Uncaught TypeError: Failed to resolve module specifier
"firebase/database". Relative references must start with either "/",
"./", or "../".
i am trying to setup firebase configuration for the latest version of firebase 9.1
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-app.js";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "....",
appId: "..."
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
//below import statement is causing the error
import { getDatabase, ref, set } from "firebase/database";
const db = getDatabase();
</script>
<script type="text/javascript" >
function InsertData() {
set(ref(db, 'TheStudent/'+rollV), {
NameOfStudent: "abc",
RollNo: 13,
Section: "B",
Gender: "Male"
});
}
document.getElementById('insertBtn').onclick = InsertData;
</script>
PS. i have hidden the config on purpose, so thats not the problem.
It seems you are using Firebase SDK over CDN so try importing database in same way:
import { getDatabase, ref, set } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-database.js";
// CDN URL instead of "firebase/database"

How to store Firebase credentials in Vue.js projects after building (env_var)

I have been trying to deploy my firebase&vue app.
However I couldn't add firebase credentials to the env variable.
Basically this is the structure on vue.js
config
---- key.js
---- keys_dev.js
---- keys_prod.js
key.js
if(process.env.NODE_ENV == 'production'){
module.exports = require('./keys_prod');
} else {
module.exports = require('./keys_dev');
}
keys_dev.js
module.exports = {
firebase: {
apiKey: "*********************************",
authDomain: "*****************************",
databaseURL: "****************************",
projectId: "******************************",
storageBucket: "**************************",
messagingSenderId: "**********************",
}
}
keys_prod.js
module.exports = {
firebase: {
apiKey: process.env['FIREBASE_apiKey'],
authDomain: process.env['FIREBASE_authDomain'],
databaseURL: process.env['FIREBASE_databaseURL'],
projectId: process.env['FIREBASE_projectId'],
storageBucket: process.env['FIREBASE_storageBucket'],
messagingSenderId: process.env['FIREBASE_messagingSenderId'],
}
}
Also I tried like this in keys_prod.js but I guess we can not use object in the env_var, so I changed it to the code above.
module.exports = {
firebase: process.env.FIREBASE_CONFIG
}
After npm run build, I created express app, define process.env's however when I run server, I am getting error because of env_vars are missing.
I tried to see logs on both front and backend console. I can see envs on node console but not in browser.
I also tried to deploy this app to heroku and firebase hosting. In both cases I added envs externally, but nothing change. (I guess there is no difference to use env_vars in localhost or remote server right ?)
Finally I tried to change keys.js (keys_prod > keys_dev)
if(process.env.NODE_ENV == 'production'){
module.exports = require('./keys_dev');
} else {
module.exports = require('./keys_dev');
}
then it works, but I can find the credentials in the source code this time.
There's a better way that the other answer. You don't need to import - that would bring the settings into the deployed JS, which isn't a good idea.
Create a file like .env.local in the root of the Vue app, like this:
$ cat .env.local
# REMEMBER:
# ----------------------------------------------------------
# In development, *restart* "yarn serve" to pick up changes.
# ----------------------------------------------------------
VUE_APP_FIREBASE_API_KEY='1234-F1xH53UCnk'
VUE_APP_FIREBASE_AUTH_DOMAIN='your-web-1234.firebaseapp.com'
VUE_APP_FIREBASE_DATABASE_URL='https://your-web-1234.firebaseio.com'
VUE_APP_FIREBASE_PROJECT_ID='your-web-1234'
VUE_APP_FIREBASE_STORAGE_BUCKET='your-web-1234.appspot.com'
VUE_APP_FIREBASE_MESSAGING_SENDER_ID='12345678'
VUE_APP_FIREBASE_APP_ID='1:1234:web:0398509235'
Wherever you want firebase, do something like:
function getFirebaseConfig() {
const firebaseConfig = {
// see .env file for instructions
apiKey: process.env.VUE_APP_FIREBASE_API_KEY || 'api-key-not-set',
authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN || 'env-not-set',
databaseURL: process.env.VUE_APP_FIREBASE_DATABASE_URL || 'env-not-set',
projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID || 'env-not-set',
storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET || 'env-not-set',
messagingSenderId: process.env.VUE_APP_FIREBASE_MESSAGING_SENDER_ID || 'env-not-set',
appId: process.env.VUE_APP_FIREBASE_APP_ID || 'env-not-set',
}
return firebaseConfig
}
// Initialize Firebase
firebase.initializeApp(getFirebaseConfig())
I'm using TypeScript, so I put that in a file called cloud-functions.ts` and after the above, I have:
export const postContactFunc = firebase.functions().httpsCallable('postContact')
Then, where I want to consume that function, I have:
// somewhere-else.ts
import {postContactFunc} from '#/services/cloud-functions'
Note that .env*.local is never checked in.
To remind myself what the file should be, I have this content in .env which is checked in:
$ cat .env
# REMEMBER:
# ----------------------------------------------------------
# DO NOT EDIT THIS FILE
#
# Edit .env.local or similar.
# ----------------------------------------------------------
# Get these from console - look on the _app_ area not the _project_ area.
VUE_APP_FIREBASE_API_KEY='not-set-yet'
VUE_APP_FIREBASE_AUTH_DOMAIN='not-set-yet'
VUE_APP_FIREBASE_DATABASE_URL='not-set-yet'
VUE_APP_FIREBASE_PROJECT_ID='not-set-yet'
VUE_APP_FIREBASE_STORAGE_BUCKET='not-set-yet'
VUE_APP_FIREBASE_MESSAGING_SENDER_ID='not-set-yet'
VUE_APP_FIREBASE_APP_ID='not-set-yet'
Here how you can do it.
Firstly, add dev.env to your project and add firebase variables.
FIREBASE_CONFIG: {
apiKey: "*********************************",
authDomain: "*****************************",
databaseURL: "****************************",
projectId: "******************************",
storageBucket: "**************************",
messagingSenderId: "**********************",
}
Import the file in dev.env.js
import merge from 'webpack-merge';
import env from './dev.env';
module.exports = merge(env, {
NODE_ENV: 'development'
}
Now, Initialize your firebase app with
import * as firebase from 'firebase';
firebase.initializeApp({VUE_APP_FIREBASE_CONFIG})
There you go! Firebase is set up for you
Hope this helps!

How to attach multiple js modules onto single firebase instance

I am refactoring some code so that different javascript modules in different js files can use the same Firebase instance. I also want to eliminate the possibility of race conditions as different modules are loaded.
I believe that these are the steps that I would need to follow in order to avoid a race condition:
Load firebase.js
Initialize firebase prototype with authentication
Execute external JS files module1.js and module2.js
In code this will roughly translate to the following:
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="crossorigin="anonymous"></script>
<script src="https://www.gstatic.com/firebasejs/3.6.1/firebase.js"></script>
<script type="text/javascript">
if (firebase.apps.length === 0) {
firebase.initializeApp({
apiKey: "<REMOVED>",
authDomain: "<REMOVED>",
databaseURL: "<REMOVED>",
storageBucket: "<REMOVED>",
messagingSenderId: "<REMOVED>"
});
}
firebase.auth().signOut().then(function () {
var customTokenUrl = "<REMOVED>";
$.ajax({
url: customTokenUrl,
data: {},
xhrFields: {withCredentials: true},
crossDomain: true,
success: function (token) {
firebase.auth().signInWithCustomToken(token);
},
type: 'POST'
});
});
</script>
<script src="someurl/module1.js"></script>
<script src="someurl/module2.js"></script>
This is roughly the code for both module1.js and module2.js:
var module1 = (function (MODULE) {
...
...
firebase.auth().onAuthStateChanged(MODULE.onAuthStateChanged.bind(MODULE));
function onAuthStateChanged(user) {
if (user) {
// User is signed in.
MODULE.uid = user.uid;
setWatchers(); // This is where I set the firebase refs
}
}
return MODULE;
}
Here are the questions I have:
In module1.js, is there a possibility that onAuthStateChanged won't fire? I think that, theoretically, module1.js can execute after the auth state changed in firebase. Wouldn't that make the onAuthStateChanged method not fire?
Can the var firebase ever be undefined in module1.js?

Cannot authenticate with emberfire

I am currently following this tutorial to authenticate my EmberApp with Firebase: Ember authentication with Firebase. I am working on the part which uses the Torii addon for authentication.
Here is what I have done so far:
app/torii-adapters/application.js
import Ember from 'ember';
import ToriiFirebaseAdapter from 'emberfire/torii-adapters/firebase';
export default ToriiFirebaseAdapter.extend({
firebase: Ember.inject.service()
});
app/adapters/application.js
import config from '../../config/environment';
import FirebaseAdapter from 'emberfire/adapters/firebase';
import Firebase from 'firebase';
export default FirebaseAdapter.extend({
firebase: new Firebase(config.firebase)
});
config/environment.js
module.exports = function(environment) {
var ENV = {
modulePrefix: 'my-auth-test',
environment: environment,
baseURL: '/',
locationType: 'auto',
firebase: 'MY_FIREBASE_URL',
torii: {
sessionServiceName: 'session'
},
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
...
routes/application.js -> Login function
login: function() {
var controller = this.get('controller');
var email = controller.get('userEmail');
var password = controller.get('userPassword');
this.get('session').open('firebase', {
provider: 'password',
email: email,
password: password
}).then(function() {
this.transitionTo('protected');
}.bind(this));
}
The problem that I have is the following error:
Please set the firebase property in your environment config.
But as far as I can see I have the property set. Can someone help me fix this issue?
That's the old method. Recently I ran into a similar issue after copy/pasting my old implementation, but after a quick look at https://github.com/firebase/emberfire I updated my config/environment.js to the following and was able to get it to work.
Try:
// config/environment.js
var ENV = {
firebase: {
apiKey: 'xyz',
authDomain: 'YOUR-FIREBASE-APP.firebaseapp.com',
databaseURL: 'https://YOUR-FIREBASE-APP.firebaseio.com',
storageBucket: 'YOUR-FIREBASE-APP.appspot.com',
}

Categories