This project demonstrates using the following technologies:
-
AWS Lambda: AWS Lambda allows developers to deploy packages of executable JavaScript code to the AWS infrastructure and make it executable without having to worry about managing servers.
-
webpack:
webpack
is used to create optimized bundles from JavaScript code that leverage ES6 modules. -
babel:
babel
transpiles JavaScript code to JavaScript code that is compatible with various runtimes. -
TypeScript: TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
-
bunyan:
bunyan
provides structured JSON logging. -
ava:
ava
is a test runner. -
tslint:
tslint
is a TypeScript linter. -
yarn:
yarn
is a dependency manager that is an alternative tonpm
. -
nyc:
nyc
provides a command-line interface for calculating test code coverage with istanbul. -
chalk:
chalk
is used to add color to console output. -
proxyquire:
proxyquire
is used to substitute mock modules at runtime when running tests.
Clone this repo and make changes as you see fit. Push your changes to your own repo.
-
Allow developers to use TypeScript for lambda functions, tests, and other source code.
-
Also allow JavaScript files to be used (hopefully sparingly).
-
Automatically compile JavaScript code related to AWS Lambda functions down to level supported by
node
6.10
(which is currently the latest Node.js runtime that AWS lambda supports). -
Calculate test code coverage using
nyc
when running tests usingava
. -
Create a bundle using
webpack
for each AWS Lambda function located atsrc/lambdas/*
.
-
Create a server and relaunch when file changes (this is not necessary due to the nature of testing and deploying lambda functions).
-
Provide a starter project that works for everyone.
-
Provide deployment scripts (use something like terraform, CloudFormation, or aws-cli if you need to deploy lambda functions).
-
yarn test
: Use this command to lint, compiletest/**/*
files with TypeScript, and run tests withava
andnyc
. We use the following glob pattern for unit tests:test/**/*.test.js
. -
yarn build
: Use this command to compile the lambda functions. -
yarn bundle
: Use this command to build the lambda functions and then create zip files atwork/dist/*.zip
. -
yarn lint
: Use this command to lint thesrc/**/*
andtest/**/*
files withtslint
(does not require compilation).
This starter project uses require-self-ref
to make it possible to require
/import
relative to the root of the project.
For example, import { sleep } from '~/src/util'
will always import
the sleep
function from src/util/index.ts
no matter which file
the import file is found in.
In the webpack
configuration we provide an resolve.alias
property
that automatically resolves ~/*
paths relative to the root of the project.
In the tsc
(TypeScript compiler) configuration, we use a combination of
the compilerOptions.baseUrl
and compilerOptions.paths
properties to
configure how ~/*
paths are resolved.
At runtime, all test files include import 'require-self-ref'
which
loads the require-self-ref
module which tweaks the Node.js module
loader so that ~/*
paths are properly resolved at runtime. It's
not necessary to use require-self-ref
for lambda functions because
the webpack
bundling job will automatically inline all modules into
a single bundle.
TypeScript was chosen because it helps developers write code with more compile-time safety checks via it's flexible and powerful static typing.
This project provides multiple TypeScript configuration files and their usage is explained below.
-
tsconfig.json
: This TypeScript configuration file is used by IDEs such as Visual Studio Code and Atom Editor. Theincludes
for this configuration includesrc/**/*
andtest/**/*
.The compilation scripts in this project do not use this configuration when compiling files because the output settings for
test
andsrc
are different. -
tsconfig-test.json
: This TypeScript configuration file is used to compile files intest/
directory and themodule
output setting iscommonjs
so that they can be executed directly by Node.js runtime without having to be bundled or transpiled withwebpack
andbabel
. -
tsconfig-src.json
: This TypeScript configuration file is used to compile files insrc/
directory and themodule
output setting isES6
and the output files cannot be executed directly by Node.js. It is assumed thatwebpack
andbabel
will be used to create a JavaScript bundle that targets the Node.js runtime supported by AWS Lambda.
The webpack tool is used to create an
optimized bundle for each lambda function located at src/lambdas/
.
The webpack
tool is invoked via yarn webpack
which cause webpack
to
use the default configuration located at webpack.config.json
.
This project does not use webpack
to process code in the test/*
directory when running tests. The test code is only compiled by
the TypeScript compiler (tsc
). The source files in test/*
are
compiled from TypeScript down to commonjs
modules so that they can be
loaded directly by the Node.js runtime.
NOTE: In earlier versions of this starter project, we tried to use
rollup
but rollup
poorly handled transforming JavaScript files
that had both ES6 import
/export
statements and CommonJS require(...)
statements in the same file.
In our use case, we wanted to be able to require(...)
normal JavaScript files
and use import
/export
for ES6 modules created from TypeScript compiler.
That is, in our use case a single JavaScript file compiled from TypeScript
file might have a mix of import
/export
and require(...)
statements.
When the rollup-plugin-commonjs
plugin saw import
/export
in a file then it didn't bother traversing
the require(...)
statements (because it assumed that you don't mix
both in the same file). This caused code referenced in these require(...)
statements to not be bundled properly.
The webpack configuration for each lambda function is dynamically produced
inside webpack.config.js
. webpack
will automatically create a bundle as
described by the entry
property. The entry
property value is an object in
which each key is a bundle name and each associated value is the entry point
file.
The babel
transpiler is integrated with webpack
via babel-loader
plugin.
This project is only configured to use babel
when creating the AWS lambda
bundle files because we need to transpile all JavaScript files so that they
are compatible with the Node.js runtime supported by AWS Lambda. Currently,
the highest Node.js version supported bye AWS Lambda is node
6.10
.
The babel
configuration is embedded inside the webpack
configuration which
allows flexibility in the future for having multiple babel
configurations
for the various output targets.
The babel-preset-env
package provides presets for babel
that can be
used to target specific runtime environments (for example, node
6.10
).
The babel
configuration is provided via the options
property of the
babel-loader
plugin in webpack.config.js
and it looks like the following:
{
presets: [
[
'env',
{
// Latest Node.js runtime for AWS Lambda functions is currently 6.10
targets: {
node: '6.10'
},
modules: false
}
]
],
plugins: [
'external-helpers'
]
}
This project uses bunyan
because it uses structured JSON logging.
Bunyan loggers are created and configured when they are created via
the createLogger
function of src/logging/index.ts
.
This project provides a yarn.lock
file and uses yarn
as its package manager.
If you prefer npm
then delete the yarn.lock
file and run npm install
which will create a package-lock.json
file.
All source code for this project is provided under the MIT License.
See LICENSE
file.
If you see ways to improve this project then please create a Pull Request or an Issue.