Serverless framework, Typescript, Express and Webpack

Yasuhiro Ito

Serverless Framework

Typescript

Webpack

Express

Wed Sep 15 2021

I'm going to tell you how to implement express with typescript on serverless by using webpack!

The directory structure and files

- src/
  - routes.ts
- package.json
- serverless.yaml
- tsconfig.json
- webpack.config.js

package.json

{
  "name": "sls-express-ts-webpack",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@vendia/serverless-express": "^4.3.11",
    "express": "^4.17.1"
  },
  "devDependencies": {
    "@babel/core": "^7.15.5",
    "@babel/preset-env": "^7.15.4",
    "@babel/preset-typescript": "^7.15.0",
    "@types/express": "^4.17.13",
    "babel-loader": "^8.2.2",
    "cache-loader": "^4.1.0",
    "fork-ts-checker-webpack-plugin": "^6.3.3",
    "serverless": "^2.57.0",
    "serverless-offline": "^8.1.0",
    "serverless-webpack": "^5.5.3",
    "typescript": "^4.4.2",
    "webpack": "^5.52.0",
    "webpack-node-externals": "^3.0.0"
  }
}

serverless.yaml

service: sls-express-ts-webpack
useDotenv: true

provider:
  name: aws
  runtime: nodejs12.x

custom:
  webpack:
    webpackConfig: "webpack.config.js"
    packager: "yarn"
    includeModules: true
  serverless-offline:
    useChildProcesses: true

package:
  individually: true

plugins:
  - serverless-webpack
  - serverless-offline

functions:
  app:
    handler: src/routes.handler
    events:
      - httpApi:
          path: "/{proxy+}"
          method: "*"

tsconfig.json

{
  "compilerOptions": {
    "preserveConstEnums": true,
    "strictNullChecks": true,
    "inlineSources": true,
    "inlineSourceMap": true,
    "sourceRoot": "/",
    "target": "es2017",
    "outDir": ".build",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "lib": ["es2017"],
    "rootDir": "./",
    "resolveJsonModule": true
  }
}

webpack.config.js

const path = require("path");
const nodeExternals = require("webpack-node-externals");
const slsw = require("serverless-webpack");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");

const isLocal = slsw.lib.webpack.isLocal;

module.exports = {
  mode: isLocal ? "development" : "production",
  entry: slsw.lib.entries,
  externals: [nodeExternals()],
  devtool: "source-map",
  resolve: {
    extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
  },
  output: {
    libraryTarget: "commonjs2",
    path: path.join(__dirname, ".webpack"),
    filename: "[name].js",
  },
  target: "node",
  module: {
    rules: [
      {
        // Include ts, tsx, js, and jsx files.
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "cache-loader",
            options: {
              cacheDirectory: path.resolve(".webpackCache"),
            },
          },
          "babel-loader",
        ],
      },
    ],
  },
  plugins: [new ForkTsCheckerWebpackPlugin()],
};

src/routes.ts

import express, { json } from "express";

const serverlessExpress = require("@vendia/serverless-express");
const app = express();

app.use(json());

app.get("/", async (_, res) => {
  return res.send("<h1>Hello World!!</h1>");
});

export const handler = serverlessExpress({ app });

Install packages

You need to install packages.

yarn install

Now ready to go

npx sls offline start

You can see "Hello World" on your browser if you access http://localhost:3000.

How to deploy to AWS

You need to setup the credential for AWS, then execute the below.

npx sls deploy