Skip to content

Using TypeScript with nodejs runtime #2636

@Envek

Description

@Envek

Hey! Thank you for awesome tool–it is amazing (yet magical a bit). Here I want to bring some attention to areas (with links to existing issues) where it is hard to use and customize SAM CLI. And, hopefully, start discussion for this topic.

TL;DR: Use Makefile builder to compile typescript to javascript. And I have step-by-step guide for that.


TypeScript has gained a lot of traction and popularity in last years both for frontend and backend usage. It gives us a lot of good things: protection against stupid bugs, code completion in editors, etc.

Unfortunately, AWS SAM CLI out-of-the-box doesn't have support for developing Lambda functions for NodeJS runtime in TypeScript (while Serverless framework does). Moreover, adding TypeScript to existing project is complicated because SAM CLI doesn't allow to add custom steps to default build process.

There are some manuals on how to add TypeScript support, add shared layers, and so on, but usually they tend to bring Webpack and replace sam build with some custom scripts that tries to mimic SAM CLI behavior. I feel that such approach is just isn't right.

In my opinion, this is how proper TypeScript support should look like:

  • Keeping the local development experience mostly unchanged: no moving package.json to other places or otherwise changing the directory structure before deployment.
  • No running sam build on every change in function handler code.
  • Keeping generated JS code as close to TS source as possible, preserving the file layout (don't bundle everything into a single file as webpack does).
  • Keeping dependencies in a separate layer shared between related Lambdas. It makes deploys faster as you only need to update function code and not its dependencies. Also, Lambda functions have a size limit which can be easily surpassed with heavy dependencies; shared layers allow us to keep coloring between the lines.
  • Keeping deploys unchanged: sam build and sam deploy, with no extra CLI magic.

In short, a Lambda with TypeScript and shared layers must behave the same way as a freshly generated Lambda on pure Node.js.

After all, I succeeded to set it up in a way that is not ideal yet, but that I like pretty much using Makefile builder as described in Building layers doc for details.

Basically it is:

build-ExampleFunction:
	npm install
	tsc
	cp -r dist "$(ARTIFACTS_DIR)/"

Where TypeScript source code is located in src/ directory, while both local and deployed lambda is instructed to search for handlers in dist/ directory that contains transpiled JavaScript:

# template.yml
Resources:
  ExampleFunction:
    Type: AWS::Serverless::Function
    Metadata:
      BuildMethod: makefile
    Properties:
      Handler: dist/handlers/example.exampleHandler

To better document my approach, I've done following things:

However, there are some inconveniences left:

  • It is hard to debug Makefile-based builds: New Makefile Output & Debugging #2006
  • It is annoying to remove .aws-sam directory after every deploy to make sam local invoke and sam local start-api use local code instead of packaged one.

I hope that my research results and these artifacts will be useful to both SAM CLI users and its developers.


Is there any plans to add built-in support for TypeScript?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions