Using Serverless framework and Webpack to build AWS Lambda in TypeScript
When dealing with the development on AWS, we rely heavily on the serverless framework mainly because of its capability to simulate the Lambda environment and debug locally.
Instead of using ES6 JavaScript, we decided to use TypeScript to surface some errors at build time.
There is a plugin called serverless-plugin-typescript that can integrate TypeScript with your serverless application. However, we choose to use webpack to preprocess our application in order to get more controls on the compilation processes.
This article is going to share the basic setup of how we did that.
If you want to check out the result, you can have a look on this repository.
Let’s get started!
Photo by Natalya Zaritskaya on Unsplash
Approach 1: Deploying the node_modules and bundled js functions to AWS Lambda
With this approach, the js bundle size would be smaller while the overall package size would be larger comparing to approach 2.
Webpack would bundle only the dependencies between files (with the loaders configured) excluding all dependencies in node_modules.
Bundled files
Steps
- Create your service with the serverless template
aws-nodejs-typescript
serverless create --template aws-nodejs-typescript --path myTypeScriptService
- Update serverless.yml
service: name: aws-nodejs-typescript-service plugins: - serverless-webpack ##### Add below code snippet ##### custom: webpack: includeModules: true # this is telling webpack to reference all dependencies (non-dev dependencies) in node_modules and serverless would upload the package.json with the node_modules folder forceExclude: - aws-sdk # this is available in the lambda environment so it can be excluded, this tells serverless-webpack not to include it in the node_modules folder ################################## provider: name: aws runtime: nodejs12.x functions: hello: handler: handler.hello events: - http: method: get path: hello
- Install webpack-node-externals
yarn add --dev webpack-node-externals
- Update webpack config
const nodeExternals = require("webpack-node-externals"); module.exports = { ... externals: [nodeExternals()], // this tells webpack not to bundle anything from node_modules folder ... }
Approach 2: Have webpack to bundle everything and tree-shake whatever not needed
With this approach, the js bundle size would be larger while the overall package size would be smaller comparing to approach 1.
Webpack will perform tree-shaking and all required dependencies are bundled in the js file so the node_modules folder would not be included in the package.
Bundled files
Steps
- Update serverless.yml
service:
name: aws-nodejs-typescript-service
plugins:
- serverless-webpack
##### Add below code snippet #####
custom:
webpack:
includeModules: false # this is the default value, that means serverless webpack would not create the node_modules folder
##################################
provider:
name: aws
runtime: nodejs12.x
functions:
hello:
handler: handler.hello
events:
- http:
method: get
path: hello
- Update webpack config
module.exports = {
...
externals: ['aws-sdk'], // this tells webpack not to bundle 'aws-sdk', we don't need this because AWS lambda environment has this included
...
}
Approach 3: Have webpack to bundle partially and upload the remaining dependencies to node_modules folder
This is a combination of approach 1 and approach 2. You have to specify the dependencies you do not want Webpack to bundle for you in the external
property.
Then, leave those dependencies for serverless-webpack
to create a package.json
and the node_modules
to upload on your lambda environment.
With this approach, you can do further optimization using AWS Lambda Layers which will store the dependencies that you reuse across different lambdas, you won’t have to redeploy these dependencies unless you update their versions.
Bundled files
Steps
- Update serverless.yml
service:
name: aws-nodejs-typescript-service
plugins:
- serverless-webpack
##### Add below code snippet #####
custom:
webpack:
includeModules: true
forceExclude:
- aws-sdk
##################################
provider:
name: aws
runtime: nodejs12.x
functions:
hello:
handler: handler.hello
events:
- http:
method: get
path: hello
- Update webpack config
module.exports = {
...
externals: ['moment', 'lodash', 'aws-sdk'], // exclude the dependencies that you want serverless-webpack to upload in the nodule_modules folder
...
}
**That’s it for the sharing! **
Here is an article that explains in detail with examples on these approaches, suggest checking it out. https://nordcloud.com/minimizing-aws-lambda-deployment-package-size-in-typescript/
Photo by Kinga Cichewicz on Unsplash