Table Of Contents
-
Introduction
- 1.1 Assumptions
- Installation
- Firebase Configuration and Application Environment
- Structure
- Base Service
- Summary
- Repository
- About Quasar
1. Introduction
Firebase is Google's mobile platform that helps you quickly develop high-quality apps and grow your business. It helps you by allowing you to build apps fast without managing infrastructure and gives you functionality like analytics, databases, messaging, and crash reporting so you can move quickly and focus on your users.
It was initially created as a startup in 2011 and was publicly available in 2012. In October 2014, Google acquired Firebase, which evolved into a platform that has 18+ products and is currently being used by 1.5 million apps as of October 2018. source - Wikipedia.
This article intends to be a base source for the articles that follows it, as the nature of this series is to inform the developer on how to set up Firebase within the Quasar Framework. While this information intends to be a foundational step for getting started with Firebase inside of Quasar, this is just the surface and is highly advisable to always consult the Firebase documentation initially for guidance.
Before we get started, a few assumptions are in order. Unless otherwise specified in the posts to follow in this series, a presumption of the Quasar project consists of using: Stylus, auto importing of components, and using the features of ESLint and Vuex.
Also, please be sure to keep your quasar-cli as current as possible.
$ npm i -g @quasar/cli@latest
Also, if you're here you've done two things:
- Chosen the Quasar Framework to be your Vuejs front-end component framework
- Chosen Firebase at the minimum to handle your Quasar application's authentication... maybe more
And finally, if something is not directly mentioned moving forward, it's more than likely to be covered in either the Quasar docs, or the Firebase docs. An effort will be made to keep a watchful eye on concepts that specifically pertain to the integration of Firebase within the Quasar Framework. Still, if something is missing, there is also the #firebase
channel on the Quasar Discord server. A final note, this code is for Vue v2 and Quasar v1.
2. Installation
If you're new to Firebase, you must create a Firebase account with a Google identity and create a project in the console.
- Perform steps 1 & 2 with the Firebase setup instructions.
Once you've gotten your account and project setup in Firebase, it's time to install dependencies in your Quasar app and start the configuration process.
Install Firebase to your Quasar application, preferably via yarn
package manager:
$ yarn add firebase
# or
$ npm install firebase
A configuration object is needed to configure the Firebase SDK for initialization from the Firebase console.
You can get access to your Firebase config object at any time by:
- Sign in to Firebase, then open your project.
- Click the Settings icon, then select Project settings.
- In the Your apps card, select the nickname of the app for which you need a config object.
- Select Config from the Firebase SDK snippet pane.
- Copy the config object snippet, then add it to your app's HTML.
or
- In your console run:
$ firebase apps:sdkconfig web
3. Firebase Configuration and Application Environment
Assuming you are developing an app that will live in a production environment, Firebase recommends creating separate projects in the Firebase console. One for production, one for dev, and even a public testing endpoint if you'd like. The point here is to keep production data safe from development.
The use of environment variables is used during Quasar's build process to identify which Firebase and other configuration information are needed given the desired build. Earlier in this article's history, the use of Qenv was used but has since become deprecated. Dotenv is now used to set up the application's environment variables.
yarn add -D dotenv
# or
npm install -D dotenv
Create a .env
file per the instructions on their repository. This file will house all environment options based on your application needs. Following dotenv's suggestion, do not split up your .env
files per environment. Here's what your .env
file could look like.
Note - For Windows Users - You'll need to install an additional package called cross-env, and update your package.json script.
{
"scripts": {
"dev:win": "cross-env QENV=DEV quasar dev"
}
}
# DEVELOPMENT FIREBASE CONFIG
DEV_API_KEY=######
DEV_AUTH_DOMAIN=######
DEV_DATA_BASE_URL=######
DEV_PROJECT_ID=######
DEV_STORAGE_BUCKET=######
DEV_MESSAGING_SENDER_ID=######
DEV_APP_ID=######
DEV_API_ENDPOINT=######
# STAGING FIREBASE CONFIG
STAGE_API_KEY=######
...
Take notice of the prefix, 'DEV', in the variable names. This will be used in our script to set our QENV
variable.
Create or update your build script in your package.json
file.
{
...
"scripts": {
"dev": "QENV=DEV quasar dev",
"lint": "eslint --ext .js,.vue src",
"test": "echo \"No test specified\" && exit 0"
},
...
}
Per the Quasar documentation, we need to add our parsed values from our .env
file. We also need to add our environment variables set during our build script to allow our config file to determine which config object to use.
const enviromentConfiguration = require('./src/utils/environmentConfig.js')
module.exports = function (ctx) {
return {
...
env: {
QENV: enviromentConfiguration(process.env.QENV)
}
...
Finally, create a utils
folder and create an enviromentConfig.js
file.
This file takes our environment variable set in our build script that gets passed over from our quasar.config.js
and uses it to determine which configuration will initialize the Firebase applications. Utilizing template string literals and aligning your environment variable names with the prefixes in your .env
file.
/src/utils/environmentConfig.js
const ENV = require('dotenv').config().parsed
/*
Use an environment variable set in package.json scripts to determine
the applications runtime environment. Add more switch cases as
need for additional environments. Remember, Firebase recomends supporting
separate Firebase project for different application environments: httpsq://firebase.google.com/docs/projects/multiprojects#support_different_environments
*/
module.exports = (QENV) => {
if (!['DEV', 'STAGE', 'PROD'].includes(QENV)) {
throw Error('Unknonw or not supplied environment variable')
}
return {
FIREBASE_CONFIG: {
apiKey: ENV[`${QENV}_API_KEY`],
authDomain: ENV[`${QENV}_AUTH_DOMAIN`],
databaseURL: ENV[`${QENV}_DATA_BASE_URL`],
projectId: ENV[`${QENV}_PROJECT_ID`],
storageBucket: ENV[`${QENV}_STORAGE_BUCKET`],
messagingSenderId: ENV[`${QENV}_MESSAGING_SENDER_ID`],
appId: ENV[`${QENV}_APP_ID`]
}
}
}
4. Structure
Before we dive into setting up the code, let's take a second to illustrate and discuss a bit of the opinionated direction we'll be taking. The fact that we can simply import Firebase and all its needed services into a single boot file, or just import the service directly in our Vue file and build our functionality as needed is definitely an option moving forward. But, the attempt here in these next few articles is to guide the development into more of a separated and maintainable production approach. We want to separate our services by a single namespace, firebaseServices, and also have each contextual service in a file. We can lend our structure to small and manageable files, as well as writing tests.
We'll revisit this again as we add more contexts to the application.
The following code snippet is meant to highlight the initial approach of setting up your application by separating your server connection and the actual service itself. The next bits are not intended to set up any real functionality, but highlight the first necessary pieces of the application structure. A typical Quasar app structure is here.
5. Base Service
The first place to get Firebase into Quasar is starting in a boot file. Create a boot file, then add its name to the boot
array in the quasar.conf.js
. Be sure to read up on Quasar’s boot files here. It is a great review, and also the first place to start when debugging Firebase issues.
$ quasar new boot firebaseConnection
/quasar.config.json
boot: [
'firebaseConnection'
],
Our boot file is not the Firebase service itself, but a point in which to bring in the Firebase service, in case you need or want to switch out your backend to another cloud provider or traditional backend API interface.
/src/boot/firebaseConnection.js
import firebaseServices from '../services/firebase'
export default async () => {
const app = firebaseServices.fBInit(process.env.QENV.FIREBASE_CONFIG)
// Validation that our service structure is working
// with an initialize Firebase application and auth instance.
console.log('Firebase App Instantiation:', app)
console.log('Firebase Auth Module:', firebaseServices.auth())
}
Calling the fBInit(process.env.QENV.FIREBASE_CONFIG)
method is just a validation that the service structure is working, but does not guarantee that the initialization happened with a valid API key.
Create a new directory in our application structure called services
, and put the base service inside.
/src/services/firebase/base.js
Throughout the next couple of articles, there will be a separation of each firebase service in relation to its context. These service file will be then be pulled into the /src/services/firebase/index.js
file where we can have a top-level firebaseServices
namespace via Object.assign()
.
Have a look here: /src/services/firebase
import firebase from 'firebase/app'
import 'firebase/auth'
/**
* Returns Firebase's auth service
* https://firebase.google.com/docs/reference/js/firebase.auth.html#callable
* @returns {Auth} - The Firebase Auth service interface
*/
export const auth = () => {
return firebase.auth()
}
/**
* Convenience method to initialize firebase app
* https://firebase.google.com/docs/reference/js/firebase?authuser=1#initializeapp
* @param {Object} config - FIREBASE_CONFIG during the build process
* @returns {App} - Creates and initializes a Firebase app instance.
*/
export const fBInit = (config) => {
return firebase.initializeApp(config)
}
First, we import our Firebase SDK and separate the imports per Firebase product. Be sure to check out the complete list of products, click on the expansion item for "Available Firebase JS SDKs (using bundler with modules)". Likewise, we could import the entire SDK, but you can shave off KB's by importing the products separately. Also, keep in mind if you only import just the app portion of the firebase and NOT the other products you'll end up getting undefined errors when trying to work with those products.
The fBInit
method allows Firebase to register a project that was created in the Firebase console.
Run the app:
$ yarn dev
Remember if you're running Windows
$ yarn dev:win
Once the app is finished building, it will launch to http://localhost:8080/#/
.
If you have successfully instantiated the Firebase service you will see this:
Otherwise, your application will fail to initialize and you will have a Quasar boot error and a Firebase error message stating you have an invalid key.
The Firebase API key doesn't get validated until an authentication method is executed. This will be highlighted in the Email Authentication article.
6. Summary
Here is the start of our integration between Firebase into the Quasar Framework and highlights getting a project created in the Firebase console, setting up the basic structure for our firebaseConnection
and our base
Firebase service files. This base service is ready for future application needs. It will serve as a starting point for any Firebase type of authentication or any of the other services that Firebase offers.
7. Repository
Quasar-Firebase Repo: Base Service
Up next: Email Authentication
8. About Quasar
Interested in Quasar? Here are some more tips and information:
More info: https://quasar.dev
GitHub: https://github.com/quasarframework/quasar
Newsletter: https://quasar.dev/newsletter
Getting Started: https://quasar.dev/start
Chat Server: https://chat.quasar.dev/
Forum: https://forum.quasar.dev/
Twitter: https://twitter.com/quasarframework
Donate: https://donate.quasar.dev
Top comments (15)
Hi! Thanks for the article! I'm always using this to start a new firebase quasar app. I see that you updated with dotenv instead of qenv. But I encountered problems with it or with the way the scripts are built. I reinstalled cross-env and used that in my script so now it "cross-env QENV=DEV quasar dev" again and it magically works. Hope you put back that part of the article again and hope this helps any newcomers that might be having the same problem
Thank you for pointing that out. I'll update the article and repo.
Thanks a lot!
Suggestion for env:
package.json
env-loader.js
quasar.conf.js
.env
process.env when staging
process.env when production
Hey Benjamin thanks for your read and suggestion. Just curious, was your suggestion to mainly remove the QENV namespace in the build env, or was there something more that you were highlighting?
Thank you for this.
Just a quick typo: the link to the Boot Files doc doesn't work, as of 2020-12-04. The correct link is: quasar.dev/quasar-cli/boot-files
My
quasar.env.json
file andpackage.json
scripts are exactly as yours are in your repo, but in myserverConnection.js
file this is what worked...const config = process.env.FIREBASE_CONFIG
From the QEnv docs you can set a "Common Root Object". This is what I did for my QEnve installation and is reflected in my code in the
serverConnection.js
file.QEvn docs: github.com/quasarframework/app-ext...
Ah. I see what happened. During the QEnv setup I defaulted to "none" when asked, "What name would you like to use for your Common Root Object." After going into my
quasar.extensions.json
file I was able to switch thecommon_root_object
value toenvironments
. Worked like a charm! Thank you for responding and pointing me to the root of the issue.Thank you for posting your question. I added a bit of guidance in that area of the article pointing out that piece of QEnv.
can this approach be used for firebase 9? Even with importing { initializeApp } and { getAuth } instead, I receive:
[Quasar] boot error: ReferenceError: process is not defined
at Array.WEBPACK_DEFAULT_EXPORT (firebaseConnection.js?4d99:4:1)
EDIT: well, I didn't know that we have to put the env object into the build config object in the quasar config. Just had it in 'return', but it has to be:
return {
...
build: {
...
env: {
QENV: enviromentConfiguration(process.env.QENV)
}
...
}
...
Hey , first of all thank you for posting this guide. It has been very informative. I've gone through it and implemented this login method on my app. Although i stumbled upon an issue that I am unable to resolve. As a matter of fact it is part of the guide, in the 4th section "Otherwise, your application will fail to initialize and you will have a Quasar boot error and a Firebase error message stating you have an invalid key." I've checked the API key a number of times and it does seem to be correct. I cannot figure what do you mean with this step of the guide "The Firebase API key doesn't get validated until an authentication method is executed. This will be highlighted in the Email Authentication article."
Thanks in advance
Ok i found my mistake , i'm gonna drop it here in case anyone else encounters it. I didn't read the QEnv documentation all the way through. Apparently in order to be able to run QENV on Windows you also have to run "npm install --save-dev cross-env" and modify package.json to "dev": "cross-env QENV=development quasar dev"
🔥🔥🔥
You lost me at qenv. Made multiple attempts to get past the 2nd step in the 1st tutorial and quit in frustration.
Jim are you familiar with what QEnv is doing and how it is handling the Firebase config object? Be sure to read the QEnv docs as this is a great Quasar application extension that offers the developer to handle our environment configurations during the build process. Feel free to jump into the Quasar discord in the #firebase channel for some clarification and help.