We want to deploy to all the things. Write once, learn once, run everywhere.
Peter Pistorius - Deployment Targets tracking issue (August 8, 2020)
Phase 0 - Netlify
RedwoodJS was originally architected to run as a static frontend deployed on a CDN that sends requests to a serverless GraphQL handler. The GraphQL handler was first deployed on AWS Lambda via Netlify Functions. Despite all the jargon in the previous description, you can forget about most of those terms with the notable exceptions of frontend and GraphQL.
You can think about your Redwood application as consisting of a React frontend speaking to a Node backend that exposes a GraphQL API. For the initial v0.1 release of Redwood, the React frontend was hosted on Netlifyās CDN and the GraphQL API was hosted on a serverless Lambda handler via Netlify Functions.
However, thereās no inherent reason a Redwood app has to be deployed this way. This led many to wonder and others to experiment with different methods of deploying the frontend and API.
What does it take to deploy the redwood
api
part to AWS Lambda directly? I would like to take a shot at it.
We currently rely on Netlify to do the heavy lifting of deployment for us, but we intend to make it easy to write deployment providers that will allow deployment to a wide variety of services.
Tom Preston-Werner - Deploying to AWS Lambda (April 8, 2020)
Phase 1 - AWS Lambda cause I donāt want a server
The first adventurer sought to bypass Netlify Functions and deploy the API directly to AWS Lambda.
So I got the api part deployed and working on AWS lambda directly using serverless. I had to move some files around in the
dist
directory and also set the environment variables in AWS. I shall create an issue to discuss the changes.
Serverless Framework
On deploying to AWS lambda, we would get an api endpoint. This
api
endpoint would be needed within theweb
part in apollo client for the graphql queries.The build step would need the
api
to be built first, before theweb
, so the endpoint is known. Using serverless to deploy, the configserverless.yml
, which is at the root of the project.Jaikant - Support Deployments to AWS Lambda (April 14, 2020)
service: jai-redwood-1
plugins:
- serverless-dotenv-plugin
provider:
name: aws
runtime: nodejs12.x
region: ap-south-1
package:
artifact: zipball/graphql.zip
functions:
graphql:
description: redwood on aws lambda
memorySize: 1024
timeout: 30
handler: dist/functions/graphql.handler
events:
- http:
path: graphql
method: GET
cors: true
- http:
path: graphql
method: POST
cors: true
- http:
path: playground
method: ANY
cors: true
I tried this with the latest version of
zip-it-and-ship-it
for AWS Lambda and it seems to have worked out of the box. I did not have to make any changes to the zip folder and I usedhandler: graphql.handler
inserverless.yml
.I changed the one line in
serverless.yml
fromhandler: dist/functions/graphql.handler
tohandler: graphql.handler
sincegraphql.js
now lives in the root of the zipball.Hemil Desai - Support Deployments to AWS Lambda (August 8, 2020)
yarn rw setup deploy aws-serverless
Iāve just chatted with @hemildesai and weāve come up with some concrete steps for adding AWS deployments using the serverless framework.
Introduce a deploy command:
yarn rw deploy api aws-serverless
- runs
yarn build api
, built files are in./api/dist
- runs zip it and ship it, placing the files in
./api/dist/
- runs serverless deploy
Peter Pistorius - Support Deployments to AWS Lambda (August 19, 2020)
yarn rw setup deploy aws-serverless
service: app
plugins:
- serverless-dotenv-plugin
provider:
name: aws
runtime: nodejs12.x
region: us-east-2
httpApi:
cors: true
payload: '1.0'
stackTags:
source: serverless
name: Redwood Lambda API with HTTP API Gateway
tags:
name: Redwood Lambda API with HTTP API Gateway
package:
individually: true
functions:
graphql:
description: graphql function deployed on AWS Lambda
package:
artifact: api/dist/zipball/graphql.zip
memorySize: 1024
timeout: 25
tags:
endpoint: /.redwood/functions/graphql
handler: graphql.handler
events:
- httpApi:
path: /.redwood/functions/graphql
method: GET
- httpApi:
path: /.redwood/functions/graphql
method: POST
Phase 2 - PM2 cause I want a server
Do you prefer hosting Redwood on your own server, the traditional serverful way, instead of all this serverless magic? Well, you can! In this recipe we configure a Redwood app with PM2 and Nginx on a Linux server.
Nick Geerts - Add serverfull hosting recipe to cookbook (October 24, 2020)
With the deploy aws-serverless
command, developers now had the ability to drop down to the underlying AWS Lambdas and were no longer reliant on Netlify Functions. This may have looked like it was presaging a stronger push towards a wider array of serverless function providers.
But the exact opposite happened, the next investigation involved leaving the serverless world behind entirely. Despite their appeal from a DX perspective, larger Redwood applications hosted on AWS Lambda experienced noticeable cold starts or exceeded the maximum allotted memory for their handler.
And for some developers running a server is not challenging or foreign, it is familiar and simple.
Iām a freelancer and have a lot of smaller clients and host my own Linux server with node.js instances in PM2 with a reverse proxy in Nginx. I was looking into deploying an example Redwood app to my own Linux server. When I build the project, the
web/dist
output is simple enough - just files to host in Nginx (yay JAMstack!).However, how can I host the function artifacts in
api/dist
? Do these conform to a spec like the serverless framework and how can I deploy them to PM2? Or do I need to use something like OpenFAAS or the Fn Project?
pm2.config.js
I have a working example!
Live site: http://redwood-pm2.nickgeerts.com
Repo: GitHub - njjkgeerts/redwood-pm2: Redwood.js serverfull hosting with PM2
const name = 'redwood-pm2'
const repo = 'git@github.com:njjkgeerts/redwood-pm2.git'
const user = 'deploy'
const path = `/home/${user}/${name}`
const host = 'example.com'
const port = 8911
const build = `yarn install && yarn rw build && yarn rw prisma deploy`
module.exports = {
apps: [
{
name,
node_args: '-r dotenv/config',
cwd: `${path}/current/`,
script: 'yarn rw serve api',
args: '--port ${port}',
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
},
},
],
deploy: {
production: {
user,
host,
ref: 'origin/master',
repo,
path,
ssh_options: 'ForwardAgent=yes',
'post-deploy': `${build} && pm2 reload pm2.config.js --env production && pm2 save`,
},
},
}
Server-less or Server-more?
āServerfullā makes sense in the context of Serverless, but to the best of my knowledge, itās not a well-known term (yet). So when people are browsing the left column navigation docs, or using the site search, is there anything we can add to help others find this document and identify immediately with the topic. Some ideas:
- Server hosting
- Traditional or classic server architecture
- Self-hosting Redwood
- Hosting Redwood without serverless or docker containers
David Price - Add serverfull hosting recipe to cookbook - (October 26, 2020)
Phase 3 - Render cause I want only one dashboard
render.com looks the same like netlify to me but comes with a way of having postgresql database, is that not a better choice in the tutorial section as deployment target?
Guled - Using render.com instead of Netlify and Heroku (June 10, 2020)
As more Redwood apps have been deployed to production, weāve seen developers place a great emphasis on having their:
- Redwood API running on a server
- Build process and infrastructure provisioning defined in code
- Frontend, API, and database all hosted on the same provider
api-server
RedwoodJS is architected as monorepo with two separate sides, an āapi sideā and a āweb side.ā The api side is a NodeJS application and the web side is a static SPA (single page app).
This works out great when hosting on Render because hosting a static site is free, and static content is served via super-fast CDN. So weāre going to setup two sides on Render.com, but first you need to add some things to your RedwoodJS project.
Install the
api-server
in your api side.cd api yarn add @redwoodjs/api-server
Create a āhealthā function used by Render to check if your api side is running correctly.
// api/src/functions/healthz.js export const handler = async () => { return { statusCode: 200 } }
On Render, create a new āweb serviceā:
- Connect to your repository
- Environment is
Node
- Build:
yarn && yarn rw prisma migrate deploy && yarn rw build api
- Start:
cd api && yarn rw-api-server --port 80
- Use custom domain: āapi.raccoon.tradeā
On Render create a new āstatic siteā:
- Build:
yarn && yarn rw build web
- Publish:
./web/dist
- Add rewrite and redirect rules
Peter Pistorius - Using render.com instead of Netlify and Heroku (March 15, 2021)
yarn rw setup deploy render
Perfect. Weāll set up a render.yaml and make this easier. Stay tuned!
Anurag Goel - Using render.com instead of Netlify and Heroku (March 15, 2021)
The PR adds a command to the Redwood CLI to automatically configure project for deployment to Render.
Sean Doughty - Adding Setup Deploy Render Command (March 25, 2021)
yarn rw setup deploy render
services:
- name: history-hosting-test-web
type: web
env: static
buildCommand: yarn rw deploy render web
staticPublishPath: ./web/dist
envVars:
- key: NODE_VERSION
value: 14
routes:
- type: rewrite
source: /.redwood/functions/*
destination: replace_with_api_url/*
- type: rewrite
source: /*
destination: /index.html
- name: history-hosting-test-api
type: web
env: node
region: oregon
buildCommand: yarn && yarn rw build api
startCommand: yarn rw deploy render api
envVars:
- key: NODE_VERSION
value: 14
- key: DATABASE_URL
fromDatabase:
name: history-hosting-test-db
property: connectionString
databases:
- name: history-hosting-test-db
region: oregon
Phase 4 - Still in progress
Is this deployment machine truly universal? That depends of course on your definition of universality. If you want to universally deploy to AWS, youāre covered. However, other major cloud providers have proved more difficult.
Google Cloud Run
Adding setup and deploy functionality for firebase hosting for web, with Cloud Run for API.
Benjamin Coe - Adding support for GCP project generation (September 26, 2020)
Azure
Iām not sure which direction this will take (The Serverless Framework vs maintaining deployment providers in Redwood) but here is some Azure specific on the topic.
Azures equivalent to AWSās Lambda and S3 is Azure Functions and Azure Storage. If the deployment would utilize Git deployment to the fullest, would there be any need for a storage account/bucket?
Johan Eliasson - Support Deployments to AWS Lambda (July 7, 2020)
Azure Static Web Apps
Iāve been tinkering Azure Static Web Apps, which would not only host the API side (via Azure Functions), but also the front-end. I donāt think function-only deployment would be too far off though.
Kim-Adeline Miguel - Deployment Targets tracking issue (September 7, 2020)
Azure Functions
I am working on hacking together a solution to run Redwood on Azure using Azure Functions.
My approach so far is to vendor the
API
package into a Redwood project:redwood-azure
and replace the code that generates Lambdas with code that generates Azure Functions. I have started this process by unpacking and attempting to grok some of theAPI
package in my own fork of this repo. The branch is called āblueskyā because āAzureā ha ha.If I can get my hacked and vendored API package working in the Redwood solution, then I can approach the core maintainers with questions of architecture and implementation. AFAIK, there will have to be some flag to tell the API package whether it should compile to Azure Functions or Lambdas.
With the final implementation, I want to limit the variance between the Lambda producing code and the Functions producing code. This will require me to gain a better understanding of the
API
package.Still early days.
Here is a link to the beginning of my vendored āhack-apiā.
Thomas Eckert - Deployment Targets tracking issue (April 6, 2021)
Cloudflare
Can I deploy the redwood app to the cloudflare page?
Muhammad Rusdi - Deploy Redwoodjs with Cloudflare Page (March 3, 2021)
Such a simple question with such a long and complicated answer.
A Cloudflare Worker is JavaScript you write that runs on Cloudflareās edge. A Cloudflare Service Worker is specifically a worker which handles HTTP traffic and is written against the Service Worker API. Cloudflare Pages is a deployment platform for frontend developers modeled on Netlify and Vercel.
Sounds cool but remember that part about Redwood being a Node app?
Hi @muhrusdi. To the best of my knowledge, no one has tried to deploy Redwood on Cloudflare. Personally, I am a big fan of their products. However, their alternative to AWS Lambdas, which is Cloudflare Workers, is a V8 runtime, which is not the same as a Node.js runtime.
This means the Redwood API will most likely not run on Cloudflare Workers. In the case of a very simple app, it might be fine. But once you add things like Prisma Client itās almost sure to fail.
If you wanted to run an experiment, you could try to deploy Redwoodās Web side to Cloudflareās CDN and the API site directly to AWS Lambdas using these instructions for a Redwood AWS deploy target.
David Price - Deploy Redwoodjs with Cloudflare Page (March 4, 2021)
Prisma is currently out of the question
The potential gotchas that keep me from trying:
- Prisma binary hates v8 runtime
- Some random dependency in
@redwoodjs/api
hates v8 runtime- Auth provider packages hate v8 runtime
- Misc API package dependencies used by random Redwood Project X hate v8 runtime
In general, I foresee it being frustrating if my local dev environment spins up the API in a Node runtime so itās not until I get to deployment that things break, which is then difficult to diagnose.
So Iād suggest starting with local dev for experimentation ā I have ZERO knowledge here:
- Is it possible to spin up a local v8 runtime for dev?
- Does babel/esbuild support it?
If we canāt do something like this, then Iām not optimistic about creating a workable, um, workflow [Editorās note: lol] regardless of being able to spin up a test app on Cloudflare using Workers.
Workers do NOT support Node.js.
I believe we can transpile code to the JavaScript version we need. But we canāt control the other dependencies (and their dependencies), which may or may not have Node.js specific requirements + dependencies.
Iāll be cheering you on. But hereās your first roadblock.
David Price - Running RedwoodJS on Cloudflare Workers (April 7, 2021)
WASM, it practically cures cancer!
You can specify a web worker output target. But youāre not wrong about various dependencies using non-web worker-friendly methods. An immediate example I can give you there is validation libraries on workers.
Wrangler wonāt currently support a WASM build target, and workers donāt currently support TCP - sooooooooo, this is a hard blocker for anything Prisma related.
Matt Sutkowski - Running RedwoodJS on Cloudflare Workers (April 7, 2021)
Deploy just Redwood-Worker-Functions to Cloudflare?
So maybe we have limitations. BUT it would still be rad to know what Workers are good at and what we could use them for. Imagine a Redwood App that takes advantage of a hybrid cloud infrastructure:
- Cloudflare CDN + Networking (DNS)
- Specific Redwood-Worker-Functions deployed to Cloudflare
- Other parts of API deployed to AWS Fargate container for persistence
I donāt know why weād do this. But itās possible.
ĀÆ\_(ć)_/ĀÆ
I do think thereās a lot of value we could unlock in Cloudflare Key/Value and Durable Objects when it comes to performance + caching. Just donāt know what the ROI would be on trying to figure out how to piece it all together.
David Price - Running RedwoodJS on Cloudflare Workers (April 7, 2021)
Cache rules everything around me
I too very much doubt that Prisma+Cloudflare will happen. Those two products just seem so out of sync, why globally distribute your workers, but then connect to a single database.
I think caching is probably the immediate answer, probably on the API-level. Maybe you have an API thatās exposed via GraphQL, but thatās cached globally. Thenā¦ you donāt really need global workers, just global varnish.
Peter Pistorius - Running RedwoodJS on Cloudflare Workers (April 7, 2021)