top of page
Search
Writer's pictureSeiji Ralph Villafranca

Serverless Angular with AWS Lambda

Updated: Aug 8, 2021

Serverless Applications are now a trend these days for applications, it reduces the time effort and cost for our applications to be deployed, so diving deeply on what is the concept of Serverless, it is simply the process of outsourcing servers from third party providers that will handle all the deployment responsibilities using shared machines, it is a Functions as a Service (FaaS) which it only runs when clients has requests executed on the application and providers are charging costs base only on the number of requests which allows us to minimize the applications cost especially a low number of users are using our app.


Angular going Serverless!


A huge thank you for AWS that they have made serverless deployments Angular easier by providing extensions that we can deploy our applications on the fly. all we have to do is configure our angular application with instructions using yml configuration.


In this part, I will show you a step by step guide on how to deploy our Angular application on AWS Lambda, I assume here that you already have your awesome angular app that we can show the world by deploying on AWS.


Here are the other prerequisites we need before we start our setup.


AWS cli

you can install AWS cli using the link below


Serverless Framework

We will install this as dev dependency later on as we setup our Angular Project


Angular Universal

We will use this as our basis for creating our serverless configuration.


The First thing we need to do is install Angular Universal, we will use this as our basis for our setup as we create our own serverless configuration. to install Universal execute the following command.


This will add support for SSR for our application by adding several files and additional scripts on package.json.


Now we will install our AWS dependencies and serverless framework so we have the capability to test our serverless locally.


This will install our serverless framework with serverless-offline to run our application offline.

npm install serverless serverless-offline serverless-apigw-binary -D

We will use aws-serverless-express to for our Lambda function.

npm install aws-serverless-express --save

Now in our project root directory, we will create a serverless.yml file that will contain our configuration necessary for deploying our application to AWS.



service: angular-serverless
plugins:
  - serverless-apigw-binary
  - serverless-offline
provider:
 name: aws
 runtime: nodejs12.x
 memorySize: 192
 timeout: 10
package:
 exclude:
    - ./**
 include:
    - "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/**"
    - "dist/**"
    - "lambda.js"
custom:
 apigwBinary:
 types:
      - "*/*"
functions:
 api:
 handler: lambda.handler
 events:
      - http: GET {proxy+}
      - http: GET /

We can see in our configuration that we our instructing what to Serverless what plugins we need for our application to run.


The next step is we will now configure our own configuration on building our serverless application, we will copy the content of server.ts generated by Angular Universal and create a file named serverless.ts file on our root directory.


import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
export const app = express();
const distFolder = join(process.cwd(), 'dist/angular-serverless/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)

app.engine('html', ngExpressEngine({
 bootstrap: AppServerModule,
}));

app.set('view engine', 'html');
app.set('views', distFolder);

// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser

app.get('*.*', express.static(distFolder, {
 maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
 res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
export * from './src/main.server';

The only difference here is that we have omitted the run function as Serverless apps will run upon request of clients and will not require ports.


We will now add tsconfig.serverless.json file that will be used as a configuration for building our Serverless app, the content will be the same as the generated tscconfig.server.json file of Angular Universal, we will just change the ourDir to ./out-tsc/serverless and under the files property we will change the server.ts to serverless.ts file.

{
 "extends": "./tsconfig.app.json",
 "compilerOptions": {
 "outDir": "./out-tsc/serverless",
 "target": "es2016",
 "types": [
 "node"
    ]
  },
 "files": [
 "src/main.server.ts",
 "serverless.ts"
  ],
 "angularCompilerOptions": {
 "entryModule": "./src/app/app.server.module#AppServerModule"
  }
}

Now we want to add our own build configuration that will used our added settings for Serverless, under angular.json we will copy the server properties and rename it to serverless, and we will use our serverless.ts as our main file and tsconfig.serverless.json as our typescript configuration.


 "serverless": {
 "builder": "@angular-devkit/build-angular:server",
 "options": {
 "outputPath": "dist/angular-serverless/serverless",
 "main": "serverless.ts",
 "tsConfig": "tsconfig.serverless.json"
          },
 "configurations": {
 "production": {
    "outputHashing": "media",
    "fileReplacements": [
                {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.prod.ts"
                }
              ],
   "sourceMap": false,
    "optimization": true
            }
          }
        },

And after successfully configuring our application, all we need to do is add our scripts in our package.json that will build our Serverless app, add the following scripts in our package.json file

"serve:serverless": "serverless offline start",
"build:serverless": "ng build --prod && ng run angular-serverless:serverless:production"

Now we will now allow the support of lambda functions as we deploy our Angular application AWS, we will create a lambda.js file on our root project that will contain the MIME Types and the aws-server-express that serve our distribution file.



const awsServerlessExpress = require("aws-serverless-express");
const server = require("./dist/angular-serverless/serverless/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",
];

server.app.use(awsServerlessExpressMiddleware.eventContext());
const serverProxy = awsServerlessExpress.createServer(
  server.app,
  null,
  binaryMimeTypes
);
module.exports.handler = (event, context) =>
  awsServerlessExpress.proxy(serverProxy, event, context);
 


and that's it, to test of our configuration will successfully build and run a serverless app we will run the npm run build:serverless.


We can see here that our application has been built successfully, we can run npm run serve:serverless to run our application locally.



We can see that our app is now running on local, and every request by the browser will be logged here as Serverless applications are on demand.

Ready on AWS!


we are now ready to deploy our application on AWS, we have configured that it can support lambda, now before we proceed, we must configure our access id and secret key as this will not allow us to deploy on AWS without a valid credentials, execute the following command and enter you access id and secret key.

aws configure

after successful configuration, we will add the script serverless:deploy on our package.json


execute the command npm run serverless:deploy and this will upload our compiled code and will provide a URL where we can access our Angular application.


and that's it! we have successfully deployed our Angular application using AWS Lambda.

for the repository of the code, checkout my project in Github.


Cheers and happy deploying!


5,395 views3 comments

Recent Posts

See All

3 Comments


Somshree Mukherjee
Somshree Mukherjee
Dec 02, 2022

After I have successfully done a "serverless deploy", I am able to see my lambda function in the console and cloudformation stacks, etc. However, by default it does not seem to have a function URL to view the deployed application. I have been trying to play around a bit to get a function URL but it end up in an error message "internal server error". Any ideas ?

Like

Darryl Frith
Darryl Frith
Jan 10, 2022

Thanks for posting this. When I run "npm run serve:serverless" I get


Serverless Error ----------------------------------------

Unexpected "handler" function configuration: Expected object received 'lambda.serverless'

Any ideas?

Like
Richard Davies
Richard Davies
Oct 31, 2022
Replying to

There is a slight error with the indenting in the serverless.yml file. The lines after "api:" should be indented. It should read:


functions:

api:

handler: lambda.handler

events:

- http:GET{proxy+}

- http:GET/


Like
bottom of page