To the Stars with Quasar & Firebase - Initial Service & Structure
Tags: vue, quasar, firebase
Published: 2020-02-06 18:59:17

## Table Of Contents
1. [Introduction](#intro)
 - 1.1 [Assumptions](#assumptions)
2. [Installation](#install)
3. [Firebase Configuration and Application Environment](#env)
4. [Structure](#structure)
5. [Base Service](#baseService)
6. [Summary](#summary)
7. [Repository](#repo)
8. [About Quasar](#aboutQuasar)

### 1. Introduction <a name="intro"></a>

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](https://en.wikipedia.org/wiki/Firebase)*.

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](https://firebase.google.com/docs/web/setup) with Firebase inside of Quasar, this is just the surface and is highly advisable to always consult the Firebase documentation initially for guidance.

 - 1.1 Assumptions <a name="assumptions"></a>

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. 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/c87j1y0jg2fgf848v2rg.png)

Also, please be sure to keep your quasar-cli as current as possible.

```bash
$ 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](https://quasar.dev/start/pick-quasar-flavour), or the [Firebase docs](https://firebase.google.com/). 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](https://discordapp.com/invite/5TDhbDg). *A final note, this code is for Vue v2 and Quasar v1.*

### 2. Installation <a name="install"></a>

If you're new to Firebase, you must create a Firebase account with a Google identity and create a project in the console.
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/u3av547f0zlrafg5arvs.jpg)

- Perform **steps 1 & 2** with the Firebase setup [instructions](https://firebase.google.com/docs/web/setup).

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:

```bash
$ 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 <q-icon name="settings" /> 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 <a name="env"></a>

Assuming you are developing an app that will live in a production environment, [Firebase recommends creating separate projects](https://firebase.google.com/docs/projects/multiprojects) 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](https://github.com/motdotla/dotenv#readme) is now used to set up the application's environment variables.


```bash
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](https://github.com/motdotla/dotenv#readme), 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](https://www.npmjs.com/package/cross-env), and update your package.json script.*
```json
{
 
  "scripts": {
    "dev:win": "cross-env QENV=DEV quasar dev"
  }
  
}
```


[**/.env**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/.env)
```
# 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.

[**/package.json**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/package.json)

```json
{
  ...
  "scripts": {
    "dev": "QENV=DEV quasar dev",
    "lint": "eslint --ext .js,.vue src",
    "test": "echo \"No test specified\" && exit 0"
   },
  ...
}
```

Per the [Quasar documentation](https://quasar.dev/quasar-cli/quasar-conf-js#using-dotenv), 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.

[**/quasar.conf.js**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/quasar.conf.js)
```js
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**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/src/utils/environmentConfig.js)
```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 <a name="structure"></a>
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.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jj8zrjtht39rt7onanec.png)

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](https://quasar.dev/quasar-cli/cli-documentation/directory-structure). 

### 5. Base Service <a name="baseService"></a>

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](https://quasar.dev/quasar-cli/cli-documentation/boot-files). It is a great review, and also the first place to start when debugging Firebase issues.

```bash
$ quasar new boot firebaseConnection
```
**/quasar.config.json**
```js
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**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/src/boot/firebaseConnection.js)
```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**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/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**](https://github.com/quasarframework/firebase-sample-apps/blob/master/base/src/services/firebase)

```js
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](https://firebase.google.com/docs/web/setup#libraries-bundle), 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:
```bash
$ yarn dev
```

*Remember if you're running Windows*
```bash
$ 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:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68xnnkixvnmxfqxr1rux.png)

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.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/js7xnjln5a1n08tcf44n.png)

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 <a name="summary"></a>

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 <a name="repo"></a>
[Quasar-Firebase Repo: Base Service](https://github.com/quasarframework/firebase-sample-apps/tree/master/base)

Up next: [Email Authentication](https://dev.to/quasar/to-the-stars-with-quasar-firebase-email-authentication-37dh)

### 8. About Quasar <a name="aboutQuasar"></a>
Interested in Quasar? Here are some more tips and information:

More info: [https://quasar.dev](https://quasar.dev)
GitHub: [https://github.com/quasarframework/quasar](https://github.com/quasarframework/quasar)
Newsletter: [https://quasar.dev/newsletter](https://quasar.dev/newsletter)
Getting Started: [https://quasar.dev/start](https://quasar.dev/start)
Chat Server: [https://chat.quasar.dev/](https://chat.quasar.dev/)
Forum: [https://forum.quasar.dev/](https://forum.quasar.dev/)
Twitter: [https://twitter.com/quasarframework](https://twitter.com/quasarframework)
Donate: [https://donate.quasar.dev](https://donate.quasar.dev)