FirebaseError: "projectId" not provided in firebase.initializeApp (NextJS) - firebase

I'm building a web app with NextJS, NextAuth and Firebase/Firestore, and I'm getting an error:
error - [FirebaseError: "projectId" not provided in firebase.initializeApp.] {
code: 'invalid-argument',
customData: undefined,
toString: [Function (anonymous)]
This is my JS file:
import NextAuth from "next-auth/next";
import TwitterProvider from "next-auth/providers/twitter";
import { FirestoreAdapter } from "#next-auth/firebase-adapter";
import { initializeApp, getApp, getApps } from "firebase/app";
import "firebase/auth";
import { getFirestore, collection, addDoc, getDocs } from "firebase/firestore";
// import { getAnalytics } from "firebase/analytics";
// import { getStorage } from "firebase/storage";
import nextConfig from "next.config";
const firebaseConfig = {
apiKey: nextConfig.env.FIREBASE_API_KEY,
authDomain: nextConfig.env.FIREBASE_AUTH_DOMAIN,
projectId: nextConfig.env.FIREBASE_PROJECT_ID,
storageBucket: nextConfig.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: nextConfig.env.FIREBASE_MESSAGING_SENDER_ID,
appId: nextConfig.env.FIREBASE_APP_ID,
measurementId: nextConfig.env.FIREBASE_MEASUREMENT_ID,
};
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();
//const analytics = getAnalytics(app);
const db = getFirestore(app);
//const storage = getStorage(app);
const dbInstance = collection(db, "bugs");
const getBugs = () => {
getDocs(dbInstance).then((data) => {
console.log(data);
});
};
export default NextAuth({
providers: [
TwitterProvider({
clientId: nextConfig.env.TWITTER_CLIENT_ID,
clientSecret: nextConfig.env.TWITTER_CLIENT_SECRET,
version: "2.0", // opt-in to Twitter OAuth 2.0
}),
],
adapter: FirestoreAdapter(db),
});
I can't find any solution on the internet.
Any idea?

In Nextjs, environment variables are only available in the Node.js environment by default, meaning they won't be exposed to the browser.
In order to expose a variable to the browser you have to prefix the variable with NEXT_PUBLIC_
Change your firebase config as shown below and also change the firebase env variables in the .env file to use NEXT_PUBLIC_ prefix.
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId:process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

Related

FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created (on NextJS)

While trying to integrate Firebase auth with my project, I encountered this error:
FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
at app (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/node_modules/#firebase/app/dist/index.node.cjs.js:356:33)
at Object.serviceNamespace [as auth] (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/node_modules/#firebase/app/dist/index.node.cjs.js:406:51)
at eval (webpack-internal:///./lib/firebase.js:28:66)
at Object../lib/firebase.js (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/pages/enter.js:22:1)
at __webpack_require__ (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///./pages/enter.js:7:71)
at Object../pages/enter.js (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/pages/enter.js:33:1)
at __webpack_require__ (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/webpack-runtime.js:33:42)
at __webpack_exec__ (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/pages/enter.js:87:52)
at /Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/pages/enter.js:88:28
at Object.<anonymous> (/Volumes/MacOS/Projects/Projects/3. PriceTag/pricetag/.next/server/pages/enter.js:91:3)
at Module._compile (internal/modules/cjs/loader.js:1133:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
at Module.load (internal/modules/cjs/loader.js:977:32)
at Function.Module._load (internal/modules/cjs/loader.js:877:14)
at Module.require (internal/modules/cjs/loader.js:1019:19) {
code: 'app/no-app',
customData: { appName: '[DEFAULT]' }
I get this error whenever I request localhost:3000/enter
Here's the Javascript code:
firebase.js
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
var firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID
};
if (!firebase.app.length) {
firebase.initializeApp(firebaseConfig)
}
export const auth = firebase.auth()
export const googleAuthProvider = new firebase.auth.GoogleAuthProvider()
enter.js
import { auth, googleAuthProvider } from '../lib/firebase'
export default function SignInPage() {
return (
<>
<SignInButton />
</>
)
}
// Google Sign In Component
const SignInButton = () => {
const signInWithGoogle = async () => {
await auth.signInWithPopup(googleAuthProvider)
}
return (
<button onClick={signInWithGoogle}>Sign in with Google</button>
)
}
// Sign Out Button component
export const SignOutButton = () => {
return (
<button onClick={() => auth.signOut}>Sign in with Google</button>
)
}
I can't seem to figure out what's causing the error. I did initialise a firebase app, so I'm not sure what's happening here.
With NextJs automatic code splitting, you never know what it is cutting out. I think NextJs is looking at your firebase.js and just including what you used:
import firebase from 'firebase/app'
export const auth = firebase.auth()
export const googleAuthProvider = new firebase.auth.GoogleAuthProvider()
I would just check if firebase is setup every time you use it.
Firebase Web V9
import { getApp as _getApp, getApps, initializeApp } from "firebase/app";
import { getAuth as _getAuth } from "firebase/auth";
import { enableIndexedDbPersistence, getFirestore as _getFirestore } from "firebase/firestore";
const config = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
};
const firebaseIsRunning = () => !!(getApps().length);
export function getApp() {
if (!firebaseIsRunning()) initializeApp(config);
return _getApp();
}
export function getFirestore() {
const isRunning = firebaseIsRunning();
if (!isRunning) getApp();
const db = _getFirestore();
if (!isRunning)
if (typeof window !== undefined) enableIndexedDbPersistence(db)
return db;
}
export function getAuth() {
if (!firebaseIsRunning()) getApp();
return _getAuth();
}
for anybody that is using firebase V9. This is what you need to do.
import { initializeApp } from 'firebase/app';
import { getFirestore } from "firebase/firestore";
const clientCredentials = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
const app = initializeApp(firebaseConfig);
const firestore = getFirestore();
export { firestore }
and you should be fine

Vuejs Router and Firebase

I have recently decided to learn Vuejs but I couldn't figure it out if there's a way to load collections once instead of on every component.
This is what I am doing on every component before export default
The main file is where I first loaded the firebase, because of the authentication.
import firebase from '../main';
import fb from 'firebase'
let db= ''
if(firebase){
db = firebase.firestore();
}
else{
var config = {
apiKey: process.env.VUE_APP_APIKEY,
authDomain: process.env.VUE_APP_AUTHDOMAIN,
projectId: process.env.VUE_APP_PROJECTID,
storageBucket:process.env.VUE_APP_STORAGEBUCKET,
messagingSenderId: process.env.VUE_APP_MESSAGINGSENDERID,
appId: process.env.VUE_APP_APPID,
measurementId: process.env.VUE_APP_MEASUREMENTID
};
let aux_fb = !fb.apps.length ? fb.initializeApp(config) : fb.app();
db = aux_fb.firestore()
}
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router';
import fb from "firebase" ;
var config = {
apiKey: process.env.VUE_APP_APIKEY,
authDomain: process.env.VUE_APP_AUTHDOMAIN,
projectId: process.env.VUE_APP_PROJECTID,
storageBucket:process.env.VUE_APP_STORAGEBUCKET,
messagingSenderId: process.env.VUE_APP_MESSAGINGSENDERID,
appId: process.env.VUE_APP_APPID,
measurementId: process.env.VUE_APP_MEASUREMENTID
}
const firebase = !fb.apps.length ? fb.initializeApp(config) : fb.app();
export default firebase;
Vue.config.productionTip = false
let app = '';
firebase.auth().onAuthStateChanged(() => {
if (!app) {
app = new Vue({
router,
render: h => h(App)
}).$mount('#app');
}
});
Also, is it safe to use a .env ?

Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app)

For my Nuxt/Vue.js app I need to export various Firestore-related elements as opposed to just firebase.firestore().
However I'm getting some Firebase App named '[DEFAULT]' already exists (app/duplicate-app) error for the default export and I don't understand why:
import firebase from 'firebase/app'
import 'firebase/firestore'
const config = {
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '...'
}
const firebaseApp = firebase.initializeApp(config)
firebase.firestore().settings({ experimentalForceLongPolling: false })
const db = firebase.firestore()
const fb = firebase
export { db, fb }
export default firebaseApp
There is no duplicate that I can identify in this export default line, so what's wrong?
The way I handle it is I have a firedb file that I import as needed (throughout the App or just in Vuex). Because the file keeps getting referenced, the config keeps re-loading, which causes the same error.
The way I've dealt with it to add this line after the config definition
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
I've got an example in condesandbox at https://codesandbox.io/s/vuex-ws-2-60fzg
With your code it would be a little more difficult, since you're exporting the
firebaseAppconst. But this may work for you (not tested)
import firebase from 'firebase/app'
import 'firebase/firestore'
const config = {
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '...'
}
const firebaseApp = firebase.apps && firebase.apps.length > 0 ? firebase.apps[0] : firebase.initializeApp(config)
firebase.firestore().settings({ experimentalForceLongPolling: false })
const db = firebase.firestore()
const fb = firebase
export { db, fb }
export default firebaseApp
You can check firebase.apps to see if its loaded. If your only loading it once, then you can just check the length. If you have multiple then you could check each apps name.
// Config file
import * as firebase from "firebase";
const config = {...};
export default !firebase.apps.length ? firebase.initializeApp(config) : firebase.app();
// Other file
import firebase from '../firebase';
...
console.log(firebase.name);
console.log(firebase.database());
If you use firestore, use :
export default !firebase.apps.length
? firebase.initializeApp(config).firestore()
: firebase.app().firestore();
You dont need to export the firebaseApp, this should be good enough
import firebase from 'firebase/app'
import 'firebase/firestore'
const config = {
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '...'
}
if (!firebase.apps.length) {
firebase.initializeApp(config)
}
firebase.firestore.settings({ experimentalForceLongPolling: false })
const db = firebase.firestore()
export { db }
export default firebase
This should avoid calling the instantiation more than once
import firebase from 'firebase/app'
import 'firebase/firestore'
const config = {
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '...'
}
if (!firebase.apps.length) {
firebase.initializeApp(config)
}
//by commenting this i got my result
// firebase.firestore.settings({ experimentalForceLongPolling: false })
const db = firebase.firestore()
export { db }
export default firebase
this worked for me
const app = !firebase.apps.length ? firebase.initializeApp(info) : firebase.app();
export const auth = app.auth()
export default app;
this my solution in my case reactjs
if(!firebase.apps.length){
firebase.initializeApp(config);
}else{
firebase.app();
}

How to fix "Cannot read property 'firestore' of null" in Firestore

I will try to change the setting in the function of firestore() but doesn't work.
I read the document and they said that this future will be removed in a future release but I don't seen the solve. So I hope anyone can help me settle this problem
Operating System version: Majove 10.14.2
Library version: ^6.1.0
Firebase Product: firestore
import * as firebase from 'firebase/app'
import 'firebase/firestore'
require('dotenv').config({ encoding: 'utf8' })
const firebaseConfig = {
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
databaseURL: process.env.DATABASE_URL,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID
}
// Initialize Firebase
let firebaseApp = null
if (!firebase.app.length) {
firebaseApp = firebase.initializeApp(firebaseConfig)
}
firebaseApp.firestore().settings({
ssl: false,
timestampsInSnapshots: true
})
export default firebaseApp.firestore()
See https://firebase.google.com/docs/web/setup .
Basic way to initialize firebase is this.
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import "firebase/functions";
import "firebase/storage";
import "firebase/messaging";
import "firebase/performance";
const config = {
// set your config here
};
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
const auth = firebase.auth();
const storage = firebase.storage();
const functions = firebase.functions();
const firestore = firebase.firestore();
let messaging = null;
try {
if (firebase.messaging.isSupported()) {
messaging = firebase.messaging();
messaging.usePublicVapidKey("your publicVapidKey here");
}
} catch (e) {}
const perf = firebase.performance();
export { firebase, auth, storage, functions, firestore, messaging };
I edited your code.
import firebase from 'firebase/app'
import 'firebase/firestore'
require('dotenv').config({ encoding: 'utf8' })
const firebaseConfig = {
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
databaseURL: process.env.DATABASE_URL,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID
}
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig)
}
const firestore = firebase.firestore();
firestore.settings({
ssl: false,
timestampsInSnapshots: true
})
export default firestore;

FCM setup for push notification in angular 6 web app

I am trying to integrate fcm in my angular 6.
Here is what i have done.
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': '93480234033'
});
const messaging = firebase.messaging();
push-notification.js
import firebase from 'firebase';
export const askForPermissioToReceiveNotifications = async () => {
try {
const messaging = firebase.messaging();
console.log('000ooppp', messaging)
messaging.requestPermission()
.then(function(){
console.log('I am in here');
return messaging.getToken()
.then(function(currentToken) {
console.log(currentToken);
})
}).catch(function(err) {
console.log('Unable to get permission to notify.', err);
});
} catch (error) {
console.error(error);
}
}
these two files are in src folder.
i have created an app on firebase console and i have got the config object
config: {
apiKey: "*****",
authDomain: "*****",
databaseURL: "*****",
projectId: "*****",
storageBucket: "*****",
messagingSenderId: "*****"
}
And in my app.module.ts file i am initialising firebase with the above object
import { AngularFireModule } from 'angularfire2';
import { ServiceWorkerModule } from '#angular/service-worker';
and then in import
imports: [
...
...
AngularFireModule.initializeApp(environment.firebase),
ServiceWorkerModule.register('/combined-worker.js', { enabled: environment.production })
...
...
]
and in app.component.ts
import { askForPermissioToReceiveNotifications } from './../push-notification';
ngOnInit () {
console.log('pop')
askForPermissioToReceiveNotifications();
}
what i want to do is when user lands on the page and he allows notification to be shown to him, a unique device token id should be generated for that particular user, how can i generate device token id when he clicks on show notification?
getting this error in console
Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app)
src/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: ""
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
now in app.module.ts
import {BrowserModule} from '#angular/platform-browser';
import {NgModule} from '#angular/core';
import {AppComponent} from './app.component';
import { AngularFireModule } from 'angularfire2';
import { AngularFireMessagingModule } from 'angularfire2/messaging';
const config = {
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: ''
};
#NgModule({
declarations: [
AppComponent
],
imports: [
AngularFireModule.initializeApp(config),
AngularFireMessagingModule
],
bootstrap: [AppComponent]
})
export class AppModule {
}
inside your component that yout want to require permission to send notification:
import {Component, OnInit} from '#angular/core';
import { AngularFireMessaging } from 'angularfire2/messaging';
import { mergeMapTo } from 'rxjs/operators';
export class HomeComponent implements OnInit {
constructor(private _messaging: AngularFireMessaging) {
}
ngOnInit() {
/* request permission */
this._messaging.requestPermission
.pipe(mergeMapTo(this._messaging.tokenChanges))
.subscribe(token => {
console.log(token);
}, err => console.log(err));
/* listen for messages */
this._messaging.messages.subscribe((message: {notification}) => {
console.log(message.notification.title);
console.log(message.notification.body);
});
}
}
Remember that there 2 ways receiving push notifications
1) when the app is open:
you'll have to handle it showing the message
2) when the app is closed:
the browser handle it for you
Hello #wazz try setting your firebase config in your app.module.ts and import firebase
import * as firebase from 'firebase';
...
firebase.initializeApp(firebase_config);

Resources