Adding pub/sub to an Express application.
Tags: cloudcomputing, javascript, tutorial, webdev
Published: 2023-07-12 15:30:06


In this blog post, we'll take a deeper look at how you can scaffold a new cloud application and take advantage of resources like topics, queues, and buckets in your Express applications. 

## Essential Tools and Services

To follow through and successfully complete this guide, you'll need to have the following tools and services installed and set up:

- **Node.js**: This is the runtime environment that allows you to run JavaScript on your local machine. You can download and install it from the official [Node.js website](https://nodejs.org/en/).
- **Nitric CLI**: This is a command-line interface for interacting with the Nitric platform. You can find the installation guide for the Nitric CLI in our [Getting Started guide](https://nitric.io/docs/guides/getting-started/installation).
- (Optional) An account on a cloud provider platform of your choice, such as [Amazon Web Services (AWS)](https://aws.amazon.com), [Google Cloud Platform (GCP)](https://cloud.google.com), or [Microsoft Azure](https://azure.microsoft.com).

## Setting up Your Project

Our first step will be to initialize a new Nitric project and add Express.js to it. Open a terminal and execute the following commands:

```bash
nitric new
? What is the name of the project? express-example
? Choose a template: official/JavaScript - Starter

# Navigate into your newly created project directory and install dependencies
cd express-example
yarn install

# Add express to your project
yarn add express
```

Now, open the project in your preferred code editor. Your project structure should resemble the following:

```txt
├── functions
│   ├── hello.js
├── node_modules
│   ├── ...
├── .gitignore
├── index.js
├── nitric.yaml
├── package.json
├── README.md
└── yarn.lock
```

You might notice a `functions` folder in the project structure. By default, Nitric anticipates the entry-point code for your application to reside here. However, this convention is flexible; you can modify it according to your application's requirements.

For this guide, let's replace the `functions` folder with a single entry-point file named `app.js`. Execute the following commands to achieve this:

```bash
rm ./functions/hello.js
touch ./functions/app.js
```

Next, we'll add some express code to kickstart our application:

```javascript
import express from 'express'
import { http } from '@nitric/sdk'

const app = express()

app.get('/', (req, res) => {
  res.send('Hello World!')
})

http(app)
```

In the code snippet above, if you're familiar with Express.js, you'll notice we didn't use `app.listen`. Instead, we employed the Nitric `http` function. This function handles the responsibility of binding the application to the appropriate port for each environment, thereby eliminating the need for `app.listen`.

With this setup, your Express.js application is ready for local testing. By default, the project comes with a `dev` script that you can run to start the local development server:

```bash
yarn dev
```

If your setup is correct, part of the output should resemble:

```txt
SUCCESS  Started Local Services! (1s)
Local running, use ctrl-C to stop

Proxy | Endpoint
8000  | http://localhost:4001

Dev Dashboard | http://localhost:49152
```

Now, your Express application is running locally, with Nitric acting as a proxy. The app is available at port `4001`, and you can test it using another terminal or web browser. Run the following command in another terminal:

```bash
curl localhost:4001
Hello World!
```

## Enhancing Your Express.js Application with cloud resources using Nitric

With the basic Express.js application up and running, let's explore how to extend its functionality with Nitric. For instance, we'll add a pub/sub topic that will allow us to execute tasks in the background while still maintaining quick HTTP API response times.

Update your `app.js` file with the following code:

```javascript
import express from 'express'
import { http, topic } from '@nitric/sdk'

const app = express()
const workRequests = topic('work-requests').for('publishing')

app.get('/', async (req, res) => {
  await workRequests.publish()
  res.send('Hello World!')
})

http(app)
```

In the updated code above, we introduce a `workRequests` topic that our application publishes. We also create a new function to handle the background work:

```bash
touch functions/worker.js
```

The `worker.js` file will contain the following code:

```javascript
import { topic } from '@nitric/sdk'

const sleep = (ms) => new Promise((res) => setTimeout(res, ms))

topic('work-requests').subscribe(async (ctx) => {
  console.log('Starting new request')
  // Wait for 2 seconds to simulate a long-running task
  await sleep(2000)
  console.log('Request processed')
})
```

When you navigate to `localhost:4001` in your browser, you should notice that the console outputs two lines, with a two-second delay between them, which indicates the simulated work request:

```txt
Starting new request
Request processed
```

You should note that even though the background worker takes two seconds to finish, the HTTP request `GET: /` still returns instantly.

## Deployment to the Cloud

Nitric simplifies the process of deploying your application to the cloud. It negates the need for manual cloud deployment processes or the use of external solutions like Terraform. 

To facilitate the deployment, we'll create a `stack`. A stack provides Nitric with the configuration necessary for a specific cloud instance of your project, such as the provider and the region.

Let's create a new stack for AWS:

```bash
nitric stack new
? What do you want to call your new stack? dev
? Which Cloud do you wish to deploy to? aws
? select the region us-east-1
```

The `nitric stack new` command will create a file named `nitric-dev.yaml`, containing:

```yaml
name: dev
provider: nitric/aws@0.30.0
region: us-east-1
```

Now, you can deploy your application to the cloud using the following command:

```bash
nitric up
```

After successful deployment, you can access your Express.js + Nitric application in the cloud using the API Gateway URL provided in the `up` command's output.

When you're done with the cloud deployment, you can decommission it using the `nitric down` command.


## Further Exploration

Watch a video about our [frameworks support](https://www.youtube.com/watch?v=IJomTyZeI3g).

Now that you understand the basics, consider exploring other Nitric resources available to enhance your app. These resources include:

- [Collections](https://nitric.io/docs/collections)
- [Schedules](https://nitric.io/docs/schedules)
- [Storage](https://nitric.io/docs/storage)
- [Messages](https://nitric.io/docs/messaging)
- [Secrets](https://nitric.io/docs/secrets)

Each of these can be added to your application with only a few lines of code.

Happy coding!