Firebase Functions Express Typescript Project Guide Part 1
Tags: webdev, express, typescript, firebase
Published: 2024-05-14 01:16:20

This guide will walk you through setting up your Mac for development with Node.js, Firebase, and Firestore, including creating a simple Express app within a Firebase Functions project.

### Prerequisites

- Basic command line knowledge
- Mac computer with admin access
- Mac with **[XCode](https://forums.developer.apple.com/forums/thread/677124)** installed
- Postman Installed
- Create a Firebase Project before hand

## Setup

### 0. Create a Firebase Project

- Login into your google account
- Go to the [Firebase Console](https://console.firebase.google.com/)
- Create a new project and name it however you like, we’ll use the name `my-project` for this example.
- Don’t set Google Analytics, not necessary
- After your Project is ready, you’ll be redirected to the project overview page
- On the left Sidenav, click the settings icon, select Project settings
- Look for your Project ID
- Now go to the [Firestore page here](https://console.firebase.google.com)
- Select the default location
- Select **Start in test mode**
- After the DB has been created,  you’ll see an empty Database 😬
- That’s all we need to know now, well come back to the console later

### 1. [Install Homebrew](https://brew.sh/) and Java

- [Homebrew](https://brew.sh/) is a package manager for macOS. It simplifies the installation of software on macOS.
- After installation, verify it by running:
    
    ```tsx
    brew --version
    ```
    
- Tu use the Firebase Emulators, we need to install the **Java JDK**, you can do it with [homebrew](https://formulae.brew.sh/formula/openjdk), although there are other methods.

### 2. [Install Node.js 18 Using nvm](https://medium.com/@priscillashamin/how-to-install-and-configure-nvm-on-mac-os-43e3366c75a6)

- [Install Guide](https://medium.com/@priscillashamin/how-to-install-and-configure-nvm-on-mac-os-43e3366c75a6)
- Note: the example is for Node 16 although you should install Node 18 `nvm`, although with `nvm` you can have multiple node versions and choose between them 😉
- `nvm` allows you to manage multiple installations of Node.js.
- After installing `nvm` and Node 18 , verify installation by running:
    
    ```tsx
    node --version
    ```
    

### 3. Make sure `npm` is installed

- Verify by running:
    
    ```tsx
    npm --version
    ```
    

### 4. Install Firebase CLI

- The firebase CLI is…
- Install it **globally** by runnning:
    
    ```tsx
    npm install -g firebase-tools
    
    ```
    
- Verify the installation:
    
    ```bash
    firebase --version
    ```
    

### 5. Create a New Firebase Functions TypeScript Project

- To use Firebase products like Functions, Firestore, Auth, and others, we need to create a new Firebase project.
- Note: this project is different from your Firebase Console Project where we will deploy this Typescript project. To be clear: one is the code project and the other, a container in Firebase Console to deploy our code project.
- Initialize your project:
    
    ```bash
    # In a terminal, change to your existing Develop directory:
    cd my-dev-directory
    # Create a new directory to store the project
    mkdir my-firebase-project
    # Move into the new directory
    cd my-firebase-project
    # Login into Firebase
    firebase login
    
    ```
    
- That command will prompt a URL or open your browser so you can login with your google account.
- After successful login, Initialize the Firebase project
    
    ```tsx
    # Initialize Firebase
    firebase init
    ```
    
- This will prompt different **Firebase** **features** to start the project, read the instructions thoroughly and then choose these options:
    - Select to use **Firestore**
    - Select to use **Functions**
    - Select to use **Emulators**
    - Leave all others features disabled
    - When prompted to select a project, choose the one you first created from the list
    - When prompted, select all defaults for the **Firestore Setup**
    - For the **Functions Setup**
    - Select TypeScript when prompted
    - Choose to use ESLint when prompted
    - Choose to install dependencies with npm, this will run `npm install` in the project and create the `node_modules` directory
    - For the **Emulators Setup** choose the **Functions** and **Firestore** emulators
    - Leave all defaults for the next options
    - Choose to download the emulators now ( this is what you need the **Java SDK** for)
    - Verify your project directory running:
        
        ```bash
        ls -la
        # The output should look like this
        total 40
        drwxr-xr-x   8   staff   256 May 13 15:33 .
        drwxr-xr-x   7   staff   224 May 13 15:07 ..
        -rw-r--r--   1   staff    68 May 13 15:33 .firebaserc
        -rw-r--r--   1   staff  1166 May 13 15:33 .gitignore
        -rw-r--r--   1   staff   650 May 13 15:33 firebase.json
        -rw-r--r--   1   staff    44 May 13 15:31 firestore.indexes.json
        -rw-r--r--   1   staff   755 May 13 15:30 firestore.rules
        drwxr-xr-x  10   staff   320 May 13 15:32 functions
        
        ```
        
    - Now you have installed a new Firebase Functions Project!

## Installing Project Dependencies

- Open the project in your Code Editor
- The directory structure should look like this:
    
    ```markdown
    # Project Structure Overview
    
    - `functions-express-ts-project-guide`
      - `functions`
        - `node_modules`
        - `src`
          - `index.ts`
          - `.eslintrc.js`
          - `.gitignore`
          - `package.json`
          - `package-lock.json`
          - `tsconfig.dev.json`
          - `tsconfig.json`
        - `.firebaserc`
        - `.gitignore`
        - `firebase.json`
        - `firestore.indexes.json`
        - `firestore.rules`
    
    ### functions
    This directory contains all the source code and configuration for Firebase Functions.
    
    #### node_modules
    - **Purpose:** Contains all the npm packages that are installed as dependencies for the project. Managed by npm.
    
    #### src
    This directory holds the TypeScript source files for the Firebase Functions.
    
    ##### index.ts
    - **Purpose:** The main entry point for Firebase Functions, contains the TypeScript code for defining cloud functions.
    
    ##### .eslintrc.js
    - **Purpose:** Configuration file for ESLint, a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code, aiming to make code more consistent and avoiding bugs.
    
    ##### .gitignore
    - **Purpose:** Specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected.
    
    ##### package.json
    - **Purpose:** Defines npm package dependencies for the project, as well as build scripts and project metadata.
    
    ##### package-lock.json
    - **Purpose:** Automatically generated file which specifies the exact versions of all npm dependencies that were installed for the project. Ensures a consistent environment for all installations of the dependencies.
    
    ##### tsconfig.dev.json
    - **Purpose:** The TypeScript compiler configuration file for development environments, may differ slightly in settings from production to enable better debugging or more verbose logging.
    
    ##### tsconfig.json
    - **Purpose:** The TypeScript compiler configuration file for the project. Defines options required to compile the project.
    
    #### .firebaserc
    - **Purpose:** Firebase CLI runtime configuration file. Stores aliases and project specific settings used by Firebase.
    
    #### .gitignore (in functions directory)
    - **Purpose:** Similar to the src .gitignore, but for the entire functions directory.
    
    #### firebase.json
    - **Purpose:** Firebase configuration file which defines rules and settings for your Firebase project, like hosting behavior and cloud functions paths.
    
    #### firestore.indexes.json
    - **Purpose:** Configuration file for defining indexes in Firestore. Helps improve query performance.
    
    #### firestore.rules
    - **Purpose:** Security rules file for Firestore. Defines what data can be accessed by whom, securing your Firestore data based on authentication and authorization.
    
    ```
    
- Open the `index.ts` file
- You should see an auto generated code, let’s remove all the code for now
- This will be our entry file and we need to create a new Express application

### 1. Install Express

- Let’s firs install express by running:
    
    ```bash
    # Important: First, move into the functions directory, this is where the package.json file lives.
    # We will run all our commands from this directory.
    cd functions
    # Install Express
    npm install express
    # You should see express on your package.json file dependencies
    ```
    
- If you take a look at the `package.json` there’s auto generated content by the Firebase CLI, there are already some scripts, dependencies, and all we need to start developing

### 2. Do some code

- Add the following to the `index.ts` file and read it carefull:
    
    ```tsx
// For our API we will use the Functions 2nd Gen HTTP Request trigger
// See this: https://firebase.google.com/docs/functions/http-events?gen=2nd
// Import onRequest from firebase-functions for HTTP triggers.
import {onRequest} from "firebase-functions/v2/https";

    // Import the entire Express module. This allows us to use its
    // functionalities to create and manage the server.
    import * as express from "express";
    
    // Import the Request and Response types from the 'express' module.
    // These types are used to type the request and response objects in
    // route handlers, providing type checking and IntelliSense features in the IDE.
    import {Request, Response} from "express";
    
    // Create a new Express application by calling `express()`.
    // This `app` object encapsulates all the functionalities of an
    // Express application.
    // It's used to configure routes, middleware, and to start the server.
    const app = express();
    
    // Define a route handler for HTTP GET requests to the root URL ("/").
    // This sets up the server to respond to GET requests at the
    // specified path. Here, the path is the root URL.
    // eslint-disable max-len
    // `req` (request) and `res` (response) are parameters typed with
    // `Request` and `Response` to enhance type safety and tooling support.
    // The handler function sends the text "Hello World!" back to the
    // client when the root URL is accessed.
    app.get("/", (req: Request, res: Response) => res.send("Hello World!"));
    
    // Export the `app` instance as `api`. This exported `api` can be used
// elsewhere, particularly in Firebase Functions, to handle
// HTTP requests. This allows the `api` to act as a
// serverless function in the Firebase ecosystem.
exports.api = onRequest(app);
    
    ```
- **Now build the project to update the emulators server with npm run build this will create a lib directory which will be the one to actually deploy to the Cloud Functions.**

### 3. Start the Emulators

- Now, go back the `package.json` file.
- See the command `serve` , run it with `npm run serve`
- You’ll see something like this:
    
    ```bash
    ✔  functions: Loaded functions definitions from source: api.
    # Important: this is the URL you will use to call the API
    ✔  functions[us-central1-api]: http function initialized (http://127.0.0.1:5001/my-project/us-central1/api).
    
    ┌─────────────────────────────────────────────────────────────┐
    │ ✔  All emulators ready! It is now safe to connect your app. │
    │ i  View Emulator UI at http://127.0.0.1:4000/               │
    └─────────────────────────────────────────────────────────────┘
    
    ┌───────────┬────────────────┬─────────────────────────────────┐
    │ Emulator  │ Host:Port      │ View in Emulator UI             │
    ├───────────┼────────────────┼─────────────────────────────────┤
    │ Functions │ 127.0.0.1:5001 │ http://127.0.0.1:4000/functions │
    
    ```
    
- Go to http://localhost:4000/ and you should see the Emulators interface, although only the **Functions** emulator is running for now in the URL: `http://127.0.0.1:5001/my-project/us-central1/api`
- Open Postman
- Create a new Request and do a GET to the URL
- The Response should be `"Hello World!"`

That's it! you have now created a Hello World with Firebase Functions, Express and Typescript. In part 2 we will cover initializing Firestore and performing the CRUD operations for a Pets REST API.