redwoodjs / redwood

The App Framework for Startups
https://redwoodjs.com
MIT License
16.94k stars 974 forks source link

Using file access for Vercel deployment #1664

Open viperfx opened 3 years ago

viperfx commented 3 years ago

Problem

When using libraries that need file access, there is no supported way to do this with Vercel + Redwood. Typically the use case here is templating libraries that initialize with a template directory of files, which the serverless functions need access to.

Attempts to make this work

Using the following vercel config option - https://vercel.com/knowledge/how-can-i-use-files-in-serverless-functions. By including the following vercel.json config

{
    "functions": {
        "api/src/functions/*.js": {
             "includeFiles": "api/src/templates/**"
        }
     }
}

However, you get an error. I've tried many different patterns but they all seem to fail with the following message

Error: The pattern "api/src/functions/*.js" defined infunctionsdoesn't match any Serverless Functions inside theapidirectory. Learn More: https://vercel.link/unmatched-function-pattern

The following repo can be used to reproduce the issue - https://github.com/viperfx/redwood-fs-vercel-bug

Vercel's response

After getting in touch with Vercel, and providing them with a repo to reproduce the issue, eventually, I got a reply from an engineer.

Checking this issue with one of our engineers, Vercel can't support "includeFiles" with Redwood at the moment. The way Redwood is configured is that it will bundle the dependencies together and all required files at build-time. Requiring a file at runtime will not work unless the file is also bundled in the function at the build-phase.

Checking the Redwood documentation and code-base, it appears you can't run this code either on AWS Lambda or Netlify, as it is a framework limitation.

References

Known workaround for Netlify - https://community.redwoodjs.com/t/how-can-i-read-and-bundle-a-non-js-or-ts-file-from-my-netlify-function/1021/11

thedavidprice commented 3 years ago

@peterp @dthyresson any suggestions about this one?

dthyresson commented 3 years ago

I've chatted with @viperfx is Discord at it was I who referred him to the

Known workaround for Netlify - https://community.redwoodjs.com/t/how-can-i-read-and-bundle-a-non-js-or-ts-file-from-my-netlify-function/1021/11

that will inject the included file into the function zip created by Netlify's zip-it-and-ship it build process.

zip -ur ${FUNCTIONS_DIST}/graphql.zip ./email/src/templates

It literally adds a file into the archive.

As Vercel notes:

Requiring a file at runtime will not work unless the file is also bundled in the function at the build-phase.

And that's what that workaround does in the build plugin ... and what would have to be solved in a general way during any deploy.

But, right now I don't have a solution in mind.

thedavidprice commented 3 years ago

Are there any frameworks that provide this functionality in some way?

Tobbe commented 3 years ago

Would it be possible to override the default build command to inject an extra script right after yarn rw build?

image

This script could place files in /dist/functions. Would that work?

dthyresson commented 3 years ago

Would it be possible to override the default build command to inject an extra script right after yarn rw build?

Actually, @Tobbe and @viperfx I think that's worth a try -- after build:

zip -ur /dist/functions/graphql.zip ./email/src/templates

dthyresson commented 3 years ago

@viperfx Did the zip -ur /dist/functions/graphql.zip ./email/src/templates approach solve this deploy scenario? If so, perhaps we can close. Thanks!

viperfx commented 3 years ago

I was not able to do this within vercel - it did not seem possible at least. I tried various things and eventually just ended up using templated strings. I now use self-hosting, so I won't really have these file access issues anymore.

krinoid commented 3 years ago

I've tried using the zip workaround on Vercel but it doesn't work due to the zip not being available during build:

image

I can imagine that one can create a node script to do this during build, but I'm exploring other potential solutions/workarounds for my case.

jmcmullen commented 3 years ago

Installing zip with yum works on Vercel but I don't think the functions are zipped up after build.

00:24:39.960 | zip warning: dist/functions/graphql.zip not found or empty
-- | --
00:24:39.960 | zip I/O error: No such file or directory
00:24:39.960 | zip error: Could not create output file (dist/functions/graphql.zip)
00:24:39.972 | Error: Command "yum install zip && yarn rw deploy vercel && zip -ur dist/functions/graphql.zip ./email/src/templates" exited with 15
aaronvanston commented 1 year ago

Any updates on this item?

We need access to functions as to change some of the configurations for the memory size. We're hitting the limit for the Vercel function on some of our larger calls. We're looking to optimise, but we need a stop-gap solution ASAP to make sure we can bump our memory size up in Vercel. Currently impacting production users where some calls timeout/ return 500.

dthyresson commented 2 weeks ago

Any updates on this item?

We need access to functions as to change some of the configurations for the memory size. We're hitting the limit for the Vercel function on some of our larger calls. We're looking to optimise, but we need a stop-gap solution ASAP to make sure we can bump our memory size up in Cercel. Currently impacting production users where some calls timeout/ return 500.

Happy to say @aaronvanston that after falling through cracks, we worked with Vercel for a fix. see: https://github.com/redwoodjs/redwood/pull/10891

You'll be able to configure function settings via:

Functions

By default, API requests in Vercel have a timeout limit of 15 seconds, but can be configured to be up to 90 seconds. Pro and other plans allow for longer duration and larger memory-size limits.

To change the maxDuration or memory per function, export a config with the settings you want applied in your function. For example:

import type { APIGatewayEvent, Context } from 'aws-lambda'

import { logger } from 'src/lib/logger'

export const config = {
  maxDuration: 30,
  memory: 512,
}

export const handler = async (event: APIGatewayEvent, _context: Context) => {
  logger.info(`${event.httpMethod} ${event.path}: vercel function`)

  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      data: 'vercel function',
    }),
  }
}

Just waiting for Vercel up publish an update to their redwood build handler.