如何搭建简易Serverless Framework Monorepo(无Lerna等工具)
单仓库多Serverless服务搭建与Webpack依赖分离方案
你的思路完全可行——不依赖大型Monorepo工具,通过根目录统一管理共享依赖、服务目录隔离专属代码的方式,既能保持项目简洁,又能实现统一打包部署。以下是具体实现步骤:
一、项目初始化与目录搭建
1. 根目录初始化
# 创建项目根目录并初始化 mkdir serverless-mono && cd serverless-mono npm init -y # 安装所有共享开发/运行依赖 npm install --save-dev serverless serverless-compose typescript webpack webpack-cli serverless-webpack eslint prettier husky npm install --save aws-sdk # 若Lambda运行时已内置可改为--save-dev
2. 构建目标目录结构
手动创建或通过命令生成目录:
# 创建共享代码目录与服务目录 mkdir shared services/services-a services/services-b # 为每个服务创建核心文件 touch services/services-a/serverless.yml services/services-a/src/handler.ts touch services/services-b/serverless.yml services/services-b/src/handler.ts
最终目录结构与你规划的完全一致。
二、Serverless Compose 统一部署配置
在根目录创建serverless-compose.yml,定义所有服务的路径:
services: service-a: path: services/service-a # 可添加统一环境变量等全局配置 environment: NODE_ENV: ${sls:stage} service-b: path: services/service-b environment: NODE_ENV: ${sls:stage}
后续通过serverless deploy即可一键部署所有服务,或通过serverless deploy --service service-a单独部署指定服务。
三、Webpack 配置与依赖分离
核心目标:让Webpack打包时自动区分根目录共享依赖和服务专属依赖,避免重复打包冗余代码。
1. 根目录通用Webpack配置
创建webpack.config.js,配置如下:
const path = require('path'); const slsw = require('serverless-webpack'); const nodeExternals = require('webpack-node-externals'); module.exports = { entry: slsw.lib.entries, target: 'node', mode: slsw.lib.webpack.isLocal ? 'development' : 'production', externals: [ nodeExternals({ // 排除根目录共享的运行依赖(若需打包进服务则删除对应项) allowlist: ['aws-sdk'] }), // 排除Lambda内置依赖,避免打包 'aws-sdk' ], resolve: { // 优先从根目录node_modules找共享依赖,再找服务专属依赖 modules: [path.resolve(__dirname, 'node_modules'), './node_modules'], extensions: ['.ts', '.js'], // 配置共享代码别名,方便服务引用 alias: { '@shared': path.resolve(__dirname, 'shared') } }, module: { rules: [ { test: /\.ts$/, use: 'ts-loader', exclude: [/node_modules/, /services\/.*\/node_modules/] } ] }, output: { libraryTarget: 'commonjs2', path: path.resolve(__dirname, '.webpack'), filename: '[name].js' } };
2. 服务端Webpack插件配置
在每个服务的serverless.yml中引入serverless-webpack插件,并指向根目录配置:
service: service-a frameworkVersion: '3' plugins: - serverless-webpack custom: webpack: webpackConfig: '../../webpack.config.js' includeModules: false # 禁用自动打包node_modules,由我们手动控制 packager: 'npm' provider: name: aws runtime: nodejs20.x region: us-east-1 functions: hello: handler: src/handler.hello events: - httpApi: path: /hello method: get
3. 依赖分离关键操作
- 共享依赖:所有跨服务通用的开发工具(如typescript、webpack)和运行依赖(如axios、lodash)统一安装在根目录。
- 专属依赖:仅服务自身需要的依赖,通过指定
--prefix安装到对应服务目录:# 为service-a安装专属依赖stripe npm install stripe --save --prefix services/service-a
Webpack会自动识别服务目录的node_modules,将专属依赖打包进服务bundle,而共享依赖仅在必要时打包(或通过externals排除)。
四、配套工具配置
1. TypeScript 配置
根目录tsconfig.json覆盖所有服务与共享代码:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "outDir": "./dist", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { "@shared/*": ["shared/*"] } }, "include": ["shared/**/*", "services/**/src/**/*"], "exclude": ["node_modules", "services/**/node_modules"] }
2. 代码规范与提交钩子
- 根目录配置
.eslintrc.js和.prettierrc,自动覆盖所有服务目录。 - 初始化Husky钩子,确保提交代码前自动检查规范:
npx husky install npx husky add .husky/pre-commit "npx eslint . --fix"
思路验证
你的方案非常适合服务数量较少、追求轻量化的场景。唯一需要注意的是:若后续服务数量激增,共享运行依赖的重复打包会导致部署包体积增大,此时再考虑引入Turborepo等轻量Monorepo工具即可。当前方案无需额外学习成本,完全满足简洁性与统一性的需求。
内容的提问来源于stack exchange,提问作者Stepan Yudin
相关产品推荐
相关产品推荐

