Skip to content

Instantly share code, notes, and snippets.

@PierBover
Last active February 7, 2023 09:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save PierBover/154475dda7567546997a5ae2ed684e5d to your computer and use it in GitHub Desktop.
Save PierBover/154475dda7567546997a5ae2ed684e5d to your computer and use it in GitHub Desktop.
Using Svelte in a Vercel serverless function

Using Svelte in a Vercel serverless function

The easiest way of using Svelte for SSR in Node is by using svelte/register. This allows to require .svelte files without any bundling and render HTML, CSS, etc.

This is the example from the docs:

require('svelte/register');

const App = require('./App.svelte').default;

const { html, css, head } = App.render({ answer: 42 });

If you do this in a Vercel serverless function it will work great locally while using vercel dev. However, once you deploy your function, it will break.

I'm not a Vercel expert, but this is how I've solved it.

1. Import the complete svelte package

It seems Vercel does some optimizations to reduce the size of the deployed functions so that only the required dependencies are bundled. It seems when doing require('svelte/register') Vercel will not bundle the complete svelte module and only the svelte/register folder. You function will break with this error:

Cannot find module '/var/task/node_modules/svelte/internal/index.js'

The solution is to do a dumb require of the whole module so that it gets bundled with your function:

require('svelte');
require('svelte/register');

2. Include all the .svelte files

Vercel will include all the .svelte files that you require in your functions, but it will ignore all the subsequent imports in your .svelte files. Svelte sub components that are not directly required in your serverless functions will not be bundled and your function will break.

The solution is simply to use the includeFiles directive in your vercel.json file:

{
  "functions": {
    "api/svelte-render.js": {
      "includeFiles": "api/_svelte/**"
    }
  }
}

Example Vercel serverless function

require('svelte');
require('svelte/register');

const Page = require('./_svelte/Page.svelte').default;

module.exports = async (request, response) => {

  const { html, css, head } = Page.render({});


  const fullHtml = `
    <!DOCTYPE html>
    <html>
    <body>
      ${html}
    </body>
    </html>
  `;

  response.setHeader('content-type', 'text/html; charset=UTF-8');
  response.send(fullHtml);
}
@leerob
Copy link

leerob commented Sep 23, 2021

Any reason not to just use SvelteKit? This works zero-config 😄

https://vercel.com/changelog/sveltekit-projects-can-now-be-deployed-with-zero-configuration

@PierBover
Copy link
Author

PierBover commented Sep 23, 2021

@leerob SvelteKit is not ready for production yet and it's overkill if you just need to render HTML.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment