Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

How to Develop Serverless Apps with GitHub Codespaces

Want to develop a serverless app with Codespaces? This tutorial will show you how to get an Azure Functions & Static Web App project ready.

Jun 08, 2023 • 0 Minute Read

Please set an alt value for this image...

GitHub Codespaces is an online development environment that runs on GitHub and works with Visual Studio Code. We can use it to develop 100% in the cloud. So I wanted to see if it could run a project that mixes Azure Functions with Azure Static Web Apps.

This project tutorial will show you how to get your Azure Functions & Static Web App project ready for GitHub Codespaces. You'll learn how to customize Visual Studio Code launch targets to automate how you test your application and about configuring your project so Visual Studio Code extensions are automatically installed for when you develop in the cloud.

The project consists of a Static Web App with an image upload form. The image is uploaded directly to Azure Blob Storage, but for that to work, it needs to receive a SAS key to perform anonymous authentication to the blob container. This means we have a serverless backend that generates SAS keys that's can be retrieved by our frontend via an API call.

You can access the project's code here on GitHub.

To complete this tutorial, you will need an Azure Account. You can sign up for free. Once you have registered, you need to create an Azure Storage Account

We want to have a dev environment that can run in Codespaces and is able to support all those services out of the box, so let's list what we need:

  1. Our project runs on nodejs so we'll need to have that dependency installed.
  2. For Azure Functions we need the Azure Functions Core Tools installed, also to test them locally.
  3. For the `@azure/storage-blob` dependency we need to have a running `webpack` that automatically rebuilds our project's JavaScript whenever we do some changes.
  4. For Static Web Apps we want the Live Server extension for Visual Studio Code that let us preview our website locally.
  5. Set up the environment variables required by our project.

Let's see how we can address each of these problems. 

Preparing your project for Codespaces

Behind the scenes, Codespaces runs docker containers where our dependencies will be installed. Luckily for us, Codespaces has a whole repo with ready-made containers that we can use out of the box. Go clone the /microsoft/vscode-dev-containers repo on GitHub. There, inside the `containers` folder we have `azure-functions-node` that already includes the nodejs dependency and the Azure Functions Core Tools dependency. So, points 1 and 2 will be covered by that. 

To enable that container for our project we need to copy the `.devcontainer` folder from the `azure-functions-node` folder into our project's root folder. Inside that directory sits the `Dockerfile` and the `devcontainer.json` file that's used for configuring our Codespace. Once it's added, commit it to git and push it to GitHub.

To setup `webpack` we are going to add these lines into our `package.json` file to make sure the dependencies are installed in the Codespaces container:

json
"devDependencies": {
  "webpack": "^4.44.1",
  "webpack-cli": "^3.3.12"
}

And then under `scripts` we will add a custom one to execute `webpack` called `build`:

json
"scripts": {
    "start": "func start",
    "test": "echo "No tests yet..."",
    "build": "webpack --mode=development"
  },

Then we need to tell VSCode how to start our project. Usually when we hit `F5` VSCode starts the Azure Functions Core Tools, but in this case, we also need it to run the webpack build. Let's edit the `.vscode/tasks.json` file to add a couple of tasks there.

json
{
  "type": "shell",
  "label": "npm run webpack",
  "command": "npm run build",
  "dependsOn": "npm install"
},

This task will run our webpack build command, and at the same time depend on `npm install` so we make sure that one is run as well. Then we need to edit the `host start` task which is the one that will launch the `Azure Functions Core Tools`. Let's make it depend on our webpack task:

json
{
  "type": "func",
  "command": "host start",
  "problemMatcher": "$func-watch",
  "isBackground": true,
  "dependsOn": "npm run webpack"
},

Note that task dependencies are specified using the task `label` as identifier.

We got 3 out of 5. Now it's time to solve the Live Server one. We need the Live Server extension installed by default. To do that, let's open the `.devcontainer/devcontainer.json` configuration file and edit the `extensions` entry to include the id for the Live Server extension, (and since we are there, let's add the Static Web Apps extension):

json
"extensions": [
	"ms-azuretools.vscode-azurefunctions",
"ms-azuretools.vscode-azurestaticwebapps",
	"dbaeumer.vscode-eslint",
	"ritwickdey.liveserver"
],

Live Server will let us preview or Static Web App under http://localhost:5500. Inside Codespaces any URL that points to localhost will be port-forwarded and redirected to a rewritten URL. For that to work with Live Server we need to tell Codespaces to forward the `5500` port. In the `.devcontainer/devcontainer.json` file we need to modify the `forwardPorts` entry to also include that port:

json
"forwardPorts": [ 7071, 5500 ],

We are going to take care of step 5 once we are inside Codespaces.

Creating your first Codespace

With all the changes we did in the previous steps, it's time to push your project to GitHub. Once that's done, go to GitHub Codespaces and click "Create your first codespace".

Then select the project for the codespace, and the git branch, and click create codespace:

Once the codespace is up and running, we can proceed to the final fifth step, which is to tell Azure Functions Core Tools how to connect to our storage account. For that create a file called `local.settings.json` at the root of your project. You can do so by renaming the `local.settings.sample.json` file already provided with the repo and calling it `local.settings.json`. There we can edit the `AzureWebJobsStorage` key to include the connection string from our storage account obtained from Azure Portal. You can do all this from inside the Visual Studio Code that's running on Codespaces! How cool and meta is that?!

It should look like this, but with your actual connection string:

json
{
    "IsEncrypted": false,
    "Values": {
      "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=youraccountname;AccountKey=<SecretAccountKey>;EndpointSuffix=core.windows.net",
      "FUNCTIONS_WORKER_RUNTIME": "node"
    }
  }

Once this is done it's time to run the project. Press `F1` and then type `Open with Live Server` to start the Live Server instance that will let us preview the Static Web App side of our project. Once that is done, press `F5` to start the Azure Functions part of our project:

After Azure Functions has booted up our backend, we can proceed to view it in the browser. Select the Codespaces tab in Visual Studio Code side panel to have access to the forwarded ports and their respective URLs:

There click "Port: 5500" under "Forwarded Ports. If all went well you should see something like this:

The Static Web App is running on our Codespace being served by Live Server, and it contacted our Serverless app that provided it with a SAS Key that will let us upload files to Azure Web Storage.

Conclusion

With these 5 steps, we can have a project that uses Azure Static Web Apps and Azure Functions to be ready to go to work out of the box with GitHub Codespaces. 

GitHub Codespaces is a great tool that lets us have a working development environment in the cloud without needing to install anything. This will help us streamline our development and share with fellow developers our apps as we build them, making it easier to collaborate. The possibilities are endless. In my case, I'm excited for all that comes to programming education online and that will be enabled by Codespaces.

Next steps

About the Author

Alvaro Videla is a developer advocate at Microsoft, and he organizes DuraznoConf. He is the coauthor of RabbitMQ in Action and has written for the Association for Computing Machinery. You can find him on Twitter as @old_sound.