Search code examples
javascriptserverlessvitevercel

Why are imported modules on serverless functions undefined?


TL;DR - why do imports return undefined? Especially for native Node modules like path?

I have a very small test application, built with Vite, that has a single endpoint in the /api directory. I created this just to play around with Vite + Vercel.

I have only 2 module imports for my endpoint - path and fs-extra. Both are returning as undefined. I was getting cannot read join of undefined errors with the path module, so I wrapped everything in a try/catch just to see if the endpoint responds. It does. See my code below.

import type {VercelRequest, VercelResponse} from '@vercel/node'
import path from 'node:path' // I've also tried 'path'
import fs from 'fs-extra'

export default function handler(req: VercelRequest, res: VercelResponse) {
  // Both of these log 'undefined' on my Vercel dashboard for function logs.
  console.log('path module:', path)
  console.log('fs module:', fs)

  try {
    // https://vercel.com/guides/how-can-i-use-files-in-serverless-functions
    const pathFromProjectRootToFile = '/api/usersData.json'
    const usersDataFilePath = path.join( // THIS IS WHERE THE ERROR HAPPENS 🙃
      process.cwd(),
      pathFromProjectRootToFile
    )
    const usersData = fs.readJSONSync(usersDataFilePath)
    res.json({users: usersData})
  } catch (e) {
    res.json({error: errorToObject(e as Error)})
  }
}

function errorToObject(err?: Error): Record<string, string> | null {
  if (!err || !(err instanceof Error)) return null

  const obj: Record<string, string> = {}

  Object.getOwnPropertyNames(err).forEach(prop => {
    const value = err[prop as keyof Error]

    if (typeof value !== 'string') return

    obj[prop] = value
  })

  return obj
}

As an aside, instead of node:path I also tried just path, but same thing - undefined. And I do have fs-extra as a dependency in my package.json.


Solution

  • When deploying a Vite app on Vercel and utilizing the /api directory for a back end with Serverless Functions, Node modules need to be imported via require, not import. The import syntax works for types and local modules. See this answer (and conversation) in Vercel's community discussions.

    import type {VercelRequest, VercelResponse} from '@vercel/node'
    import localModule from '../myLocalModule'
    
    const path = require('path')
    const fsOriginal = require('fs')
    const fs = require('fs-extra')
    
    // Rest of the file here...