Skip to content

Cookbook

jimmyfnugent edited this page Jan 29, 2022 · 15 revisions

Bookkeeping

Serverless console: https://platform.serverless.com/services/jimmyfnugent/smashbits/dev

Serverless function: https://platform.serverless.com/services/jimmyfnugent/smashbits/dev?serviceShareToken=e0d9d24500e91b4209131d7c442d48ce8266e2c69218ba12a4003c3bde11d78e

AWS Lambda: https://console.aws.amazon.com/lambda/home?region=us-east-1#/functions

MongoDB Atlas console: https://cloud.mongodb.com

Local development

Client

npm run start

This starts the React app on port 8080. It automatically knows to look for the server on port 3001 if it’s a local run.

You can tell the client to use fake data instead of hitting the local server by changing the USE_FAKE_API_CLIENT flag in client/.env. Unfortunately, even a local dev server currently needs to hit the actual test Mongo instance (more on that below), so to avoid hitting our QPS threshhold, using fake data might be a good idea if it doesn't get in your way. FYI, you might want to tell git to ignore changes to the .env file:

git update-index --skip-worktree client/.env

You can always undo this with git update-index --no-skip-worktree client/.env.

Debugging

We recommend using VSCode, which, in addition to being a nice code editor, also has some good debugging tools for TypeScript. (Without these, you'll be left debugging the generated JS in Chrome Debug Tools, which is fine but probably more annoying.) To do this, follow these instructions. Here's a sample launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Launch Chrome against localhost",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}/client"
    }
  ]
}

Server

npm run debug

This lets you debug with chrome://inspect -> DevTools for Node. It’ll wait for you to open dev tools to actually start the server, which will be on port 3001, and will automatically insert a breakpoint on the first line. The server code gets compiled by Webpack, which you can find in DevTools by Ctrl + P'ing for server/.webpack/service/index.js. (Sometimes it's not indexed, in which case, just put a debugger; statement somewhere in the codepath and it should hit that.)

We currently have an issue in which Mongo can get overwhelmed with too many simultaneous connections; this stems from serverless-offline treating every request like a fresh start of the serverless function, which doesn't match prod behavior. This means that every local request starts a new Mongo connection and doesn't clean up the old ones until they naturally expire. The problem is particularly acute when combined with client hot reloading, which means that every time you save a client change, the React tab reloads and another serverless request is made (and hence another Mongo connection established). If we get to 100 concurrent DB connections, Mongo will refuse all further requests for a bit. To get around this, there are two options:

  • Change the USE_FAKE_CLIENT flag in client/src/api_client.js to true, which intercepts remote calls and responds with fake test data. You can do this while developing on the client, and then set it back to false for some brief end-to-end validation.
  • Pass the --skipCacheInvalidation flag when starting serverless-offline, which causes it to reuse the Node cache on subsequent requests, but may or may not disable hot reloading (see here).

We recommend Advanced REST Client for issuing requests to the server for development.

Database

Currently we have local builds editing the deployed test Mongo database, though we're looking into a nicer way to play with a local Mongo instance (you're welcome to install mongodb locally yourself and try it). For the Serverless function to access MongoDB Atlas, you need an API key; ping TheNuge to get it. The Node code looks for the store URI for different stages (e.g. dev, prod) under server/secret/config.$STAGE.yml, e.g:

> cat server/secret/config.dev.yml
storeUri: mongodb+srv://$USER:$PASSWORD@$MONGO_URI

Linting

We're using ESLint for our linting and formatting. The server and client each have their own .eslintrc (because they're different npm projects), which define our code styling rules. If you're using VSCode, we recommend installing the ESLint plugin and setting it to format on save. You can also run it as a CLI from server/ or client/ with npx eslint, or add a --fix flag to have it automatically do some formatting.

Environments & deploys

Client

We have AWS Amplify set up to import Github branches and automatically deploy them to new SmashBits subdomains. For example, if you open a PR on branch my-cool-feature, Amplify will deploy your client code to https://my-cool-feature.smashbits.dev (which will be password gated).

We have two long-lived branches: development and master. Merging to development auto-deploys to https://development.smashbits.dev, and merging to master auto-deploys to https://smashbits.dev. Individual PRs should be merged into development by default! We do infrequent, manual merges to master.

Some client behavior is controlled by Amplify "environment variables" (not to be confused with command-line environment variables). These are listed in amplify.yml and controlled from the Amplify console. They can be overridden on a per-branch basis.

Server

We have two Serverless stages: dev and prod. You can deploy to one with serverless deploy --stage prod (or dev, which is the default). The stages connect to different databases (see below). Any prod deploy will immediately be visible in the production app.

Unlike on the client, we don't have Amplify auto-pushing merged branches, so the deploy step is manual.

Although the server code doesn't use Amplify, we have similar configuration via "environment variables", courtesy of Lambda. These are listed in serverless.yml, and there's more documentation about how to change them here. Note that these override the values in /secret/config.{stage}.yml!

Database

There are two Mongo Atlas databases: test and prod. These correspond to the dev and prod stages of the Serverless apps, respectively.

Clone this wiki locally