How can I use files in Vercel Functions?

This guide will explain how to read files from Vercel Functions, both when used with frameworks like Next.js or standalone on Vercel. We’ll explain how bundling works, how you can tell Vercel to include additional files for use at runtime in your functions, and more.

How bundling application code works

Your application gets bundled during a build to include all necessary user code and dependencies needed for runtime.

Both Next.js and general Vercel Functions use Vercel’s Node File Trace to determine which files (including those in node_modules) are necessary to be included. This uses static analysis to inspect any import, require, and fs usage and determine all files that a page might load.

Examples of reading files

Using process.cwd()

We recommend using process.cwd() to determine the current directory of the Vercel Function instead of using __dirname. For example, this function reads the file users.json from the root of the repository.

api/file.js
import fs from 'fs';
import path from 'path';
export function GET(request) {
let usersPath = path.join(process.cwd(), 'users.json');
let file = fs.readFileSync(usersPath);
return new Response(file);
}

Using dynamic require

If you are trying to write your code using ES Modules, sometimes you might rely on CommonJS code. To dynamically require and include a function using CJS, you can write a function as follows:

api/file.js
import { createRequire } from 'node:module';
let sayHello = createRequire(import.meta.url)('../greet.cjs');
export function GET(request) {
return new Response(sayHello());
}

This function api/file.js is requiring greet.cjs, which is in the root of the repository.

greet.js
function sayHello() {
return 'Hello, World!';
}
module.exports = sayHello;

To test this locally, ensure your package.json is configured for ES Modules:

package.json
{
"type": "module"
}

Finally, to tell Vercel to include the greet.cjs file while bundling, modify vercel.json:

vercel.json
{
"functions": {
"api/file.js": {
"includeFiles": "greet.cjs"
}
}
}

Using Next.js

Since Next.js has its own build process which uses Node File Trace, you would use the built-in functionality of the framework to include additional files rather than vercel.json. The file path can be a glob to select multiple files.

next.config.js
module.exports = {
experimental: {
outputFileTracingIncludes: {
'/api/another': ['./necessary-folder/**/*'],
},
},
}

Further, sometimes if you are using a monorepo, you’ll have a different root directory for your application. To include files outside of that folder with Next.js, you can use:

next.config.js
module.exports = {
experimental: {
// includes files from the monorepo base two directories up
outputFileTracingRoot: path.join(__dirname, '../../'),
},
}

Using SvelteKit

SvelteKit uses Node File Trace and also supports the ability to read files. You do not need to modify vercel.json with this approach.

src/routes/read-file/+page.server.js
import { read } from '$app/server';
import users from './users.json';
export async function load() {
return {
users: await read(users).text()
};
}

Using Astro

Astro uses Node File Trace and also supports the ability to include or exclude files. You do not need to modify vercel.json with this approach.

astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server',
adapter: vercel({
includeFiles: ['./users.json'],
}),
});

Examples of writing files

If you are looking for a way to write files, we recommend persisting to object storage like Vercel Blob or similar solutions.

Couldn't find the guide you need?