Vercel Serverless RESTfull API example. Using Express.js and Vercel Serverless functions.
As a foundation, Express enables the swift migration of pre-existing applications and also supports the utilization of existing extensions from the Express ecosystem.
While Vercel's Serverless capabilities empower the utilization of the Vercel platform, offering a multitude of advantages such as the ability to run AWS Serverless functions in various regions, preview deployments, and versatile runtime protocols. Furthermore, it facilitates seamless integration with GitHub.
serverless on ξ main [!] is π¦ v1.0.0 via ξ v18.16.0 via π v3.0.0
β― tree -d -C --gitignore -v
.
βββ api
βββ assets
β βββ redoc
β βββ swagger
βββ public
β βββ redoc
β βββ swagger
βββ scripts
βββ src
β βββ middleware
β βββ router
β βββ schema
β βββ service
β βββ utils
βββ tests
16 directories
- Express App api
- Express Router router
- Express Service service
- Express Middleware middleware
- Response Cache middleware/cache
- Response Compression middleware/compression
- Cross-Orign Resource Sharing middleware/cors
- Error handling middleware/error
- JSON Webtoken support middleware/jwt
- Manipulate Header middleware/header
- Serv static paths middleware/staticPath
- Schema Validation schema
- API Specification openapi
- Environment Variables dotenv
- Log, Ip, Hash, Token, Response and RuntimeCache Utils utils
- Rewrites vercel.json
- Generate
vercel.json
script generateVercelJson.mjs - Generate JWToken generateJWToken.mjs
- Generate Swagger generateSwagger.mjs
- Generate HomePage generateHomePage.mjs
- Ceck base bundle size scripts
- Cache info Service service/cache
- Info example Service service/info
- Track example Service service/track
- Application
- Express express
- Express JWT express-jwt
- Express CORS cors
- Express StaticPaths express static
- Express ApiCache apicache
- HTTP Client axios
- JWT jsonwebtoken
- Testing
- Unit Test jest
- SuperTest supertest
- E2E Test playwright
- Development
- TypeScript typescript
- nodemon nodemon
- Code Quality
- Lint eslint
- Format prettier
- Commitlint commitlint
- Husky Pre-Commit and Push hooks husky
- Documentation
- CI/CD
Prerequisites:
- pnpm
npm i -g pnpm
Install dependencies:
pnpm i
Update dependencies:
pnpm up
The pnpm install hook updates includeFiles
in the vercel.json
file.
Nodemon is used to watch for changes and restart the server. Tsc is used to compile the TypeScript code.
pnpm dev
Eslint is used to lint the code.
pnpm lint
Jest is used to run the tests.
pnpm test
Playwright is used to run the e2e tests.
pnpm e2e
Tsc is used to compile the TypeScript code.
The swagger documentation is generated from the OpenAPI specification in the openapi.yml
file.
pnpm build
The pre-commit and pre-push hooks are configured with the [husky] The pre-commit hook runs the lint and generates the documentation. The pre-push hook runs a test build.
- http://localhost:8000/api/track/
- http://localhost:8000/api/info
- http://localhost:8000/api/info/req/headers
- http://localhost:8000/api/cache/performance
- http://localhost:8000/api/cache
Visit http://localhost:8000/redoc and http://localhost:8000/swagger to see the documentation.
https://spec.openapis.org/oas/v3.0.2
The Openapi specification is used to generate the API documentation.
Update the openapi.yml
file and run pnpm build:docs
to update the API documentation.
The openapi.yml
file is used to generate the swagger.json
file for the Swagger documentation.
The script copy the current version of the openapi.yml
file for the documentation. Also copy all the assets.
The script generate the swagger.json
from the current openapi.yml
and copy the current version of the swagger.json
file for the documentation. Also copy all the assets.
serverless on ξ main [!?] is π¦ v1.0.0 via ξ v18.16.0 via π v3.0.0
β― node scripts/generateJWToken.mjs
header.payload.secret
https://vercel.com/docs/deployments/overview
Using the Node.js Runtime for Serverless Functions from Vercel. Use the "functions" field in vercel.json
to configure the serverless function entry point. The entry point must be moved to a api
subfolder.
{
"functions": {
"api/index.ts": {
"memory": 1024,
"maxDuration": 10,
"includeFiles": "{{src,public}/**,{src,public}/**/**,package.json,node_modules/{ajv,apicache,axios,compression,cors,dotenv,express,express-jwt}/**,node_modules/{ajv,apicache,axios,compression,cors,dotenv,express,express-jwt}/**/**,}",
"excludeFiles": "{src/**/*.test.ts,src/**/**/.test.ts}"
}
},
"trailingSlash": true,
"rewrites": [
{
"source": "/swagger/",
"destination": "/swagger/index.html"
},
{
"source": "/redoc/",
"destination": "/redoc/index.html"
},
{
"source": "/(.*)",
"destination": "api/index.ts"
}
]
}
Use "builds" instead of "functions" in vercel.json
. The entry point must be moved to the src
subfolder.
{
"builds": [
{
"src": "src/index.ts",
"use": "@vercel/node",
"config": {
"includeFiles": [
"src/**",
"public/**",
"package.json",
"node_modules/ajv/**",
"node_modules/apicache/**",
"node_modules/axios/**",
"node_modules/compression/**",
"node_modules/cors/**",
"node_modules/dotenv/**",
"node_modules/express/**",
"node_modules/express-jwt/**"
],
"excludeFiles": ["src/**/*.test.ts"]
}
}
],
"rewrites": [
{
"source": "/(.*)",
"destination": "src/index.ts"
}
]
}
However, in the legacy version, it is also possible to use a JavaScript file as entry point.
{
"builds": [
{
- "src": "index.ts",
+ "src": "dist/api/index.js",
"use": "@vercel/node",
"config": {
"includeFiles": [
- "**"
+ "dist/**"
]
}
}
],
"routes": [
{
"src": "/(.*)",
- "dest": "index.ts"
+ "dest": "dist/api/index.js"
}
]
}
But then you need to build the project first. And the dist
folder must be checked in.
This can be automated with a git pre-commit hook.
For example with the pnpm 'pre-commit' package.
That allow to add a pre-commit field in the package.json
"scripts": {
+ "build:add": "git add dist -f",
},
+ "pre-commit": [
+ "check",
+ "build",
+ "build:add"
+ ]
pnpm run vercel:generate
or
serverless on ξ main [!] is π¦ v1.0.0 via ξ v18.16.0 via π v3.0.0
β― node scripts/generateVercelJson.mjs
Generate vercel.json
Generate vercel.json include dependencies {{src,public}/**,{src,public}/**/**,package.json,node_modules/{ajv,apicache,axios,compression,cors,dotenv,express,express-jwt}/**,node_modules/{ajv,apicache,axios,compression,cors,dotenv,express,express-jwt}/**/**,}