How I automatically deployed Typescript to Elastic Beanstalk to speed up server-side development
By: Andrew Chung
Tags: Typescript, Deployment, Elastic Beanstalk, Nodejs, Servers

How I automatically deployed Typescript to Elastic Beanstalk to speed up server-side development

Speed up your development process by auto-deploying Typescript code to EB!

A demo of Booktogether, an online publishing platform that I created the back-end for.

For my most recent team project Booktogether — an online publishing platform in Korean for book curations and reviews — I was responsible for server-side development using Typescript and Express, as well as deployment using AWS Elastic Beanstalk.

As I soon found out, manual deployment to EB was a tedious process. I was constantly compiling Typescript code to Javascript, compressing all the files into a .zip file, and uploading the compressed file to AWS.

That’s when I thought to myself, “is there any way I can speed up deployment, so I can just focus on writing working code?” After doing some digging online, I found this walkthrough by Aaron White that helped me set up AWS CodePipeline to send my code straight from Github to EB.

Side Note: A Common Error

Although I won’t go through configuration details of CodePipeline too deeply in this article, I would like to specify a problem that I encountered while setting up this auto-deployment system. When I originally pushed the server-side code (along with a build spec file) from Github to AWS, the EB console responded with the following error:

[Instance: i-12345] Command failed on instance. Return code: 1 Output: (TRUNCATED)…/opt/elasticbeanstalk/containerfiles/ebnode.py”, line 180, in npm_install raise e subprocess.CalledProcessError (TRUNCATED)

As I later realized, this error happened because of the npm install command that EB runs when code is deployed to the EC2 instance. Specifically, the installation of some packages trigger the node-gyp process, which is run by the default EC2 user.

The default user does not have permission to access some of the packages in the node_modules directory that npm install creates, which is why one needs to create a file called .npmrc in the project root and add the following:

# Forces node-gyp process to be run as root user, not ec2 default

unsafe-perm=true

Auto-deploying Typescript code to EB

Now back to the heart of the matter. When code is deployed to a Node.js environment in Elastic Beanstalk, node app is automatically called in order to initialize the server. However, because Node.js is a Javascript runtime environment, the Typescript code that I had written for my server would not run by default. I needed to compile my Typescript code first.

In order to accomplish this without having to manually upload my code as a .zip file, I had two options. The first was to simply compile Typescript code on my local machine using a command like npm run build , and then upload both Javascript and Typescript to my Github repository. This option, however, had two main drawbacks:

An extra step (executing npm run build ) would be added to the deployment process I would have to manage changes in both .js and .ts files in Github

Given these issues, I resorted to another option — specifically, the use of the .ebextensions directory. Files in this directory are used for advanced custom configuration of an Elastic Beanstalk environment. .ebextensions files are written in YAML or JSON format, with a .config file extension.

The config file I used in this case configured EB in such a way that the instance would compile all Typescript code to Javascript right after running npm install . Referencing the following article on Typescript compilation using .ebextensions, I created a file called source_compile.config in the .ebextensions directory and included the following script:

# source_compile.config

container_commands:

compile:

command: "./node_modules/.bin/tsc -p tsconfig.json"

env:

PATH: /opt/elasticbeanstalk/node-install/node-v10.15.3-linuxT-x64/bin/

The command tsc -p tsconfig.json tells EB to compile the Typescript project to Javascript given the configuration file tsconfig.json . If there is no outdir key specified in tsconfig.json , the compiled .js files will be located in the same locations as the corresponding .ts files.

Additionally, I needed to ensure the version of node specified in the PATH key was compatible with the node version used by my EB environment. If needed, one should change the node version (currently written as v10.15.3) and OS name used in the PATH key of the source_compile.config script above.

Having gone through all these steps, I once again merged changes into my main Github branch — and voilà! The server was up and running.