Patrick Martin
Patrick Martin

Reputation: 55

Can I use @vercel/og without React?

I'm trying to create an API on Vercel which returns images, generated based on the request. I would like to use @vercel/og for this, because it can generate images from HTML, and it is very quick. However, it seems to require React, which seems entirely unnecessary for something serving no actual HTML at all.

I have an edge function in api/test.ts:

import { ImageResponse } from '@vercel/og';

export const config = {
    runtime: 'experimental-edge',
};

export default function () {
    return new ImageResponse({
        type: "div",
        props: {
            children: "Hello, World",
            style: {
                backgroundColor: "black",
                color: "white",
                width: "100%",
                height: "100%",
            }
        }
    }, { width: 500, height: 500 });
}

This runs completely fine when deployed to Vercel, but when I use vercel dev it gives me these errors:

Failed to instantiate edge runtime.
Invalid URL: ../vendor/noto-sans-v27-latin-regular.ttf
Error: Failed to complete request to /api/test: Error: socket hang up
node_modules/@vercel/og/dist/og.d.ts:1:35 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

1 import type { ReactElement } from 'react';
                                    ~~~~~~~

node_modules/satori/dist/index.d.ts:1:27 - error TS2307: Cannot find module 'react' or its corresponding type declarations.

1 import { ReactNode } from 'react';
                            ~~~~~~~

node_modules/satori/dist/index.d.ts:14:11 - error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

14     data: Buffer | ArrayBuffer;
             ~~~~~~


Found 3 errors.

There are two errors saying that @vercel/og and satori can't find React. Is there a way around this? I shouldn't need react for this, right?

Upvotes: 2

Views: 616

Answers (3)

jakubpelak
jakubpelak

Reputation: 81

I have created a simple example for generating open graph images with no react, no framework at all. Just one dependency:

https://www.jakubpelak.com/posts/vercel-og-card-no-framework

Sadly, as @hasparus mentioned, it currently does not run locally. However, I am currently getting a different error. I remember getting the same one before (font related). Then, a few months back, it has gotten fixed and code ran smoothly even on local machine. Not at this moment, thougn. Hopefully it gets fixed soon.

Upvotes: 0

josiahwiebe
josiahwiebe

Reputation: 151

You should be able to use it without React, but as @hasparus pointed out you won't be able to use JSX function.

I spent some time getting it to work, and encountered some of the same struggles getting it to work locally. Edge Functions simply don't seem to operate all that well with vercel dev.

I discovered an undocumented unstable_createNodejsStream function in the package, which I was able to get working both locally, and live on Vercel. I wrote about it on my website here, but here's the gist:

  1. import { unstable_createNodejsStream } from '@vercel/og'
  2. Update your handler to a default Node.js handler, i.e., export default async function (req, res) {}
  3. Write your HTML as a standard JS object in the expected JSX output format, use the custom h() function defined here by hasparus, or import { h } from 'preact' and write it in JSX format
  4. Create a new stream using unstable_createNodejsStream and pipe it to the response

Upvotes: 0

hasparus
hasparus

Reputation: 1324

I worked around the React-related errors and the inability to run .tsx edge functions without Next.js by installing @types/react and defining my own JSX function and using it without JSX syntax just in a .ts file.

function h<T extends React.ElementType<any>>(
  type: T,
  props: React.ComponentPropsWithRef<T>,
  ...children: React.ReactNode[]
) {
  return {
    type,
    key: "key" in props ? props.key : null,
    props: {
      ...props,
      children: children && children.length ? children : props.children,
    },
  };
}

After this you can run it in Vercel deployment preview.

However, in vercel dev locally, I'm still getting the following error.

Failed to instantiate edge runtime.
Invalid URL: ../vendor/noto-sans-v27-latin-regular.ttf
Error: Failed to complete request to /api/og: Error: socket hang up

I had also forced vercel CLI to use the newer TypeScript version with pnpm.overrides in package.json to solve some TypeScript parse errors I was getting.

Upvotes: 0

Related Questions