Serverless FrameworkでmonorepoのtRPCをデプロイする
前提
Yarn Workspacesを使ってMonorepo環境を構築し、Sub PackageのapiをServerless Frameworkを使ってAWS Lambdaにデプロイします。
.
├── apps
│ ├── api
│ │ ├── index.ts
│ │ └── serverless.yml
│ └── web
└── package.json
Monorepo環境でServerless Frameworkをデプロイする場合、一部のパッケージはルートディレクトリのnode_modulesにホイストされ、Serverless Frameworkの最終的な.zipファイルに含まれないという問題があります。
Serverless Plugin Monorepoを使うことで、Yarn Workspacesからホイスト機能を無効にせずにこの問題を解決することができます。
Serverless Frameworkのpluginsは上から順番にロードされるため、Serverless Plugin Monorepoはpluginsのできるだけ上の方に定義する方が良いでしょう。依存関係によりますが、ローカルのnode_modulesには存在するが成果物の.zipファイルには含まれず、Cannot find module '***'
というエラーがAWS Lambdaで発生する場合があります。
Serverless Framework Load Order
Serverless FrameworkでtRPCの設定
エントリーポイントのindex.tsは以下のように記述しています。AWS LambdaでExpressのようなhttpをルーティングするためにはserverless-httpが必要です。
import express from 'express';
import * as trpcExpress from '@trpc/server/adapters/express';
import cors from 'cors';
import dotenv from 'dotenv';
import { createContext } from './trpc';
import serverless from 'serverless-http';
import { appRouter, AppRouter } from './router/_app';
const app = express();
app.use(cors());
dotenv.config();
const port = process.env.PORT || 8080;
app.use(
'/trpc',
trpcExpress.createExpressMiddleware({
router: appRouter,
createContext,
})
);
app.get('/', (req, res) => {
res.send('Hello World!!');
});
app.listen(port, () => {
console.log(`server listening at http://localhost:${port}`);
});
export const handler = serverless(app);
export { AppRouter };
最終的なserverless.yml
は以下のようになります。
自分の環境ではnode_mosulesの.prisma
がルートディレクトリに含まれてしまったため、Error: Cannot find module '.prisma/client/index'
というエラーが出ました。そのためpatterns
でルートディレクトリの.prisma
フォルダを含めるようにしています。
service: trpc-lambda
plugins:
- serverless-plugin-monorepo
- serverless-dotenv-plugin
- serverless-plugin-typescript
- serverless-plugin-common-excludes
- serverless-plugin-include-dependencies
provider:
name: aws
region: ap-northeast-1
runtime: nodejs16.x
functions:
trpc:
handler: index.handler
events:
- http:
method: ANY
path: /{proxy+}
package:
excludeDevDependencies: false
patterns:
- '!node_modules/prisma/libquery_engine-*'
- 'node_modules/@prisma/client/**/*'
- '!node_modules/@prisma/engines/**'
- '../../node_modules/.prisma/**/*'
- '!../../node_modules/.prisma/client/libquery_engine-*'
- '../../node_modules/.prisma/client/libquery_engine-rhel-*'
参考
Serverless Framework - Plugins
Setup Monorepo via Yarn workspace for Serverless Framework and Expo with Typescript
Electron-Prisma Error: can not find module '.prisma/client'
Deployed appsync code can't find node_module even if present in the .serverless package
Discussion