Deploying Angular Universal v16 to AWS Serverless: A Step-by-Step Guide
Tags: angular, aws, serverless, ssr
Published: 2023-07-03 10:40:30

**Introduction**

Angular Universal is a powerful framework for server-side rendering (SSR) of Angular applications, providing better SEO, performance, and faster loading times. AWS Serverless services, on the other hand, offer a scalable and cost-effective way to deploy applications without managing infrastructure. Combining these two technologies can lead to a high-performing and easily scalable solution. In step-by-step, we will guide you through the process of deploying Angular Universal version 16 to AWS Serverless services.

**Prerequisites**

Before we begin, make sure you have the following prerequisites in place:

1. Node.JS version 18
2. Angular Cli v16
3. AWS account with necessary IAM permissions.
4. AWS CLI (Command Line Interface) installed and configured.
5. Basic knowledge of Angular, AWS services, and serverless deployment.

**Step 1: Create Angular project**
Use the Angular CLI to create your Angular app. Ensure that you have version 16 of Angular dependency installed.

To create angular project you can run the command below:

```
$ ng new my-app
```

and then setup angular universal, this command will install some dependencies, update files and create others, if you are not familiar I recommend this link: https://angular.io/guide/universal

```
$ ng add @nguniversal/express-engine
```

then run the command to make sure everything is OK, it will run your app on localhost port 4000.

```
$ npm run build:ssr && npm run serve:ssr
```  

This command will generate a production build of your Angular Universal app, including the server-side rendering files.


**Step 2: Setup an AWS Serverless Framework**

We will set up a basic Serverless Framework project with a handler function in AWS Lambda.

2.1 - First we need to install serverless framework dependencies:

```
$ npm i -S aws-serverless-express
$ npm i -D serverless serverless-api-compression serverless-apigw-binary serverless-associate-waf serverless-offline
```

2.2 - Then create a `lambda.js` file on root and add the SSR handler function.

```javascript
const awsServerlessExpress = require("aws-serverless-express");
const server = require("./dist/my-app/server/main");
const awsServerlessExpressMiddleware = require("aws-serverless-express/middleware");

const binaryMimeTypes = [
  "application/javascript",
  "application/json",
  "application/octet-stream",
  "application/xml",
  "image/jpeg",
  "image/png",
  "image/gif",
  "text/comma-separated-values",
  "text/css",
  "text/html",
  "text/javascript",
  "text/plain",
  "text/text",
  "text/xml",
  "image/x-icon",
  "image/svg+xml",
  "application/x-font-ttf",
];

const app = server.app();
app.use(awsServerlessExpressMiddleware.eventContext());
const serverProxy = awsServerlessExpress.createServer(app,null,binaryMimeTypes);

module.exports.universal = (event, context) =>
  awsServerlessExpress.proxy(serverProxy, event, context);

```
2.3 - Next create a `serverless.yml` file on root as show below:

```yml
service: angular-serverless-app

plugins:
  - serverless-apigw-binary
  - serverless-offline
  - serverless-api-compression
  - serverless-associate-waf

provider:
  name: aws
  runtime: nodejs18.x
  memorySize: 2048
  timeout: 10
  stage: dev
  region: us-east-1
  deploymentBucket:

package:
  excludeDevDependencies: true
  exclude:
    - src/**
    - node_modules/**
    - firebug-lite/**
    - e2e/**
    - coverage/**
    - .angular/**
    - .vscode/**
    - '!node_modules/@vendia/**'
    - '!node_modules/aws-serverless-express/**'
    - '!node_modules/binary-case/**'
    - '!node_modules/type-is/**'
    - '!node_modules/media-typer/**'
    - '!node_modules/mime-types/**'
    - '!node_modules/mime-db/**'

custom:
  serverless-offline:
    noPrependStageInUrl: true
  contentCompression: 1024
  apigwBinary:
    types:
      - '*/*'

functions:
  api:
    handler: lambda.universal
    events:
      - http: ANY /{proxy+}
      - http: ANY /
```


**Step 3: Simulate serverless offline mode & deploy to AWS Serverless Services**

To simulate serverless offline mode is easy just run the command:

```
$ serverless offline start
```

Ensure that serverless package is installed global to run command above.

if everything run OK you can deploy using command:

```
$ serverless deploy
```

It will output urls to access your application. Every time you run the command above, a package is created and then uploaded to the S3 bucket, so you can manage them.

obs: Some resources won't be found because the aws service builds the path in your url, to fix it you can create a new build config in `angular.json` and set the path to `baseHref` and add a new npm script:

```json
...
  "configurations": {
    "production": {
      "budgets": [
        {
          "type": "initial",
          "maximumWarning": "500kb",
          "maximumError": "1mb"
        },
        {
          "type": "anyComponentStyle",
          "maximumWarning": "2kb",
          "maximumError": "4kb"
        }
      ],
      "outputHashing": "all"
    },
    "serverless": {
      "budgets": [
        {
          "type": "initial",
          "maximumWarning": "500kb",
          "maximumError": "1mb"
        },
        {
          "type": "anyComponentStyle",
          "maximumWarning": "2kb",
          "maximumError": "4kb"
        }
      ],
      "outputHashing": "all",
      "baseHref": "/dev/"
    },
...
```

```json
"build:ssr:aws": "ng build --configuration serverless && ng run my-app:server",
```

**Step 4: remove serverless application**

To remove your application you can run command below:

```
$ serverless remove
```

**Step 5: Domain Setup (Optional)**

If you prefer to use a custom domain for your application, set up a domain and configure it to point to your AWS Serverless app. This step involves setting up DNS records and configuring your AWS resources accordingly.

**Conclusion**

By following these steps, you can deploy your Angular Universal v16 application to AWS Serverless services, combining the power of SSR with the scalability and cost-effectiveness of AWS Serverless offerings. This setup ensures improved performance, better SEO, and seamless scalability for your Angular app. Remember to keep an eye on Angular Universal and AWS updates for any changes or improvements in the deployment process.

The repository with all changes:  [https://github.com/jeanfsantos/angular-serverless-app](https://github.com/jeanfsantos/angular-serverless-app)

Happy Deploying!