A Serverless monorepo starter that uses Lerna and Yarn Workspaces.
- Designed to scale for larger projects
- Maintains internal dependencies as packages
- Uses Lerna to figure out which services have been updated
- Supports publishing dependencies as private NPM packages
- Uses serverless-bundle to generate optimized Lambda packages
- Uses Yarn Workspaces to hoist packages to the root
node_modules/directory
To create a new Serverless project
$ git clone https://github.com/AnomalyInnovations/serverless-lerna-yarn-starter my-projectEnter the new directory
$ cd my-projectInstall NPM packages for the entire project
$ yarnThe directory structure roughly looks like:
package.json
/libs
/packages
/sample-package
index.js
package.json
/services
/service1
handler.js
package.json
serverless.yml
/service2
handler.js
package.json
serverless.yml
This repo is split into 3 directories. Each with a different purpose:
-
packages
These are internal packages that are used in our services. Each contains a
package.jsonand can be optionally published to NPM. Any changes to a package should only deploy the service that depends on it. -
services
These are Serverless services that are deployed. Has a
package.jsonandserverless.yml. There are two sample services.service1: Depends on thesample-package. This means that if it changes, we want to deployservice1.service2: Does not depend on any internal packages.
More on deployments below.
-
libs
Any common code that you might not want to maintain as a package. Does NOT have a
package.json. Any changes here should redeploy all our services.
The packages/ and services/ directories are Yarn Workspaces.
The Serverless services are meant to be managed on their own. Each service is based on our Serverless Node.js Starter. It uses the serverless-bundle plugin (based on Webpack) to create optimized Lambda packages.
This is good for keeping your Lambda packages small. But it also ensures that you can have Yarn hoist all your NPM packages to the project root. Without Webpack, you'll need to disable hoisting since Serverless Framework does not package the dependencies of a service correctly on its own.
Install an NPM package inside a service.
$ yarn add some-npm-packageRun a function locally.
$ serverless invoke local -f getRun tests in a service.
$ yarn testDeploy the service.
$ serverless deployDeploy a single function.
$ serverless deploy function -f getTo add a new service.
$ cd services/
$ serverless install --url https://github.com/AnomalyInnovations/serverless-nodejs-starter --name new-service
$ cd new-service
$ yarnSince each package has its own package.json, you can manage it just like you would any other NPM package.
To add a new package:
$ mkdir packages/new-package
$ yarn initPackages can also be optionally published to NPM.
To use a package:
$ yarn add [email protected]Note that packages should be added by specifying the version number declared in their package.json. Otherwise, yarn tries to find the dependency in the registry.
If you need to add any other common code in your repo that won't be maintained as a package, add it to the libs/ directory. It does not contain a package.json. This means that you'll need to install any NPM packages as dependencies in the root.
To install an NPM package at the root.
$ yarn add -W some-npm-packageWe want to ensure that only the services that have been updated get deployed. This means that, if a change is made to:
-
services
Only the service that has been changed should be deployed. For ex, if you change any code in
service1, thenservice2should not be deployed. -
packages
If a package is changed, then only the service that depends on this package should be deployed. For ex, if
sample-packageis changed, thenservice1should be deployed. -
libs
If any of the libs are changed, then all services will get deployed.
To implement the above, use the following algorithm in your CI:
- Run
lerna ls --since ${prevCommitSHA} -allto list all packages that have changed since the last successful deployment. If this list includes one of the services, then deploy it. - Run
git diff --name-only ${prevCommitSHA} ${currentCommitSHA}to get a list of all the updated files. If they don't belong to any of your Lerna packages (lerna ls -all), deploy all the services. - Otherwise skip the deployment.
Seed supports deploying Serverless monorepo projects that use Lerna and Yarn Workspaces. To enable it, add the following to the seed.yml in your repo root:
check_code_change: lernaTo test this:
Add the App
- Fork this repo and add it to your Seed account.
- Add both of the services.
- Deploy your app once.
Update a Service
- Make a change in
services/service2/handler.jsand git push. - Notice that
service2has been deployed whileservice1was skipped.
Update a Package
- Make a change in
packages/sample-package/index.jsand git push. - Notice that
service1should be deployed whileservice2will have been skipped.
Update a Lib
- Finally, make a change in
libs/index.jsand git push. - Both
service1andservice2should've been deployed.
This repo is maintained by Serverless Stack.