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.jsonscript 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.secrethttps://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:generateor
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}/**/**,}